




















@@ -4,6 +4,7 @@ import fs from "node:fs/promises";
44import os from "node:os";
55import path from "node:path";
66import { afterEach, beforeEach, describe, expect, it } from "vitest";
7+import { withEnvAsync } from "../test-utils/env.js";
78import {
89augmentChatHistoryWithCliSessionImports,
910mergeImportedChatHistoryMessages,
@@ -13,8 +14,6 @@ import {
1314} from "./cli-session-history.js";
1415import { expectRecordFields, requireRecord } from "./test-helpers.assertions.js";
151616-const ORIGINAL_HOME = process.env.HOME;
17-1817type ClaudeCliFallbackSeed = NonNullable<ReturnType<typeof readClaudeCliFallbackSeed>>;
1918type AugmentCliHistoryParams = Parameters<typeof augmentChatHistoryWithCliSessionImports>[0];
2019@@ -150,28 +149,14 @@ async function withClaudeProjectsDir<T>(
150149const filePath = path.join(projectsDir, `${sessionId}.jsonl`);
151150await fs.mkdir(projectsDir, { recursive: true });
152151await fs.writeFile(filePath, createClaudeHistoryLines(sessionId), "utf-8");
153-process.env.HOME = homeDir;
154152try {
155-return await run({ homeDir, sessionId, filePath });
153+return await withEnvAsync({ HOME: homeDir }, () => run({ homeDir, sessionId, filePath }));
156154} finally {
157-if (ORIGINAL_HOME === undefined) {
158-delete process.env.HOME;
159-} else {
160-process.env.HOME = ORIGINAL_HOME;
161-}
162155await fs.rm(root, { recursive: true, force: true });
163156}
164157}
165158166159describe("cli session history", () => {
167-afterEach(() => {
168-if (ORIGINAL_HOME === undefined) {
169-delete process.env.HOME;
170-} else {
171-process.env.HOME = ORIGINAL_HOME;
172-}
173-});
174-175160it("reads claude-cli session messages from the Claude projects store", async () => {
176161await withClaudeProjectsDir(async ({ homeDir, sessionId, filePath }) => {
177162expect(resolveClaudeCliSessionFilePath({ cliSessionId: sessionId, homeDir })).toBe(filePath);
@@ -460,25 +445,25 @@ describe("readClaudeCliFallbackSeed", () => {
460445homeDir = path.join(tmpRoot, "home");
461446projectsDir = path.join(homeDir, ".claude", "projects", "demo-workspace");
462447await fs.mkdir(projectsDir, { recursive: true });
463-process.env.HOME = homeDir;
464448});
465449466450afterEach(async () => {
467-if (ORIGINAL_HOME === undefined) {
468-delete process.env.HOME;
469-} else {
470-process.env.HOME = ORIGINAL_HOME;
471-}
472451await fs.rm(tmpRoot, { recursive: true, force: true });
473452});
474453454+function readFallbackSeed(
455+cliSessionId = SESSION_ID,
456+): ReturnType<typeof readClaudeCliFallbackSeed> {
457+return readClaudeCliFallbackSeed({ cliSessionId, homeDir });
458+}
459+475460async function writeJsonl(lines: ReadonlyArray<Record<string, unknown>>): Promise<void> {
476461const file = path.join(projectsDir, `${SESSION_ID}.jsonl`);
477462await fs.writeFile(file, `${lines.map((line) => JSON.stringify(line)).join("\n")}\n`, "utf-8");
478463}
479464480465it("returns undefined when the Claude session file does not exist", () => {
481-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
466+const seed = readFallbackSeed();
482467expect(seed).toBeUndefined();
483468});
484469@@ -505,7 +490,7 @@ describe("readClaudeCliFallbackSeed", () => {
505490},
506491]);
507492508-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
493+const seed = readFallbackSeed();
509494const fallbackSeed = requireFallbackSeed(seed, "uncompacted session");
510495expect(fallbackSeed.summaryText).toBeUndefined();
511496expect(fallbackSeed.recentTurns).toHaveLength(3);
@@ -555,7 +540,7 @@ describe("readClaudeCliFallbackSeed", () => {
555540},
556541]);
557542558-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
543+const seed = readFallbackSeed();
559544const fallbackSeed = requireFallbackSeed(seed, "compacted session");
560545expect(fallbackSeed.summaryText).toBe(
561546"User asked about deployment; agent recommended a blue-green strategy.",
@@ -587,7 +572,7 @@ describe("readClaudeCliFallbackSeed", () => {
587572},
588573]);
589574590-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
575+const seed = readFallbackSeed();
591576const fallbackSeed = requireFallbackSeed(seed, "compact boundary session");
592577// Falls back to the boundary's content so the seed at least labels
593578// that compaction happened, instead of replaying nothing.
@@ -632,7 +617,7 @@ describe("readClaudeCliFallbackSeed", () => {
632617},
633618]);
634619635-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
620+const seed = readFallbackSeed();
636621expect(seed?.summaryText).toBe("LATER summary that must win.");
637622expect(seed?.recentTurns).toHaveLength(1);
638623expect(JSON.stringify(seed?.recentTurns)).toContain("tail turn");
@@ -649,12 +634,12 @@ describe("readClaudeCliFallbackSeed", () => {
649634message: { role: "user", content: "sidechain user turn" },
650635},
651636]);
652-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
637+const seed = readFallbackSeed();
653638expect(seed).toBeUndefined();
654639});
655640656641it("rejects path-like session ids instead of escaping the Claude projects tree", () => {
657-const seed = readClaudeCliFallbackSeed({ cliSessionId: "../escape" });
642+const seed = readFallbackSeed("../escape");
658643expect(seed).toBeUndefined();
659644});
660645@@ -685,7 +670,7 @@ describe("readClaudeCliFallbackSeed", () => {
685670},
686671]);
687672688-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
673+const seed = readFallbackSeed();
689674const fallbackSeed = requireFallbackSeed(seed, "latest boundary session");
690675expect(fallbackSeed.summaryText).toBe("Conversation compacted (2)");
691676expect(fallbackSeed.summaryText).not.toBe("FIRST compact summary");
@@ -708,7 +693,7 @@ describe("readClaudeCliFallbackSeed", () => {
708693},
709694]);
710695711-const seed = readClaudeCliFallbackSeed({ cliSessionId: SESSION_ID });
696+const seed = readFallbackSeed();
712697expect(seed?.summaryText).toBe("trailing summary without boundary");
713698});
714699});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。