mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-05 09:31:27 +00:00
[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 <noreply@anthropic.com>
This commit is contained in:
@@ -180,6 +180,39 @@ describe("applyModelOverrideToSessionEntry", () => {
|
||||
expect((entry.updatedAt ?? 0) > before).toBe(true);
|
||||
});
|
||||
|
||||
it("sets liveModelSwitchPending when switching to default with runtime-only fields", () => {
|
||||
const entry: SessionEntry = {
|
||||
sessionId: "sess-96269",
|
||||
updatedAt: Date.now() - 5_000,
|
||||
modelProvider: "anthropic",
|
||||
model: "claude-sonnet-4-6",
|
||||
contextTokens: 200_000,
|
||||
contextBudgetStatus: contextBudgetStatus({
|
||||
updatedAt: Date.now() - 5_000,
|
||||
provider: "anthropic",
|
||||
model: "claude-sonnet-4-6",
|
||||
contextTokenBudget: 200_000,
|
||||
}),
|
||||
};
|
||||
|
||||
const result = applyModelOverrideToSessionEntry({
|
||||
entry,
|
||||
selection: {
|
||||
provider: "openai",
|
||||
model: "gpt-5.4",
|
||||
isDefault: true,
|
||||
},
|
||||
markLiveSwitchPending: true,
|
||||
});
|
||||
|
||||
expect(result.updated).toBe(true);
|
||||
expect(entry.modelProvider).toBeUndefined();
|
||||
expect(entry.model).toBeUndefined();
|
||||
expect(entry.contextTokens).toBeUndefined();
|
||||
expect(entry.contextBudgetStatus).toBeUndefined();
|
||||
expect(entry.liveModelSwitchPending).toBe(true);
|
||||
});
|
||||
|
||||
it("marks non-default overrides with the provided source", () => {
|
||||
const entry: SessionEntry = {
|
||||
sessionId: "sess-5a",
|
||||
|
||||
@@ -93,6 +93,14 @@ export function applyModelOverrideToSessionEntry(params: {
|
||||
}
|
||||
}
|
||||
|
||||
// When switching back to the default model without override fields to delete
|
||||
// (e.g. model comes from steering/fallback runtime fields), the isDefault
|
||||
// branch at line 42 won't set selectionUpdated. Mark it here so that
|
||||
// liveModelSwitchPending can still be set below when runtime is misaligned.
|
||||
if (selection.isDefault && runtimePresent && !runtimeAligned) {
|
||||
selectionUpdated = true;
|
||||
}
|
||||
|
||||
// contextTokens are derived from the active session model. When the selected
|
||||
// model changes (or runtime model is already stale), the cached window can
|
||||
// pin the session to an older/smaller limit until another run refreshes it.
|
||||
|
||||
Reference in New Issue
Block a user