Skip to content

Commit 2a484a3

Browse files
SunnyShu0925claude
andauthored
[AI] fix(sessions): set liveModelSwitchPending when switching to default with runtime-only fields (#96318)
When a session's model comes from steering/fallback runtime fields (entry.modelProvider/entry.model) rather than explicit override fields, switching back to the default model via /model default would not set liveModelSwitchPending. The isDefault branch in applyModelOverrideToSessionEntry only sets selectionUpdated when it deletes override fields — but when no override fields exist, selectionUpdated stays false, preventing the liveModelSwitchPending flag from being set at the gate condition. Fix: after the runtime alignment check, set selectionUpdated when selection.isDefault and runtime fields are misaligned, so that liveModelSwitchPending is properly set for the pending live switch. Adds test coverage for this previously untested scenario. Related to #96269 Co-authored-by: Claude <[email protected]>
1 parent 1069c60 commit 2a484a3

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

src/sessions/model-overrides.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,39 @@ describe("applyModelOverrideToSessionEntry", () => {
180180
expect((entry.updatedAt ?? 0) > before).toBe(true);
181181
});
182182

183+
it("sets liveModelSwitchPending when switching to default with runtime-only fields", () => {
184+
const entry: SessionEntry = {
185+
sessionId: "sess-96269",
186+
updatedAt: Date.now() - 5_000,
187+
modelProvider: "anthropic",
188+
model: "claude-sonnet-4-6",
189+
contextTokens: 200_000,
190+
contextBudgetStatus: contextBudgetStatus({
191+
updatedAt: Date.now() - 5_000,
192+
provider: "anthropic",
193+
model: "claude-sonnet-4-6",
194+
contextTokenBudget: 200_000,
195+
}),
196+
};
197+
198+
const result = applyModelOverrideToSessionEntry({
199+
entry,
200+
selection: {
201+
provider: "openai",
202+
model: "gpt-5.4",
203+
isDefault: true,
204+
},
205+
markLiveSwitchPending: true,
206+
});
207+
208+
expect(result.updated).toBe(true);
209+
expect(entry.modelProvider).toBeUndefined();
210+
expect(entry.model).toBeUndefined();
211+
expect(entry.contextTokens).toBeUndefined();
212+
expect(entry.contextBudgetStatus).toBeUndefined();
213+
expect(entry.liveModelSwitchPending).toBe(true);
214+
});
215+
183216
it("marks non-default overrides with the provided source", () => {
184217
const entry: SessionEntry = {
185218
sessionId: "sess-5a",

src/sessions/model-overrides.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ export function applyModelOverrideToSessionEntry(params: {
9393
}
9494
}
9595

96+
// When switching back to the default model without override fields to delete
97+
// (e.g. model comes from steering/fallback runtime fields), the isDefault
98+
// branch at line 42 won't set selectionUpdated. Mark it here so that
99+
// liveModelSwitchPending can still be set below when runtime is misaligned.
100+
if (selection.isDefault && runtimePresent && !runtimeAligned) {
101+
selectionUpdated = true;
102+
}
103+
96104
// contextTokens are derived from the active session model. When the selected
97105
// model changes (or runtime model is already stale), the cached window can
98106
// pin the session to an older/smaller limit until another run refreshes it.

0 commit comments

Comments
 (0)