# Provider/Model Runtime Switching **Date:** 2026-02-06 **Status:** In Progress ## Goal Enable easy runtime switching of model providers per tier via the `/model` command, using `provider/model` syntax. ## Commands ``` /model — Show all tiers with provider/model labels /model fast — Switch active tier (existing behavior) /model default github-copilot/claude-sonnet-4-5 — Change default tier's provider+model /model complex anthropic/claude-opus-4 — Change complex tier's provider+model /model fast github-copilot/gpt-4o-mini — Change fast tier's provider+model ``` ## Design Decisions 1. **No presets** — Direct `provider/model` targeting per tier. YAGNI. 2. **Full override** — When you set a tier, it fully replaces the previous client. 3. **Local tier excluded** — `/model local` continues to use `/backend` for switching. Local models are a different concern. 4. **Auth** — Config-based `api_key` for most providers. `/login` OAuth flow for GitHub Copilot (already implemented). 5. **Merged into /model** — No separate `/provider` command. Everything lives under `/model`. ## Implementation ### 1. ModelRouter (`src/models/router.ts`) - Add `setClient(tier: ModelTier, client: ModelClient, label: string)` — replaces a tier's client at runtime - Add `getLabel(tier: ModelTier): string` — returns `provider/model` string for display - Track labels in a `Map` populated at construction and updated by `setClient()` ### 2. Client Factory (`src/daemon/index.ts`) Extract `createClientFromProvider(provider: string, model: string, opts?: { apiKey?: string; endpoint?: string }): ModelClient` factory function from the existing inline client creation logic. Used by both daemon startup and runtime `/model` switching. ### 3. Command Parser (`src/frontends/tui/commands.ts`) - Extend `Command` type: `{ type: 'model'; name?: string; providerModel?: string }` - Parse `/model ` — split on space to get tier + provider/model - Parse provider/model string: split on first `/` to get provider and model name - Update autocompletion to suggest available providers after tier name - Update tooltips ### 4. Daemon Wiring (`src/daemon/index.ts`) Handle the new command variant: 1. Receive `{ type: 'model', name: 'default', providerModel: 'github-copilot/claude-sonnet-4-5' }` 2. Parse provider and model from `providerModel` 3. Call `createClientFromProvider(provider, model)` to instantiate client 4. Call `router.setClient('default', client, 'github-copilot/claude-sonnet-4-5')` 5. Respond with confirmation message ### 5. Provider Name Mapping Map short provider names to client constructors: | Provider Name | Client Class | |---------------|-------------| | `anthropic` | AnthropicClient | | `openai` | OpenAIClient | | `github` / `github-copilot` | GitHubModelsClient | | `gemini` | GeminiClient | | `bedrock` | BedrockClient | | `ollama` | OllamaClient | | `llamacpp` | LlamaCppClient | ## Files Changed | File | Change | |------|--------| | `src/models/router.ts` | Add `setClient()`, `getLabel()`, label tracking | | `src/models/router.test.ts` | Tests for new methods | | `src/frontends/tui/commands.ts` | Extended parser, completions, tooltips | | `src/frontends/tui/commands.test.ts` | Tests for new parsing | | `src/daemon/index.ts` | Extract factory, wire new command handler |