From 8b1ed2f6890dd1da149dd06e73017ea0317b29bf Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sun, 15 Feb 2026 19:53:42 -0800 Subject: [PATCH] Make /model provider switch activate selected tier in minimal TUI --- docs/plans/state.json | 12 ++++++ src/frontends/tui/minimal.test.ts | 61 +++++++++++++++++++++++++++++++ src/frontends/tui/minimal.ts | 4 +- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/docs/plans/state.json b/docs/plans/state.json index 8ef1a25..9209909 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -57,6 +57,18 @@ "test_status": "pnpm test:run src/daemon/clientFactory.test.ts src/models/openai.test.ts + pnpm typecheck passing (updated to cover textual 401 without status field)" }, + "tui-model-provider-switch-activates-tier": { + "status": "completed", + "date": "2026-02-16", + "updated": "2026-02-16", + "summary": "Fixed minimal TUI /model behavior to also activate the selected tier and sync agent tier immediately. This prevents confusing cases where provider/model changes are applied to one tier while prompts still run on another tier.", + "files_modified": [ + "src/frontends/tui/minimal.ts", + "src/frontends/tui/minimal.test.ts" + ], + "test_status": "pnpm test:run src/frontends/tui/minimal.test.ts src/models/openai.test.ts src/daemon/clientFactory.test.ts + pnpm typecheck passing" + }, + "deployment-port-env-override": { "status": "completed", "date": "2026-02-16", diff --git a/src/frontends/tui/minimal.test.ts b/src/frontends/tui/minimal.test.ts index 200bc21..0915fa4 100644 --- a/src/frontends/tui/minimal.test.ts +++ b/src/frontends/tui/minimal.test.ts @@ -163,6 +163,67 @@ describe('MinimalTui backend command', () => { expect(mockRouter.setClient).toHaveBeenCalledOnce(); expect(mockRouter.setTierStrict).toHaveBeenCalledWith('default', true); + expect(mockRouter.setTier).toHaveBeenCalledWith('default'); + } finally { + if (prevOpenRouterKey) { + process.env.OPENROUTER_API_KEY = prevOpenRouterKey; + } else { + delete process.env.OPENROUTER_API_KEY; + } + } + }); + + it('switches active tier and syncs agent for /model ', () => { + const prevOpenRouterKey = process.env.OPENROUTER_API_KEY; + delete process.env.OPENROUTER_API_KEY; + + try { + const mockSession = { + id: 'test', + getHistory: () => [], + addMessage: vi.fn(), + clear: vi.fn(), + replaceHistory: vi.fn(), + }; + + const mockRouter = { + getTier: () => 'fast' as const, + getAvailableTiers: () => ['default', 'fast', 'local'], + setTier: vi.fn(() => true), + getLocalProviderName: () => 'ollama', + setLocalClient: vi.fn(), + setClient: vi.fn(), + setTierStrict: vi.fn(), + chat: vi.fn(), + getClient: vi.fn(), + }; + + const mockAgent = { + setModelTier: vi.fn(), + getModelTier: vi.fn(() => 'fast'), + process: vi.fn(), + }; + + const tui = new MinimalTui({ + session: mockSession as any, + modelClient: mockRouter as any, + modelRouter: mockRouter as any, + agent: mockAgent as any, + systemPrompt: 'test', + modelProviderConfigs: { + openrouter: { + provider: 'openrouter', + model: 'seed-model', + api_key: 'test-key', + endpoint: 'https://openrouter.ai/api/v1', + }, + }, + }); + + (tui as any).handleModelCommand('default', 'openrouter/deepseek/deepseek-chat'); + + expect(mockRouter.setTier).toHaveBeenCalledWith('default'); + expect(mockAgent.setModelTier).toHaveBeenCalledWith('default'); } finally { if (prevOpenRouterKey) { process.env.OPENROUTER_API_KEY = prevOpenRouterKey; diff --git a/src/frontends/tui/minimal.ts b/src/frontends/tui/minimal.ts index 55b2030..20ad479 100644 --- a/src/frontends/tui/minimal.ts +++ b/src/frontends/tui/minimal.ts @@ -287,12 +287,14 @@ export class MinimalTui { }); router.setClient(tier, client, providerModel); router.setTierStrict(tier, true); + router.setTier(tier); - if (this.config.agent && tier === router.getTier()) { + if (this.config.agent) { this.config.agent.setModelTier(tier); } console.log(`${colors.gray}Set ${tier} to:${colors.reset} ${providerModel}`); + console.log(`${colors.gray}Switched to model:${colors.reset} ${tier}`); console.log(`${colors.gray}Fallbacks for ${tier} disabled (strict tier mode).${colors.reset}\n`); } catch (error) { const message = error instanceof Error ? error.message : String(error);