
























@@ -3065,6 +3065,126 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
30653065expect(result.sessionEntry.totalTokensFresh).toBe(true);
30663066});
306730673068+it("clears stale runtime model cache fields on /new and /reset (#77322)", async () => {
3069+const storePath = await createStorePath("openclaw-reset-runtime-model-cache-");
3070+const sessionKey = "agent:main:telegram:direct:runtime-model-cache";
3071+const existingSessionId = "existing-session-runtime-model-cache";
3072+const runtimeModelCache = {
3073+modelProvider: "openai",
3074+model: "gpt-5.4-mini",
3075+contextTokens: 400_000,
3076+cacheRead: 1_000,
3077+cacheWrite: 2_000,
3078+fallbackNoticeSelectedModel: "openai/gpt-5.4-mini",
3079+fallbackNoticeActiveModel: "minimax/m2.7",
3080+fallbackNoticeReason: "rate limit",
3081+systemPromptReport: {
3082+source: "run",
3083+generatedAt: 1,
3084+provider: "openai",
3085+model: "gpt-5.4-mini",
3086+systemPrompt: { chars: 1, projectContextChars: 0, nonProjectContextChars: 1 },
3087+injectedWorkspaceFiles: [],
3088+skills: { promptChars: 0, entries: [] },
3089+tools: { listChars: 0, schemaChars: 0, entries: [] },
3090+},
3091+verboseLevel: "on",
3092+} as const;
3093+const explicitUserOverride = {
3094+providerOverride: "minimax",
3095+modelOverride: "m2.7",
3096+modelOverrideSource: "user",
3097+} as const;
3098+const cases = [
3099+{ name: "new clears stale runtime model cache", body: "/new" },
3100+{ name: "reset clears stale runtime model cache", body: "/reset" },
3101+] as const;
3102+3103+for (const testCase of cases) {
3104+await seedSessionStoreWithOverrides({
3105+ storePath,
3106+ sessionKey,
3107+sessionId: existingSessionId,
3108+overrides: { ...runtimeModelCache, ...explicitUserOverride },
3109+});
3110+const seeded = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record<
3111+string,
3112+SessionEntry
3113+>;
3114+expect(seeded[sessionKey]?.modelProvider, testCase.name).toBe(
3115+runtimeModelCache.modelProvider,
3116+);
3117+expect(seeded[sessionKey]?.model, testCase.name).toBe(runtimeModelCache.model);
3118+3119+const cfg = {
3120+session: { store: storePath, idleMinutes: 999 },
3121+} as OpenClawConfig;
3122+3123+const result = await initSessionState({
3124+ctx: {
3125+Body: testCase.body,
3126+RawBody: testCase.body,
3127+CommandBody: testCase.body,
3128+From: "6761477233",
3129+To: "bot",
3130+ChatType: "direct",
3131+SessionKey: sessionKey,
3132+Provider: "telegram",
3133+Surface: "telegram",
3134+},
3135+ cfg,
3136+commandAuthorized: true,
3137+});
3138+3139+expect(result.isNewSession, testCase.name).toBe(true);
3140+expect(result.resetTriggered, testCase.name).toBe(true);
3141+expect(result.sessionId, testCase.name).not.toBe(existingSessionId);
3142+expect(result.sessionEntry.modelProvider, testCase.name).toBeUndefined();
3143+expect(result.sessionEntry.model, testCase.name).toBeUndefined();
3144+expect(result.sessionEntry.cacheRead, testCase.name).toBeUndefined();
3145+expect(result.sessionEntry.cacheWrite, testCase.name).toBeUndefined();
3146+expect(result.sessionEntry.fallbackNoticeSelectedModel, testCase.name).toBeUndefined();
3147+expect(result.sessionEntry.fallbackNoticeActiveModel, testCase.name).toBeUndefined();
3148+expect(result.sessionEntry.fallbackNoticeReason, testCase.name).toBeUndefined();
3149+expect(result.sessionEntry.systemPromptReport, testCase.name).toBeUndefined();
3150+expect(result.sessionEntry.providerOverride, testCase.name).toBe(
3151+explicitUserOverride.providerOverride,
3152+);
3153+expect(result.sessionEntry.modelOverride, testCase.name).toBe(
3154+explicitUserOverride.modelOverride,
3155+);
3156+expect(result.sessionEntry.modelOverrideSource, testCase.name).toBe(
3157+explicitUserOverride.modelOverrideSource,
3158+);
3159+// Unrelated behavior overrides still carry across the reset.
3160+expect(result.sessionEntry.verboseLevel, testCase.name).toBe(runtimeModelCache.verboseLevel);
3161+3162+const stored = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record<
3163+string,
3164+SessionEntry
3165+>;
3166+expect(stored[sessionKey].modelProvider, testCase.name).toBeUndefined();
3167+expect(stored[sessionKey].model, testCase.name).toBeUndefined();
3168+expect(stored[sessionKey].cacheRead, testCase.name).toBeUndefined();
3169+expect(stored[sessionKey].cacheWrite, testCase.name).toBeUndefined();
3170+expect(stored[sessionKey].fallbackNoticeSelectedModel, testCase.name).toBeUndefined();
3171+expect(stored[sessionKey].fallbackNoticeActiveModel, testCase.name).toBeUndefined();
3172+expect(stored[sessionKey].fallbackNoticeReason, testCase.name).toBeUndefined();
3173+expect(stored[sessionKey].systemPromptReport, testCase.name).toBeUndefined();
3174+expect(stored[sessionKey].providerOverride, testCase.name).toBe(
3175+explicitUserOverride.providerOverride,
3176+);
3177+expect(stored[sessionKey].modelOverride, testCase.name).toBe(
3178+explicitUserOverride.modelOverride,
3179+);
3180+expect(stored[sessionKey].modelOverrideSource, testCase.name).toBe(
3181+explicitUserOverride.modelOverrideSource,
3182+);
3183+expect(stored[sessionKey].contextTokens, testCase.name).toBeUndefined();
3184+expect(stored[sessionKey].verboseLevel, testCase.name).toBe(runtimeModelCache.verboseLevel);
3185+}
3186+});
3187+30683188it("preserves spawned session ownership metadata across /new and /reset", async () => {
30693189const storePath = await createStorePath("openclaw-reset-spawned-metadata-");
30703190const sessionKey = "subagent:owned-child";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。