History

Migrate legacy terminal history to terminal-scoped log path

- On open, read legacy transcript files and write them to the new terminal-scoped history path - Remove legacy files after migration and warn if cleanup fails - Update tests to assert migration, content preservation, and legacy file removal

Julius Marminge committed 9 months ago

Commit d27b08b1 parent 485747b2 files · +21 −8Browse files

Unified · Split

2 files
  1. apps/server/src/terminalManager.test.ts +5 −2
  2. apps/server/src/terminalManager.ts +16 −6
apps/server/src/terminalManager.test.ts+5−2
@@ -334,15 +334,18 @@ describe("TerminalManager", () => { · 333 unmodified lines
334334 manager.dispose();
335335 });
336336
337− it("loads existing legacy transcript filenames and keeps new naming for writes", async () => {
337+ it("migrates legacy transcript filenames to terminal-scoped history path on open", async () => {
338338 const { manager, logsDir } = makeManager();
339339 const legacyPath = path.join(logsDir, "thread-1.log");
340+ const nextPath = historyLogPath(logsDir);
340341 fs.writeFileSync(legacyPath, "legacy-line\n", "utf8");
341342
342343 const snapshot = await manager.open(openInput());
343344
344345 expect(snapshot.history).toBe("legacy-line\n");
345− expect(fs.existsSync(legacyPath)).toBe(true);
346+ expect(fs.existsSync(nextPath)).toBe(true);
347+ expect(fs.readFileSync(nextPath, "utf8")).toBe("legacy-line\n");
348+ expect(fs.existsSync(legacyPath)).toBe(false);
346349
347350 manager.dispose();
348351 });
apps/server/src/terminalManager.ts+16−6
@@ -582,12 +582,12 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 581 unmodified lines
582582 }
583583
584584 private async readHistory(threadId: string, terminalId: string): Promise<string> {
585− const historyPath = this.historyPath(threadId, terminalId);
585+ const nextPath = this.historyPath(threadId, terminalId);
586586 try {
587− const raw = await fs.promises.readFile(historyPath, "utf8");
587+ const raw = await fs.promises.readFile(nextPath, "utf8");
588588 const capped = capHistory(raw, this.historyLineLimit);
589589 if (capped !== raw) {
590− await fs.promises.writeFile(historyPath, capped, "utf8");
590+ await fs.promises.writeFile(nextPath, capped, "utf8");
591591 }
592592 return capped;
593593 } catch (error) {
@@ -600,12 +600,22 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 6 unmodified lines
600600 return "";
601601 }
602602
603+ const legacyPath = this.legacyHistoryPath(threadId);
603604 try {
604− const raw = await fs.promises.readFile(this.legacyHistoryPath(threadId), "utf8");
605+ const raw = await fs.promises.readFile(legacyPath, "utf8");
605606 const capped = capHistory(raw, this.historyLineLimit);
606− if (capped !== raw) {
607− await fs.promises.writeFile(this.legacyHistoryPath(threadId), capped, "utf8");
607+
608+ // Migrate legacy transcript filename to the terminal-scoped path.
609+ await fs.promises.writeFile(nextPath, capped, "utf8");
610+ try {
611+ await fs.promises.rm(legacyPath, { force: true });
612+ } catch (cleanupError) {
613+ this.logger.warn("failed to remove legacy terminal history", {
614+ threadId,
615+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),
616+ });
608617 }
618+
609619 return capped;
610620 } catch (error) {
611621 if ((error as NodeJS.ErrnoException).code === "ENOENT") {