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:
PonyX-lab
2026-03-11 05:02:43 +08:00
committed by GitHub
parent 0c17e7c225
commit 53374394fb
5 changed files with 131 additions and 2 deletions

View File

@@ -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: [],

View File

@@ -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,