Skip to content

Commit 422ff8d

Browse files
[AI] fix(model): /model <default> writes override when session runs non-default model
Strip isDefault from model selections before applying overrides in the directive-handling paths. When a user explicitly switches to the configured default model via /model, the selection must write an override so the session actually transitions — clearing overrides left the session pinned to the stale runtime model. Related to #96269
1 parent f65aca6 commit 422ff8d

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

src/auto-reply/reply/directive-handling.impl.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,15 @@ export async function handleDirectiveOnly(
455455
}
456456
}
457457
if (modelSelection) {
458+
// Strip isDefault so user-requested model switches always write an
459+
// explicit override. When the selected model happens to match the
460+
// configured default, retaining isDefault would clear overrides and
461+
// leave the session pinned to its current (possibly different)
462+
// runtime model (#96269).
463+
const { isDefault: _, ...selection } = modelSelection;
458464
const applied = applyModelOverrideToSessionEntry({
459465
entry: sessionEntry,
460-
selection: modelSelection,
466+
selection,
461467
profileOverride,
462468
markLiveSwitchPending: true,
463469
});

src/auto-reply/reply/directive-handling.persist.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,12 @@ export async function persistInlineDirectives(params: {
267267
provider,
268268
});
269269
if (modelResolution.modelSelection) {
270+
// Strip isDefault — user-requested model switches always write an
271+
// explicit override (#96269).
272+
const { isDefault: _, ...selection } = modelResolution.modelSelection;
270273
const appliedModelOverride = applyModelOverrideToSessionEntry({
271274
entry: sessionEntry,
272-
selection: modelResolution.modelSelection,
275+
selection,
273276
profileOverride: modelResolution.profileOverride,
274277
markLiveSwitchPending: params.markLiveSwitchPending,
275278
});

src/sessions/model-overrides.test.ts

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

183+
it("writes default model override when selected without isDefault flag (#96269)", () => {
184+
// Regression test for #96269: when a user explicitly selects the
185+
// configured default model via /model, the selection must be treated
186+
// as an explicit switch (no isDefault flag). The old behaviour
187+
// passed isDefault=true, which cleared overrides and left the
188+
// session pinned to the stale runtime model.
189+
const before = Date.now() - 5_000;
190+
const entry: SessionEntry = {
191+
sessionId: "sess-model-cmd-default",
192+
updatedAt: before,
193+
providerOverride: "tencent-token-plan",
194+
modelOverride: "glm-5.1",
195+
contextTokens: 128_000,
196+
};
197+
198+
const result = applyModelOverrideToSessionEntry({
199+
entry,
200+
selection: {
201+
provider: "minimax",
202+
model: "MiniMax-M3",
203+
// No isDefault — mimics directive-handling.impl.ts stripping it
204+
},
205+
});
206+
207+
expect(result.updated).toBe(true);
208+
// Must write the override so the session actually switches.
209+
expect(entry.providerOverride).toBe("minimax");
210+
expect(entry.modelOverride).toBe("MiniMax-M3");
211+
expect(entry.modelOverrideSource).toBe("user");
212+
expect((entry.updatedAt ?? 0) > before).toBe(true);
213+
});
214+
183215
it("marks non-default overrides with the provided source", () => {
184216
const entry: SessionEntry = {
185217
sessionId: "sess-5a",

0 commit comments

Comments
 (0)