This commit is contained in:
Ethan Chen 2026-03-15 22:36:12 +08:00 committed by GitHub
commit 6be8f9928a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 2 deletions

View File

@ -1557,6 +1557,57 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
expect(result.sessionEntry.verboseLevel).toBeUndefined(); expect(result.sessionEntry.verboseLevel).toBeUndefined();
expect(result.sessionEntry.thinkingLevel).toBeUndefined(); expect(result.sessionEntry.thinkingLevel).toBeUndefined();
}); });
it("preserves modelOverride and providerOverride across daily freshness resets", async () => {
// Daily freshness resets (e.g. 4am boundary) have resetTriggered=false, so
// modelOverride/providerOverride must be preserved outside the resetTriggered guard.
vi.useFakeTimers();
try {
// Simulate: it is 5am, session was last active at 3am (before 4am daily boundary)
vi.setSystemTime(new Date(2026, 0, 18, 5, 0, 0));
const storePath = await createStorePath("openclaw-freshness-model-override-");
const sessionKey = "agent:main:telegram:dm:model-override-user";
const existingSessionId = "stale-session-model-override";
await writeSessionStoreFast(storePath, {
[sessionKey]: {
sessionId: existingSessionId,
updatedAt: new Date(2026, 0, 18, 3, 0, 0).getTime(),
modelOverride: "claude-opus-4",
providerOverride: "anthropic",
},
});
const cfg = { session: { store: storePath } } as OpenClawConfig;
const result = await initSessionState({
ctx: {
Body: "hello",
RawBody: "hello",
CommandBody: "hello",
From: "model-override-user",
To: "bot",
ChatType: "direct",
SessionKey: sessionKey,
Provider: "telegram",
Surface: "telegram",
},
cfg,
commandAuthorized: true,
});
expect(result.isNewSession).toBe(true);
expect(result.resetTriggered).toBe(false);
expect(result.sessionId).not.toBe(existingSessionId);
// Model/provider overrides must survive daily freshness resets
expect(result.sessionEntry.modelOverride).toBe("claude-opus-4");
expect(result.sessionEntry.providerOverride).toBe("anthropic");
// Behavior overrides are NOT carried over for non-resetTriggered resets
expect(result.sessionEntry.verboseLevel).toBeUndefined();
expect(result.sessionEntry.thinkingLevel).toBeUndefined();
} finally {
vi.useRealTimers();
}
});
}); });
describe("drainFormattedSystemEvents", () => { describe("drainFormattedSystemEvents", () => {

View File

@ -359,6 +359,12 @@ export async function initSessionState(params: {
isNewSession = true; isNewSession = true;
systemSent = false; systemSent = false;
abortedLastRun = false; abortedLastRun = false;
// Always preserve model/provider overrides across session resets
// (including daily freshness resets, not just explicit /reset or /new)
if (entry) {
persistedModelOverride = entry.modelOverride;
persistedProviderOverride = entry.providerOverride;
}
// When a reset trigger (/new, /reset) starts a new session, carry over // When a reset trigger (/new, /reset) starts a new session, carry over
// user-set behavior overrides (verbose, thinking, reasoning, ttsAuto) // user-set behavior overrides (verbose, thinking, reasoning, ttsAuto)
// so the user doesn't have to re-enable them every time. // so the user doesn't have to re-enable them every time.
@ -367,8 +373,6 @@ export async function initSessionState(params: {
persistedVerbose = entry.verboseLevel; persistedVerbose = entry.verboseLevel;
persistedReasoning = entry.reasoningLevel; persistedReasoning = entry.reasoningLevel;
persistedTtsAuto = entry.ttsAuto; persistedTtsAuto = entry.ttsAuto;
persistedModelOverride = entry.modelOverride;
persistedProviderOverride = entry.providerOverride;
persistedLabel = entry.label; persistedLabel = entry.label;
} }
} }