Skip to content

feat(daemon): Ollama backend wiring — settings + selector + UI (v0.1.1)#68

Merged
OpenCircuitDev merged 4 commits into
mainfrom
feat/ollama-daemon-wiring
Jun 11, 2026
Merged

feat(daemon): Ollama backend wiring — settings + selector + UI (v0.1.1)#68
OpenCircuitDev merged 4 commits into
mainfrom
feat/ollama-daemon-wiring

Conversation

@OpenCircuitDev

Copy link
Copy Markdown
Owner

Summary

Track 1, item 1 from docs/AGENT_OPERATIONS.md — Ollama daemon wiring. v0.1.1 ships on this. backend = "ollama" is now a first-class configured choice end-to-end: settings (TOML + Tauri commands) → selector → API server → settings UI.

The Ollama adapter itself (crates/ocm-inference/src/ollama.rs, NDJSON over :11434) already existed and was bench-verified; this PR makes it constructible from settings rather than dead code.

What changed

Rust (crates/)

  • ocm-daemon::settingsBackend enum (auto/llamacpp/vllm/ollama, serde lowercase, default Auto) + 3 new fields: backend, ollama_base_url, ollama_model. All new fields #[serde(default)] so a v0.1.0 settings.toml without these keys still parses (legacy-load test included).
  • ocm-inference::selectorBackendKind::Ollama variant; DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434"; new make_backend_for_kind(kind, inference_url, ollama_url, ollama_model) settings-driven constructor. Existing make_backend(base_url) preserved for back-compat. Auto-detect (detect_backend_kind) never returns Ollama — Ollama is opt-in (bridges to an external daemon; not something OCM auto-supervises).
  • ocm-daemon::bootstrapbuild_app_state resolves Settings.backend (Auto → existing detect; explicit → that kind), falls back to DEFAULT_OLLAMA_BASE_URL / ollama::DEFAULT_MODEL when URL/model unset, and calls make_backend_for_kind. The Ollama backend now flows through to AppState.backend, which is the abstraction the OpenAI-compat API server consumes — "API passes the configured model through" is satisfied at the bootstrap layer (no openai.rs change needed).

Tauri commands (get_settings / save_settings) need no change: they round-trip the whole Settings struct, so the new fields flow through automatically.

Frontend (frontend/)

  • settings.tsBackend type + 3 new fields on the Settings interface (mirror of Rust).
  • settings/+page.svelte<select> for backend (humanized labels: auto/llama.cpp/vLLM/Ollama) + two <input>s for Ollama URL and Ollama model. Placeholders show the daemon's native defaults (127.0.0.1:11434, llama3).

TDD

Followed the test-first discipline adapted for "CI is my compiler" (no local Rust toolchain on this machine).

Commit Purpose CI Run Verdict
42004cc test(ollama): RED 13 new tests referencing symbols that don't exist yet 27378990831 ❌ (expected — compile-fail on missing variants/fields)
cb61171 feat(ollama): GREEN Minimal impl to satisfy tests 27379125343 ❌ (clippy::derivable_impls — a lint, not a logic failure)
6963c3f fix(settings) #[derive(Default)] + #[default] instead of manual impl 27379270693 ✅ all 3 platforms
d8b126c feat(frontend) TS type + Svelte UI 27379313091 Frontend CI ✅ 26s

The RED-then-GREEN audit trail is intentional — it proves each new test actually tested something that didn't exist, then turned green from the minimal impl.

New test coverage

  • selector.rs (+4 tests): as_str() lockstep with Ollama::name(); default URL constant; make_backend_for_kind produces the expected backend name() for all three kinds.
  • settings.rs (+5 tests): Backend::default() == Auto; lowercase TOML serde; full Ollama round-trip; forward-compat legacy-load (settings.toml without backend key still parses to Auto); all-variants TOML round-trip.
  • bootstrap.rs (+4 tests): the headline assertion — Settings.backend = OllamaAppState.backend.name() == "Ollama"; Ollama with no URL/model still constructs (defaults fill in); explicit LlamaCpp / Vllm override platform detect.

Test plan

  • cargo clippy --workspace --all-targets -- -D warnings — green on ubuntu/macOS/windows (run 27379270693)
  • cargo test --workspace — green on ubuntu/macOS/windows (run 27379270693; counts per crate visible in log)
  • Frontend npm run check — 258 files, 0 errors, 0 warnings (local, then CI run 27379313091)
  • Frontend npm run build — clean static build in 3.80s (local)
  • Manual smoke (operator) — launch cargo tauri dev, pick Ollama in the new selector, point at a running ollama serve, send a chat. Not run here (no local Rust toolchain; per AGENT_OPERATIONS verification doctrine, CI is the compiler).
  • Bench cross-check (operator) — the amnesia-ab sandbox already CONFIRMED Ollama+Mem0 end-to-end on 2026-06-11; no rerun needed unless the operator wants one against the wired path.

Out of scope (deferred per AGENT_OPERATIONS Track 1)

  • Process supervision (item 2) — supervisor.rs is still #[allow(dead_code)]. Will land in a separate PR.
  • Settings UI polish (item 3) — current UI shows all rows unconditionally. Conditional "show Ollama fields only when backend = ollama" is a UX nicety for a follow-up.
  • mem0-v3-locomo activation (Track 2) — separate workload-packaging task.

🤖 Generated with Claude Code

Brand and others added 4 commits June 11, 2026 15:35
…ootstrap wiring

TDD red-pass for v0.1.1 Ollama daemon wiring (Track 1, item 1 per
AGENT_OPERATIONS.md). Tests reference symbols that don't yet exist; CI
will fail at compile, which IS the red. The green commit follows.

selector.rs:
- BackendKind::Ollama (new variant) + as_str() = "Ollama"
- DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434"
- make_backend_for_kind(kind, inference_url, ollama_url, ollama_model)
  — settings-driven constructor; existing make_backend(base_url) preserved
- existing detect / make_backend tests updated for the third variant
  (auto-detect still never picks Ollama — opt-in only)

settings.rs:
- Backend enum (Auto/LlamaCpp/Vllm/Ollama), serde lowercase
- new fields: backend (default Auto), ollama_base_url, ollama_model
- forward-compat: legacy settings.toml without `backend` parses to Auto
- TOML round-trip for every Backend variant

bootstrap.rs:
- build_app_state honors Settings.backend:
  · Auto → existing platform detect (LlamaCpp/Vllm only)
  · Ollama → Ollama backend wired through (the headline assertion)
  · Explicit LlamaCpp/Vllm → that backend regardless of platform
- Ollama with unset URL/model falls back to daemon defaults

API server passes the configured model through implicitly:
AppState.backend is Arc<dyn InferenceBackend>; the Ollama adapter already
takes (base_url, model) in its constructor, so wiring it via bootstrap is
the only change needed at the API layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Minimal implementation to turn the RED commit green. The Ollama adapter
already exists (crates/ocm-inference/src/ollama.rs); this commit makes
it constructible from settings.

selector.rs:
- BackendKind::Ollama variant; as_str() = "Ollama" (matches Ollama::name)
- DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434" (Ollama daemon default)
- make_backend_for_kind(kind, inference_url, ollama_url, ollama_model):
  settings-driven constructor; keeps make_backend(base_url) for back-compat
- detect_backend_kind never returns Ollama (opt-in only — auto-detect
  picks between backends OCM can supervise itself)

settings.rs:
- Backend enum (Auto/LlamaCpp/Vllm/Ollama), serde lowercase, default Auto
- new fields: backend, ollama_base_url, ollama_model
- all new fields #[serde(default)] for forward-compat with old settings.toml

bootstrap.rs:
- resolve_backend_kind(Settings.backend) → BackendKind (Auto delegates to
  detect_backend_kind; explicit selections override)
- build_app_state resolves Ollama URL/model to constants when unset and
  calls make_backend_for_kind — Ollama backend now flows through to
  AppState.backend, satisfying the "API server passes the configured
  model through" requirement (AppState.backend: Arc<dyn InferenceBackend>
  is the abstraction boundary)

Frontend type + UI changes follow in the next commit (no Rust impact).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…impls)

CI's `clippy -D warnings` rejected the manual `impl Default for Backend`.
Switch to the derive-with-#[default] form (same observable behavior:
Backend::default() = Backend::Auto). Tests unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the new Settings fields on the Rust side (crates/ocm-daemon/src/
settings.rs): backend, ollama_base_url, ollama_model.

settings.ts:
- Backend type ('auto' | 'llamacpp' | 'vllm' | 'ollama'), matches Rust serde
- Three new fields on the Settings interface

settings/+page.svelte:
- backend <select> with humanized labels (auto/llama.cpp/vLLM/Ollama)
- Ollama URL input (placeholder shows the daemon default 11434)
- Ollama model input (placeholder shows the existing DEFAULT_MODEL = llama3)
- Fields shown unconditionally; matches existing pattern (one form, all rows)

Verified locally: npm run check (258 files, 0 errors) + npm run build (3.80s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@OpenCircuitDev OpenCircuitDev merged commit 9ebe234 into main Jun 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant