@@ -372,6 +372,56 @@ test("sessions.reset rotates generated topic transcript files with the new sessi
|
372 | 372 | expect(path.basename(persistedEntry?.sessionFile ?? "")).toBe(`${nextSessionId}-topic-456.jsonl`); |
373 | 373 | }); |
374 | 374 | |
| 375 | +test("sessions.reset rotates an already-stale generated transcript file to the new session id", async () => { |
| 376 | +const { dir, storePath } = await createSessionStoreDir(); |
| 377 | +// Post-upgrade state: the stored sessionFile still embeds an OLDER generated id |
| 378 | +// that no longer matches the entry's logical sessionId, so rotation must key off |
| 379 | +// the file's embedded id rather than the current sessionId (issue #77770). |
| 380 | +const staleFileSessionId = "11111111-1111-4111-8111-111111111111"; |
| 381 | +const currentSessionId = "22222222-2222-4222-8222-222222222222"; |
| 382 | +const staleSessionFile = path.join(dir, `${staleFileSessionId}.jsonl`); |
| 383 | +await fs.writeFile(staleSessionFile, `${JSON.stringify({ role: "user", content: "old" })}\n`); |
| 384 | + |
| 385 | +await writeSessionStore({ |
| 386 | +entries: { |
| 387 | +main: sessionStoreEntry(currentSessionId, { |
| 388 | +sessionFile: staleSessionFile, |
| 389 | +}), |
| 390 | +}, |
| 391 | +}); |
| 392 | + |
| 393 | +const reset = await directSessionReq<{ |
| 394 | +ok: true; |
| 395 | +key: string; |
| 396 | +entry: { |
| 397 | +sessionId: string; |
| 398 | +sessionFile?: string; |
| 399 | +}; |
| 400 | +}>("sessions.reset", { key: "main" }); |
| 401 | + |
| 402 | +expect(reset.ok).toBe(true); |
| 403 | +const nextSessionId = reset.payload?.entry.sessionId; |
| 404 | +const nextSessionFile = reset.payload?.entry.sessionFile; |
| 405 | +if (!nextSessionId || !nextSessionFile) { |
| 406 | +throw new Error("expected reset session id and file"); |
| 407 | +} |
| 408 | +expect(nextSessionId).not.toBe(currentSessionId); |
| 409 | +// The new session must adopt the new session id, not keep the stale generated name. |
| 410 | +expect(path.basename(nextSessionFile)).toBe(`${nextSessionId}.jsonl`); |
| 411 | +expect(path.basename(nextSessionFile)).not.toBe(`${staleFileSessionId}.jsonl`); |
| 412 | + |
| 413 | +const store = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record< |
| 414 | +string, |
| 415 | +{ |
| 416 | +sessionId?: string; |
| 417 | +sessionFile?: string; |
| 418 | +} |
| 419 | +>; |
| 420 | +const persistedEntry = store["agent:main:main"]; |
| 421 | +expect(persistedEntry?.sessionId).toBe(nextSessionId); |
| 422 | +expect(path.basename(persistedEntry?.sessionFile ?? "")).toBe(`${nextSessionId}.jsonl`); |
| 423 | +}); |
| 424 | + |
375 | 425 | test("sessions.reset preserves legacy explicit model overrides without modelOverrideSource", async () => { |
376 | 426 | await expectMainResetModelFields({ |
377 | 427 | defaultPrimary: "openai/gpt-test-a", |
|