mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 04:50:23 +00:00
Fix stale runtime model reuse on session reset (#41173)
Merged via squash.
Prepared head SHA: d8a04a466a
Co-authored-by: PonyX-lab <266766228+PonyX-lab@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
This commit is contained in:
@@ -1255,6 +1255,79 @@ describe("runReplyAgent typing (heartbeat)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("clears stale runtime model fields when resetSession retries after compaction failure", async () => {
|
||||
await withTempStateDir(async (stateDir) => {
|
||||
const sessionId = "session-stale-model";
|
||||
const storePath = path.join(stateDir, "sessions", "sessions.json");
|
||||
const transcriptPath = sessions.resolveSessionTranscriptPath(sessionId);
|
||||
const sessionEntry: SessionEntry = {
|
||||
sessionId,
|
||||
updatedAt: Date.now(),
|
||||
sessionFile: transcriptPath,
|
||||
modelProvider: "qwencode",
|
||||
model: "qwen3.5-plus-2026-02-15",
|
||||
contextTokens: 123456,
|
||||
systemPromptReport: {
|
||||
source: "run",
|
||||
generatedAt: Date.now(),
|
||||
sessionId,
|
||||
sessionKey: "main",
|
||||
provider: "qwencode",
|
||||
model: "qwen3.5-plus-2026-02-15",
|
||||
workspaceDir: stateDir,
|
||||
bootstrapMaxChars: 1000,
|
||||
bootstrapTotalMaxChars: 2000,
|
||||
systemPrompt: {
|
||||
chars: 10,
|
||||
projectContextChars: 5,
|
||||
nonProjectContextChars: 5,
|
||||
},
|
||||
injectedWorkspaceFiles: [],
|
||||
skills: {
|
||||
promptChars: 0,
|
||||
entries: [],
|
||||
},
|
||||
tools: {
|
||||
listChars: 0,
|
||||
schemaChars: 0,
|
||||
entries: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
const sessionStore = { main: sessionEntry };
|
||||
|
||||
await fs.mkdir(path.dirname(storePath), { recursive: true });
|
||||
await fs.writeFile(storePath, JSON.stringify(sessionStore), "utf-8");
|
||||
await fs.mkdir(path.dirname(transcriptPath), { recursive: true });
|
||||
await fs.writeFile(transcriptPath, "ok", "utf-8");
|
||||
|
||||
state.runEmbeddedPiAgentMock.mockImplementationOnce(async () => {
|
||||
throw new Error(
|
||||
'Context overflow: Summarization failed: 400 {"message":"prompt is too long"}',
|
||||
);
|
||||
});
|
||||
|
||||
const { run } = createMinimalRun({
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
sessionKey: "main",
|
||||
storePath,
|
||||
});
|
||||
await run();
|
||||
|
||||
expect(sessionStore.main.modelProvider).toBeUndefined();
|
||||
expect(sessionStore.main.model).toBeUndefined();
|
||||
expect(sessionStore.main.contextTokens).toBeUndefined();
|
||||
expect(sessionStore.main.systemPromptReport).toBeUndefined();
|
||||
|
||||
const persisted = JSON.parse(await fs.readFile(storePath, "utf-8"));
|
||||
expect(persisted.main.modelProvider).toBeUndefined();
|
||||
expect(persisted.main.model).toBeUndefined();
|
||||
expect(persisted.main.contextTokens).toBeUndefined();
|
||||
expect(persisted.main.systemPromptReport).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
it("surfaces overflow fallback when embedded run returns empty payloads", async () => {
|
||||
state.runEmbeddedPiAgentMock.mockImplementationOnce(async () => ({
|
||||
payloads: [],
|
||||
|
||||
@@ -278,6 +278,10 @@ export async function runReplyAgent(params: {
|
||||
updatedAt: Date.now(),
|
||||
systemSent: false,
|
||||
abortedLastRun: false,
|
||||
modelProvider: undefined,
|
||||
model: undefined,
|
||||
contextTokens: undefined,
|
||||
systemPromptReport: undefined,
|
||||
fallbackNoticeSelectedModel: undefined,
|
||||
fallbackNoticeActiveModel: undefined,
|
||||
fallbackNoticeReason: undefined,
|
||||
|
||||
Reference in New Issue
Block a user