test(agents): share skills home env helper

This commit is contained in:
Vincent Koc
2026-04-12 11:26:29 +01:00
parent 8bf37f0b9f
commit 362e48d876
3 changed files with 68 additions and 61 deletions

View File

@@ -1,9 +1,14 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { buildWorkspaceSkillsPrompt } from "./skills.js";
import { writeSkill } from "./skills.test-helpers.js";
import {
restoreMockSkillsHomeEnv,
setMockSkillsHomeEnv,
type SkillsHomeEnvSnapshot,
} from "./skills/home-env.test-support.js";
const tempDirs: string[] = [];
@@ -31,43 +36,21 @@ async function createWorkspaceSkillDirs() {
describe("buildWorkspaceSkillsPrompt — .agents/skills/ directories", () => {
let fakeHome: string;
let previousHome: string | undefined;
let previousOpenClawHome: string | undefined;
let previousUserProfile: string | undefined;
let envSnapshot: SkillsHomeEnvSnapshot;
beforeEach(async () => {
fakeHome = await createTempDir("openclaw-home-");
previousHome = process.env.HOME;
previousOpenClawHome = process.env.OPENCLAW_HOME;
previousUserProfile = process.env.USERPROFILE;
process.env.HOME = fakeHome;
delete process.env.OPENCLAW_HOME;
delete process.env.USERPROFILE;
vi.spyOn(os, "homedir").mockReturnValue(fakeHome);
envSnapshot = setMockSkillsHomeEnv(fakeHome);
});
afterEach(async () => {
vi.restoreAllMocks();
if (previousHome === undefined) {
delete process.env.HOME;
} else {
process.env.HOME = previousHome;
}
if (previousOpenClawHome === undefined) {
delete process.env.OPENCLAW_HOME;
} else {
process.env.OPENCLAW_HOME = previousOpenClawHome;
}
if (previousUserProfile === undefined) {
delete process.env.USERPROFILE;
} else {
process.env.USERPROFILE = previousUserProfile;
}
await Promise.all(
tempDirs
.splice(0, tempDirs.length)
.map((dir) => fs.rm(dir, { recursive: true, force: true })),
);
await restoreMockSkillsHomeEnv(envSnapshot, async () => {
await Promise.all(
tempDirs
.splice(0, tempDirs.length)
.map((dir) => fs.rm(dir, { recursive: true, force: true })),
);
});
});
it("loads project .agents/skills/ above managed and below workspace", async () => {

View File

@@ -1,8 +1,13 @@
import os from "node:os";
import { formatSkillsForPrompt as upstreamFormatSkillsForPrompt } from "@mariozechner/pi-coding-agent";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import { createCanonicalFixtureSkill } from "../skills.test-helpers.js";
import {
restoreMockSkillsHomeEnv,
setMockSkillsHomeEnv,
type SkillsHomeEnvSnapshot,
} from "./home-env.test-support.js";
import { formatSkillsForPrompt, type Skill } from "./skill-contract.js";
import type { SkillEntry } from "./types.js";
import {
@@ -100,38 +105,13 @@ describe("formatSkillsCompact", () => {
});
describe("applySkillsPromptLimits (via buildWorkspaceSkillsPrompt)", () => {
let previousHome: string | undefined;
let previousOpenClawHome: string | undefined;
let previousUserProfile: string | undefined;
let envSnapshot: SkillsHomeEnvSnapshot;
beforeEach(() => {
previousHome = process.env.HOME;
previousOpenClawHome = process.env.OPENCLAW_HOME;
previousUserProfile = process.env.USERPROFILE;
process.env.HOME = "/Users/openclaw-test-user";
delete process.env.OPENCLAW_HOME;
delete process.env.USERPROFILE;
vi.spyOn(os, "homedir").mockReturnValue("/Users/openclaw-test-user");
envSnapshot = setMockSkillsHomeEnv("/Users/openclaw-test-user");
});
afterEach(() => {
vi.restoreAllMocks();
if (previousHome === undefined) {
delete process.env.HOME;
} else {
process.env.HOME = previousHome;
}
if (previousOpenClawHome === undefined) {
delete process.env.OPENCLAW_HOME;
} else {
process.env.OPENCLAW_HOME = previousOpenClawHome;
}
if (previousUserProfile === undefined) {
delete process.env.USERPROFILE;
} else {
process.env.USERPROFILE = previousUserProfile;
}
});
afterEach(() => restoreMockSkillsHomeEnv(envSnapshot));
it("respects explicit exposure metadata before compact formatting", () => {
const hidden = makeEntry({ ...makeSkill("hidden"), disableModelInvocation: true });

View File

@@ -0,0 +1,44 @@
import os from "node:os";
import { vi } from "vitest";
export type SkillsHomeEnvSnapshot = {
previousHome: string | undefined;
previousOpenClawHome: string | undefined;
previousUserProfile: string | undefined;
};
export function setMockSkillsHomeEnv(fakeHome: string): SkillsHomeEnvSnapshot {
const snapshot: SkillsHomeEnvSnapshot = {
previousHome: process.env.HOME,
previousOpenClawHome: process.env.OPENCLAW_HOME,
previousUserProfile: process.env.USERPROFILE,
};
process.env.HOME = fakeHome;
delete process.env.OPENCLAW_HOME;
delete process.env.USERPROFILE;
vi.spyOn(os, "homedir").mockReturnValue(fakeHome);
return snapshot;
}
export async function restoreMockSkillsHomeEnv(
snapshot: SkillsHomeEnvSnapshot,
cleanup?: () => Promise<void> | void,
) {
vi.restoreAllMocks();
if (snapshot.previousHome === undefined) {
delete process.env.HOME;
} else {
process.env.HOME = snapshot.previousHome;
}
if (snapshot.previousOpenClawHome === undefined) {
delete process.env.OPENCLAW_HOME;
} else {
process.env.OPENCLAW_HOME = snapshot.previousOpenClawHome;
}
if (snapshot.previousUserProfile === undefined) {
delete process.env.USERPROFILE;
} else {
process.env.USERPROFILE = snapshot.previousUserProfile;
}
await cleanup?.();
}