






















@@ -4,7 +4,8 @@ import fs from "node:fs";
44import os from "node:os";
55import path from "node:path";
66import { SessionManager } from "openclaw/plugin-sdk/agent-sessions";
7-import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
7+import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
8+import { withEnv, withEnvAsync } from "../test-utils/env.js";
89import { estimateStringChars, estimateTokensFromChars } from "../utils/cjk-chars.js";
910import { createToolSummaryPreviewTranscriptLines } from "./session-preview.test-helpers.js";
1011import {
@@ -1111,8 +1112,7 @@ describe("readSessionMessages", () => {
11111112{ message: { role: "assistant", content: "newer legacy archive" } },
11121113]);
11131114clearSessionTranscriptIndexCache();
1114-vi.stubEnv("OPENCLAW_HOME", tmpDir);
1115-try {
1115+await withEnvAsync({ OPENCLAW_HOME: tmpDir }, async () => {
11161116const fullMessages = await readSessionMessagesAsync(sessionId, storePath, undefined, {
11171117mode: "full",
11181118reason: "test cross-root reset archive fallback",
@@ -1122,9 +1122,7 @@ describe("readSessionMessages", () => {
11221122expect(fullMessages.map((message) => (message as { content?: unknown }).content)).toEqual([
11231123"newer legacy archive",
11241124]);
1125-} finally {
1126-vi.unstubAllEnvs();
1127-}
1125+});
11281126});
1129112711301128test("does not use stale generated session archives for reset archive fallback", async () => {
@@ -2242,19 +2240,14 @@ describe("readLatestSessionUsageFromTranscript", () => {
22422240});
2243224122442242describe("resolveSessionTranscriptCandidates", () => {
2245-afterEach(() => {
2246-vi.unstubAllEnvs();
2247-});
2248-22492243test("fallback candidate uses OPENCLAW_HOME instead of os.homedir()", () => {
2250-vi.stubEnv("OPENCLAW_HOME", "/srv/openclaw-home");
2251-vi.stubEnv("HOME", "/home/other");
2252-2253-const candidates = resolveSessionTranscriptCandidates("sess-1", undefined);
2254-const fallback = candidates[candidates.length - 1];
2255-expect(fallback).toBe(
2256-path.join(path.resolve("/srv/openclaw-home"), ".openclaw", "sessions", "sess-1.jsonl"),
2257-);
2244+withEnv({ OPENCLAW_HOME: "/srv/openclaw-home", HOME: "/home/other" }, () => {
2245+const candidates = resolveSessionTranscriptCandidates("sess-1", undefined);
2246+const fallback = candidates[candidates.length - 1];
2247+expect(fallback).toBe(
2248+path.join(path.resolve("/srv/openclaw-home"), ".openclaw", "sessions", "sess-1.jsonl"),
2249+);
2250+});
22582251});
22592252});
22602253@@ -2381,13 +2374,9 @@ describe("archiveSessionTranscripts", () => {
23812374storePath = nextStorePath;
23822375});
238323762384-beforeAll(() => {
2385-vi.stubEnv("OPENCLAW_HOME", tmpDir);
2386-});
2387-2388-afterAll(() => {
2389-vi.unstubAllEnvs();
2390-});
2377+function withArchiveHome<T>(fn: () => T): T {
2378+return withEnv({ OPENCLAW_HOME: tmpDir }, fn);
2379+}
2391238023922381test.each([
23932382{
@@ -2408,42 +2397,48 @@ describe("archiveSessionTranscripts", () => {
24082397] as const)(
24092398"archives transcript from default and explicit sessionFile path for $sessionId",
24102399({ transcriptFileName, buildArgs }) => {
2411-const transcriptPath = path.join(tmpDir, transcriptFileName);
2412-const args = buildArgs();
2413-fs.writeFileSync(transcriptPath, '{"type":"session"}\n', "utf-8");
2414-const archived = archiveSessionTranscripts(args);
2415-expect(archived).toHaveLength(1);
2416-expect(archived[0]).toContain(".reset.");
2417-expect(fs.existsSync(transcriptPath)).toBe(false);
2418-expect(fs.existsSync(archived[0])).toBe(true);
2400+withArchiveHome(() => {
2401+const transcriptPath = path.join(tmpDir, transcriptFileName);
2402+const args = buildArgs();
2403+fs.writeFileSync(transcriptPath, '{"type":"session"}\n', "utf-8");
2404+const archived = archiveSessionTranscripts(args);
2405+expect(archived).toHaveLength(1);
2406+expect(archived[0]).toContain(".reset.");
2407+expect(fs.existsSync(transcriptPath)).toBe(false);
2408+expect(fs.existsSync(archived[0])).toBe(true);
2409+});
24192410},
24202411);
2421241224222413test("returns empty array when no transcript files exist", () => {
2423-const archived = archiveSessionTranscripts({
2424-sessionId: "nonexistent-session",
2425- storePath,
2426-reason: "reset",
2427-});
2414+withArchiveHome(() => {
2415+const archived = archiveSessionTranscripts({
2416+sessionId: "nonexistent-session",
2417+ storePath,
2418+reason: "reset",
2419+});
242824202429-expect(archived).toStrictEqual([]);
2421+expect(archived).toStrictEqual([]);
2422+});
24302423});
2431242424322425test("skips files that do not exist and archives only existing ones", () => {
2433-const sessionId = "sess-archive-3";
2434-const transcriptPath = path.join(tmpDir, `${sessionId}.jsonl`);
2435-fs.writeFileSync(transcriptPath, '{"type":"session"}\n', "utf-8");
2426+withArchiveHome(() => {
2427+const sessionId = "sess-archive-3";
2428+const transcriptPath = path.join(tmpDir, `${sessionId}.jsonl`);
2429+fs.writeFileSync(transcriptPath, '{"type":"session"}\n', "utf-8");
243624302437-const archived = archiveSessionTranscripts({
2438- sessionId,
2439- storePath,
2440-sessionFile: "/nonexistent/path/file.jsonl",
2441-reason: "deleted",
2442-});
2431+ const archived = archiveSessionTranscripts({
2432+ sessionId,
2433+ storePath,
2434+ sessionFile: "/nonexistent/path/file.jsonl",
2435+ reason: "deleted",
2436+ });
244324372444-expect(archived).toHaveLength(1);
2445-expect(archived[0]).toContain(".deleted.");
2446-expect(fs.existsSync(transcriptPath)).toBe(false);
2438+expect(archived).toHaveLength(1);
2439+expect(archived[0]).toContain(".deleted.");
2440+expect(fs.existsSync(transcriptPath)).toBe(false);
2441+});
24472442});
24482443});
24492444此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。