Files
openclaw/src/agents/skills.resolveskillspromptforrun.test.ts
Kim fd71bc04ec fix(skills): unify runtime inclusion and available_skills exposure policy (#60852)
Merged via squash.

Prepared head SHA: 2b48b3a455
Co-authored-by: KimGLee <150593189+KimGLee@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-04-05 01:30:22 +03:00

145 lines
4.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { resolveSkillsPromptForRun } from "./skills.js";
import { createCanonicalFixtureSkill } from "./skills.test-helpers.js";
import type { SkillEntry } from "./skills/types.js";
describe("resolveSkillsPromptForRun", () => {
it("prefers snapshot prompt when available", () => {
const prompt = resolveSkillsPromptForRun({
skillsSnapshot: { prompt: "SNAPSHOT", skills: [] },
workspaceDir: "/tmp/openclaw",
});
expect(prompt).toBe("SNAPSHOT");
});
it("builds prompt from entries when snapshot is missing", () => {
const entry: SkillEntry = {
skill: createFixtureSkill({
name: "demo-skill",
description: "Demo",
filePath: "/app/skills/demo-skill/SKILL.md",
baseDir: "/app/skills/demo-skill",
source: "openclaw-bundled",
}),
frontmatter: {},
};
const prompt = resolveSkillsPromptForRun({
entries: [entry],
workspaceDir: "/tmp/openclaw",
});
expect(prompt).toContain("<available_skills>");
expect(prompt).toContain("/app/skills/demo-skill/SKILL.md");
});
it("keeps legacy entries with disableModelInvocation hidden when exposure metadata is absent", () => {
const hidden: SkillEntry = {
skill: createFixtureSkill({
name: "hidden-skill",
description: "Hidden",
filePath: "/app/skills/hidden-skill/SKILL.md",
baseDir: "/app/skills/hidden-skill",
source: "openclaw-workspace",
disableModelInvocation: true,
}),
frontmatter: {},
};
const prompt = resolveSkillsPromptForRun({
entries: [hidden],
workspaceDir: "/tmp/openclaw",
});
expect(prompt).not.toContain("/app/skills/hidden-skill/SKILL.md");
});
it("inherits agents.defaults.skills when rebuilding prompt for an agent", () => {
const visible: SkillEntry = {
skill: createFixtureSkill({
name: "github",
description: "GitHub",
filePath: "/app/skills/github/SKILL.md",
baseDir: "/app/skills/github",
source: "openclaw-workspace",
}),
frontmatter: {},
};
const hidden: SkillEntry = {
skill: createFixtureSkill({
name: "hidden-skill",
description: "Hidden",
filePath: "/app/skills/hidden-skill/SKILL.md",
baseDir: "/app/skills/hidden-skill",
source: "openclaw-workspace",
}),
frontmatter: {},
};
const prompt = resolveSkillsPromptForRun({
entries: [visible, hidden],
config: {
agents: {
defaults: {
skills: ["github"],
},
list: [{ id: "writer" }],
},
},
workspaceDir: "/tmp/openclaw",
agentId: "writer",
});
expect(prompt).toContain("/app/skills/github/SKILL.md");
expect(prompt).not.toContain("/app/skills/hidden-skill/SKILL.md");
});
it("uses agents.list[].skills as a full replacement for defaults", () => {
const inheritedEntry: SkillEntry = {
skill: createFixtureSkill({
name: "weather",
description: "Weather",
filePath: "/app/skills/weather/SKILL.md",
baseDir: "/app/skills/weather",
source: "openclaw-workspace",
}),
frontmatter: {},
};
const explicitEntry: SkillEntry = {
skill: createFixtureSkill({
name: "docs-search",
description: "Docs",
filePath: "/app/skills/docs-search/SKILL.md",
baseDir: "/app/skills/docs-search",
source: "openclaw-workspace",
}),
frontmatter: {},
};
const prompt = resolveSkillsPromptForRun({
entries: [inheritedEntry, explicitEntry],
config: {
agents: {
defaults: {
skills: ["weather"],
},
list: [{ id: "writer", skills: ["docs-search"] }],
},
},
workspaceDir: "/tmp/openclaw",
agentId: "writer",
});
expect(prompt).not.toContain("/app/skills/weather/SKILL.md");
expect(prompt).toContain("/app/skills/docs-search/SKILL.md");
});
});
function createFixtureSkill(params: {
name: string;
description: string;
filePath: string;
baseDir: string;
source: string;
disableModelInvocation?: boolean;
}): SkillEntry["skill"] {
return createCanonicalFixtureSkill(params);
}