- 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
Unified · Split
| @@ -334,15 +334,18 @@ describe("TerminalManager", () => { · 333 unmodified lines | |||
| 334 | manager.dispose(); | 334 | manager.dispose(); |
| 335 | }); | 335 | }); |
| 336 | 336 | ||
| 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 () => { |
| 338 | const { manager, logsDir } = makeManager(); | 338 | const { manager, logsDir } = makeManager(); |
| 339 | const legacyPath = path.join(logsDir, "thread-1.log"); | 339 | const legacyPath = path.join(logsDir, "thread-1.log"); |
| 340 | const nextPath = historyLogPath(logsDir); | ||
| 340 | fs.writeFileSync(legacyPath, "legacy-line\n", "utf8"); | 341 | fs.writeFileSync(legacyPath, "legacy-line\n", "utf8"); |
| 341 | 342 | ||
| 342 | const snapshot = await manager.open(openInput()); | 343 | const snapshot = await manager.open(openInput()); |
| 343 | 344 | ||
| 344 | expect(snapshot.history).toBe("legacy-line\n"); | 345 | 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); | ||
| 346 | 349 | ||
| 347 | manager.dispose(); | 350 | manager.dispose(); |
| 348 | }); | 351 | }); |
| @@ -582,12 +582,12 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 581 unmodified lines | |||
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | private async readHistory(threadId: string, terminalId: string): Promise<string> { | 584 | private async readHistory(threadId: string, terminalId: string): Promise<string> { |
| 585 | const historyPath = this.historyPath(threadId, terminalId); | 585 | const nextPath = this.historyPath(threadId, terminalId); |
| 586 | try { | 586 | try { |
| 587 | const raw = await fs.promises.readFile(historyPath, "utf8"); | 587 | const raw = await fs.promises.readFile(nextPath, "utf8"); |
| 588 | const capped = capHistory(raw, this.historyLineLimit); | 588 | const capped = capHistory(raw, this.historyLineLimit); |
| 589 | if (capped !== raw) { | 589 | if (capped !== raw) { |
| 590 | await fs.promises.writeFile(historyPath, capped, "utf8"); | 590 | await fs.promises.writeFile(nextPath, capped, "utf8"); |
| 591 | } | 591 | } |
| 592 | return capped; | 592 | return capped; |
| 593 | } catch (error) { | 593 | } catch (error) { |
| @@ -600,12 +600,22 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 6 unmodified lines | |||
| 600 | return ""; | 600 | return ""; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | const legacyPath = this.legacyHistoryPath(threadId); | ||
| 603 | try { | 604 | try { |
| 604 | const raw = await fs.promises.readFile(this.legacyHistoryPath(threadId), "utf8"); | 605 | const raw = await fs.promises.readFile(legacyPath, "utf8"); |
| 605 | const capped = capHistory(raw, this.historyLineLimit); | 606 | const capped = capHistory(raw, this.historyLineLimit); |
| 606 | if (capped !== raw) { | 607 | |
| 607 | await fs.promises.writeFile(this.legacyHistoryPath(threadId), capped, "utf8"); | 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 | }); | ||
| 608 | } | 617 | } |
| 618 | |||
| 609 | return capped; | 619 | return capped; |
| 610 | } catch (error) { | 620 | } catch (error) { |
| 611 | if ((error as NodeJS.ErrnoException).code === "ENOENT") { | 621 | if ((error as NodeJS.ErrnoException).code === "ENOENT") { |