fix(tui): align resolveModelSelection priority with gateway
Reorder conditions in resolveModelSelection so that modelOverride is checked before runtime model/modelProvider, matching the priority in resolveSessionModelRef (session-utils.ts). Without this change, a session with both a runtime model (from a previous run) and a modelOverride (from /model) would display the stale runtime model in the footer instead of the user's selection. Add a test case covering override precedence over runtime model. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b85353502c
commit
ee35f50550
@ -331,4 +331,69 @@ describe("tui session actions", () => {
|
||||
expect(state.sessionInfo.modelProvider).toBe("my-copilot");
|
||||
expect(state.sessionInfo.contextTokens).toBe(200000);
|
||||
});
|
||||
|
||||
it("prefers modelOverride over runtime model in session entry", async () => {
|
||||
// After /model switch, the entry has both a runtime model (from last run)
|
||||
// and a modelOverride (user's intent for next run). The override should win.
|
||||
const listSessions = vi.fn().mockResolvedValue({
|
||||
ts: Date.now(),
|
||||
path: "/tmp/sessions.json",
|
||||
count: 1,
|
||||
defaults: {},
|
||||
sessions: [
|
||||
{
|
||||
key: "agent:main:main",
|
||||
model: "gpt-5.3-codex",
|
||||
modelProvider: "openai-codex",
|
||||
modelOverride: "claude-opus-4-6",
|
||||
providerOverride: "anthropic",
|
||||
updatedAt: 200,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const state: TuiStateAccess = {
|
||||
agentDefaultId: "main",
|
||||
sessionMainKey: "agent:main:main",
|
||||
sessionScope: "global",
|
||||
agents: [],
|
||||
currentAgentId: "main",
|
||||
currentSessionKey: "agent:main:main",
|
||||
currentSessionId: null,
|
||||
activeChatRunId: null,
|
||||
historyLoaded: false,
|
||||
sessionInfo: {},
|
||||
initialSessionApplied: true,
|
||||
isConnected: true,
|
||||
autoMessageSent: false,
|
||||
toolsExpanded: false,
|
||||
showThinking: false,
|
||||
connectionStatus: "connected",
|
||||
activityStatus: "idle",
|
||||
statusTimeout: null,
|
||||
lastCtrlCAt: 0,
|
||||
};
|
||||
|
||||
const { refreshSessionInfo } = createSessionActions({
|
||||
client: { listSessions } as unknown as GatewayChatClient,
|
||||
chatLog: { addSystem: vi.fn() } as unknown as import("./components/chat-log.js").ChatLog,
|
||||
tui: { requestRender: vi.fn() } as unknown as import("@mariozechner/pi-tui").TUI,
|
||||
opts: {},
|
||||
state,
|
||||
agentNames: new Map(),
|
||||
initialSessionInput: "",
|
||||
initialSessionAgentId: null,
|
||||
resolveSessionKey: vi.fn(),
|
||||
updateHeader: vi.fn(),
|
||||
updateFooter: vi.fn(),
|
||||
updateAutocompleteProvider: vi.fn(),
|
||||
setActivityStatus: vi.fn(),
|
||||
});
|
||||
|
||||
await refreshSessionInfo();
|
||||
|
||||
// Override should take precedence over runtime model
|
||||
expect(state.sessionInfo.model).toBe("claude-opus-4-6");
|
||||
expect(state.sessionInfo.modelProvider).toBe("anthropic");
|
||||
});
|
||||
});
|
||||
|
||||
@ -118,17 +118,21 @@ export function createSessionActions(context: SessionActionContext) {
|
||||
entry?: SessionInfoEntry,
|
||||
defaults?: SessionInfoDefaults | null,
|
||||
) => {
|
||||
// 1. Explicit user override (set via /model) wins over last-run runtime model.
|
||||
// This matches the priority in resolveSessionModelRef (session-utils.ts).
|
||||
const overrideModel = entry?.modelOverride?.trim();
|
||||
if (overrideModel) {
|
||||
const overrideProvider = entry?.providerOverride?.trim() || state.sessionInfo.modelProvider;
|
||||
return { modelProvider: overrideProvider, model: overrideModel };
|
||||
}
|
||||
// 2. Fall back to runtime model from last run.
|
||||
if (entry?.modelProvider || entry?.model) {
|
||||
return {
|
||||
modelProvider: entry.modelProvider ?? state.sessionInfo.modelProvider,
|
||||
model: entry.model ?? state.sessionInfo.model,
|
||||
};
|
||||
}
|
||||
const overrideModel = entry?.modelOverride?.trim();
|
||||
if (overrideModel) {
|
||||
const overrideProvider = entry?.providerOverride?.trim() || state.sessionInfo.modelProvider;
|
||||
return { modelProvider: overrideProvider, model: overrideModel };
|
||||
}
|
||||
// 3. Configured defaults.
|
||||
if (defaults?.modelProvider || defaults?.model) {
|
||||
return {
|
||||
modelProvider: defaults.modelProvider ?? state.sessionInfo.modelProvider,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user