fix: archive old transcript files on /new and /reset (#14949)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4724df7dea
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Marcus Castro
2026-02-13 16:55:16 -03:00
committed by GitHub
parent c8b198ab51
commit 31537c669a
8 changed files with 211 additions and 19 deletions

View File

@@ -583,6 +583,49 @@ describe("initSessionState preserves behavior overrides across /new and /reset",
expect(result.sessionEntry.ttsAuto).toBe("on");
});
it("archives previous transcript file on /new reset", async () => {
const storePath = await createStorePath("openclaw-reset-archive-");
const sessionKey = "agent:main:telegram:dm:user-archive";
const existingSessionId = "existing-session-archive";
await seedSessionStoreWithOverrides({
storePath,
sessionKey,
sessionId: existingSessionId,
overrides: {},
});
const transcriptPath = path.join(path.dirname(storePath), `${existingSessionId}.jsonl`);
await fs.writeFile(
transcriptPath,
`${JSON.stringify({ message: { role: "user", content: "hello" } })}\n`,
"utf-8",
);
const cfg = {
session: { store: storePath, idleMinutes: 999 },
} as OpenClawConfig;
const result = await initSessionState({
ctx: {
Body: "/new",
RawBody: "/new",
CommandBody: "/new",
From: "user-archive",
To: "bot",
ChatType: "direct",
SessionKey: sessionKey,
Provider: "telegram",
Surface: "telegram",
},
cfg,
commandAuthorized: true,
});
expect(result.isNewSession).toBe(true);
expect(result.resetTriggered).toBe(true);
const files = await fs.readdir(path.dirname(storePath));
expect(files.some((f) => f.startsWith(`${existingSessionId}.jsonl.reset.`))).toBe(true);
});
it("idle-based new session does NOT preserve overrides (no entry to read)", async () => {
const storePath = await createStorePath("openclaw-idle-no-preserve-");
const sessionKey = "agent:main:telegram:dm:new-user";

View File

@@ -26,6 +26,7 @@ import {
type SessionScope,
updateSessionStore,
} from "../../config/sessions.js";
import { archiveSessionTranscripts } from "../../gateway/session-utils.fs.js";
import { deliverSessionMaintenanceWarning } from "../../infra/session-maintenance-warning.js";
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
import { normalizeMainKey } from "../../routing/session-key.js";
@@ -380,6 +381,17 @@ export async function initSessionState(params: {
},
);
// Archive old transcript so it doesn't accumulate on disk (#14869).
if (previousSessionEntry?.sessionId) {
archiveSessionTranscripts({
sessionId: previousSessionEntry.sessionId,
storePath,
sessionFile: previousSessionEntry.sessionFile,
agentId,
reason: "reset",
});
}
const sessionCtx: TemplateContext = {
...ctx,
// Keep BodyStripped aligned with Body (best default for agent prompts).