























@@ -0,0 +1,62 @@
1+import { describe, expect, it, vi } from "vitest";
2+import { createCanonicalFixtureSkill } from "../test-support/test-helpers.js";
3+import type { SkillEntry } from "../types.js";
4+import { buildWorkspaceSkillCommandSpecs } from "./command-specs.js";
5+6+vi.mock("../../plugins/bundle-commands.js", () => ({
7+loadEnabledClaudeBundleCommands: () => [],
8+}));
9+10+vi.mock("../loading/workspace.js", () => ({
11+filterWorkspaceSkillEntriesWithOptions: (entries: SkillEntry[]) => entries,
12+loadVisibleWorkspaceSkillEntries: () => [],
13+}));
14+15+describe("buildWorkspaceSkillCommandSpecs", () => {
16+it("uses shared user-invocable skill exposure policy", () => {
17+const specs = buildWorkspaceSkillCommandSpecs("/workspace", {
18+entries: [
19+createEntry("visible"),
20+createEntry("hidden-by-exposure", {
21+exposure: {
22+includeInRuntimeRegistry: true,
23+includeInAvailableSkillsPrompt: true,
24+userInvocable: false,
25+},
26+}),
27+createEntry("hidden-by-invocation", {
28+invocation: {
29+userInvocable: false,
30+disableModelInvocation: false,
31+},
32+}),
33+],
34+});
35+36+expect(specs.map((spec) => spec.skillName)).toEqual(["visible"]);
37+});
38+});
39+40+function createEntry(
41+name: string,
42+opts?: {
43+exposure?: SkillEntry["exposure"];
44+invocation?: SkillEntry["invocation"];
45+},
46+): SkillEntry {
47+return {
48+skill: createCanonicalFixtureSkill({
49+ name,
50+description: `${name} description`,
51+filePath: `/skills/${name}/SKILL.md`,
52+baseDir: `/skills/${name}`,
53+source: "openclaw-workspace",
54+}),
55+frontmatter: {},
56+invocation: opts?.invocation ?? {
57+userInvocable: true,
58+disableModelInvocation: false,
59+},
60+exposure: opts?.exposure,
61+};
62+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。