diff --git a/src/agents/skills.buildworkspaceskillstatus.test.ts b/src/agents/skills.buildworkspaceskillstatus.test.ts index 5fc642d138d..f0445542862 100644 --- a/src/agents/skills.buildworkspaceskillstatus.test.ts +++ b/src/agents/skills.buildworkspaceskillstatus.test.ts @@ -14,6 +14,12 @@ afterEach(async () => { await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true }))); }); +async function createTempWorkspaceDir() { + const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-skill-status-")); + tempDirs.push(workspaceDir); + return workspaceDir; +} + function makeEntry(params: { name: string; source?: string; @@ -94,6 +100,36 @@ describe("buildWorkspaceSkillStatus", () => { expect(skill?.missing.config).toContain("browser.enabled"); expect(skill?.install[0]?.id).toBe("brew"); }); + + it("honors legacy clawdbot skill metadata requirements and install hints", async () => { + const workspaceDir = await createTempWorkspaceDir(); + await writeSkill({ + dir: path.join(workspaceDir, "skills", "legacy-skill"), + name: "legacy-skill", + description: "Legacy metadata", + metadata: + '{"clawdbot":{"requires":{"bins":["fakebin"]},"install":[{"id":"brew","kind":"brew","formula":"fakebin","bins":["fakebin"],"label":"Install fakebin"}]}}', + }); + + const report = withEnv({ PATH: "" }, () => + buildWorkspaceSkillStatus(workspaceDir, { + managedSkillsDir: path.join(workspaceDir, ".managed"), + }), + ); + const skill = report.skills.find((entry) => entry.name === "legacy-skill"); + + expect(skill).toBeDefined(); + expect(skill?.eligible).toBe(false); + expect(skill?.requirements.bins).toEqual(["fakebin"]); + expect(skill?.missing.bins).toEqual(["fakebin"]); + expect(skill?.install[0]).toMatchObject({ + id: "brew", + kind: "brew", + label: "Install fakebin", + bins: ["fakebin"], + }); + }); + it("respects OS-gated skills", async () => { const entry = makeEntry({ name: "os-skill", diff --git a/src/compat/legacy-names.ts b/src/compat/legacy-names.ts index f452876825b..684f21b2bab 100644 --- a/src/compat/legacy-names.ts +++ b/src/compat/legacy-names.ts @@ -1,6 +1,6 @@ export const PROJECT_NAME = "openclaw" as const; -export const LEGACY_PROJECT_NAMES = [] as const; +export const LEGACY_PROJECT_NAMES = ["clawdbot"] as const; export const MANIFEST_KEY = PROJECT_NAME; diff --git a/src/shared/frontmatter.test.ts b/src/shared/frontmatter.test.ts index 69d48e05b57..778359b41c4 100644 --- a/src/shared/frontmatter.test.ts +++ b/src/shared/frontmatter.test.ts @@ -49,6 +49,16 @@ describe("shared/frontmatter", () => { ).toEqual({ foo: 2 }); }); + test("resolveOpenClawManifestBlock reads legacy manifest keys", () => { + expect( + resolveOpenClawManifestBlock({ + frontmatter: { + metadata: "{ clawdbot: { requires: { bins: ['op'] }, install: [] } }", + }, + }), + ).toEqual({ requires: { bins: ["op"] }, install: [] }); + }); + test("resolveOpenClawManifestBlock returns undefined for invalid input", () => { expect(resolveOpenClawManifestBlock({ frontmatter: {} })).toBeUndefined(); expect(