Files
Maven/docs/plans/05-model-swap.md
T
kami 5fe8f228c1 feat(mavweb): /ecosystem page consuming Nexus/Praxis/Hexis + shell fixes
Add a read-only /ecosystem page that consumes the sibling services'
JSON APIs (Nexus entities, Praxis attention, Hexis capabilities),
fetched concurrently with honest per-panel error states. Siblings stay
headless — mavweb is their human surface (arch §16). Wired via mavweb
-nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network.

Fix mobile horizontal overflow across all pages: .content is a flex
child with default min-width:auto, so it refused to shrink below the
tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll
instead of dragging the page sideways. Verified via CDP geometry check
(scrollWidth === clientWidth at 430px).

Also includes in-progress Ethos UI redesign, ecosystem deploy compose,
and planning docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:04:23 +04:00

30 lines
2.6 KiB
Markdown

# Plan: On-the-Fly Model Swap (Multi-Model Routing)
**Goal:** Maven can switch between LLM models at runtime — including using a remote `llama-server` instance on workpc over LAN — without restarting the daemon. The phraser, router (LLM router), and replier all point at a dynamic backend that can be re-pointed via IPC.
**Done when:**
- `internal/llm/client.go` supports a dynamic base URL that can be swapped at runtime
- `internal/phraser/llmphraser.go` can hot-swap its backend (stop current `llama-server` subprocess, start new one, or point to a remote one)
- Remote model config: `phraser.mode = "remote"` with `remote_url = "http://workpc:8080"` — connects without spawning a subprocess
- Swap is triggered via IPC (`MethodSwapModel`) with a new config block — no daemon restart
- Router's `LLMRouter` (in `internal/router/llmrouter.go`) follows the same swap
- Fallback: if the new model fails to respond within timeout, the old model stays active (never leave the user with no model)
**Scope:**
- `internal/llm/client.go` — add `SetBaseURL(string)` method for runtime re-pointing
- `internal/phraser/llmphraser.go` — add `Swap(Config) error` method
- `internal/router/llmrouter.go` — already holds a `Completer` interface; swap the underlying client
- `cmd/mavend/voice.go` — re-creates `LLMReplier` when model changes
- New IPC method `MethodSwapModel` in `internal/ipc/api.go`
- Config: `phraser.mode` field (`local|remote`), `phraser.remote_url`
**Steps:**
1. Add `SetBaseURL(url string)` to `internal/llm/client.go` — atomically swaps the `base` field under a mutex (add `sync.RWMutex` to `Client`)
2. Add `Swap(cfg Config) error` to `internal/phraser/llmphraser.go` — stops current `llama-server` (via `Close()`), starts new one with new config, or connects to remote URL without spawning
3. Extend `PhraserConfig` in `internal/config/config.go` with `Mode string` (`"local"` or `"remote"`) and `RemoteURL string`
4. Create new `internal/llm/manager.go` — manages a set of named backends, allows `SwitchModel(name)` that re-wires phraser + LLM router + replier atomically
5. Add `MethodSwapModel` to `internal/ipc/api.go` with request `{model_path, mode, remote_url, n_gpu_layers, n_ctx}`
6. Wire swap handler in `cmd/mavend/main.go``srv.ModelSwapFn` called from IPC dispatch, re-wires phraser, rebuilds router with new LLMRouter, rebuilds replier
7. Add `model` block to `config.Config` with named model definitions (local paths + remote URLs)
8. Test: swap between local `StubPhraser` and remote llama-server on LAN; verify phraser + router + replier all use the new backend