Files
Maven/docs/plans/05-model-swap.md
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

2.6 KiB

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.gosrv.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