| import fs from "node:fs/promises"; |
| import os from "node:os"; |
| import path from "node:path"; |
| import { afterAll, beforeAll } from "vitest"; |
|
|
| type HomeEnvSnapshot = { |
| HOME: string | undefined; |
| USERPROFILE: string | undefined; |
| HOMEDRIVE: string | undefined; |
| HOMEPATH: string | undefined; |
| OPENCLAW_STATE_DIR: string | undefined; |
| OPENCLAW_AGENT_DIR: string | undefined; |
| PI_CODING_AGENT_DIR: string | undefined; |
| }; |
|
|
| function snapshotHomeEnv(): HomeEnvSnapshot { |
| return { |
| HOME: process.env.HOME, |
| USERPROFILE: process.env.USERPROFILE, |
| HOMEDRIVE: process.env.HOMEDRIVE, |
| HOMEPATH: process.env.HOMEPATH, |
| OPENCLAW_STATE_DIR: process.env.OPENCLAW_STATE_DIR, |
| OPENCLAW_AGENT_DIR: process.env.OPENCLAW_AGENT_DIR, |
| PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR, |
| }; |
| } |
|
|
| function restoreHomeEnv(snapshot: HomeEnvSnapshot) { |
| for (const [key, value] of Object.entries(snapshot)) { |
| if (value === undefined) { |
| delete process.env[key]; |
| } else { |
| process.env[key] = value; |
| } |
| } |
| } |
|
|
| export function createTempHomeHarness(options: { prefix: string; beforeEachCase?: () => void }) { |
| let fixtureRoot = ""; |
| let caseId = 0; |
|
|
| beforeAll(async () => { |
| fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), options.prefix)); |
| }); |
|
|
| afterAll(async () => { |
| if (!fixtureRoot) { |
| return; |
| } |
| await fs.rm(fixtureRoot, { recursive: true, force: true }); |
| }); |
|
|
| async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> { |
| const home = path.join(fixtureRoot, `case-${++caseId}`); |
| await fs.mkdir(path.join(home, ".openclaw", "agents", "main", "sessions"), { recursive: true }); |
| const envSnapshot = snapshotHomeEnv(); |
| process.env.HOME = home; |
| process.env.USERPROFILE = home; |
| process.env.OPENCLAW_STATE_DIR = path.join(home, ".openclaw"); |
| process.env.OPENCLAW_AGENT_DIR = path.join(home, ".openclaw", "agent"); |
| process.env.PI_CODING_AGENT_DIR = path.join(home, ".openclaw", "agent"); |
|
|
| if (process.platform === "win32") { |
| const match = home.match(/^([A-Za-z]:)(.*)$/); |
| if (match) { |
| process.env.HOMEDRIVE = match[1]; |
| process.env.HOMEPATH = match[2] || "\\"; |
| } |
| } |
|
|
| try { |
| options.beforeEachCase?.(); |
| return await fn(home); |
| } finally { |
| restoreHomeEnv(envSnapshot); |
| } |
| } |
|
|
| return { withTempHome }; |
| } |
|
|
| export function makeReplyConfig(home: string) { |
| return { |
| agents: { |
| defaults: { |
| model: "anthropic/claude-opus-4-5", |
| workspace: path.join(home, "openclaw"), |
| }, |
| }, |
| channels: { |
| whatsapp: { |
| allowFrom: ["*"], |
| }, |
| }, |
| session: { store: path.join(home, "sessions.json") }, |
| }; |
| } |
|
|