5fe8f228c1
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>
30 lines
2.6 KiB
Markdown
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
|