From 647a12ecafc797b0b780f5ecbd9e600198d4cf17 Mon Sep 17 00:00:00 2001 From: Adam Smith Date: Sat, 28 Feb 2026 15:57:17 -0800 Subject: [PATCH] fix(opencode): show skill names instead of array indices in error message Skill.all() returns an array, so Object.keys() produced numeric indices ("0, 1, 2, ...") instead of skill names. Use .map() to extract names. Fixes #7080 --- packages/opencode/src/tool/skill.ts | 2 +- packages/opencode/test/tool/skill.test.ts | 45 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/tool/skill.ts b/packages/opencode/src/tool/skill.ts index 8fcfb592dee6..d7cc3406a421 100644 --- a/packages/opencode/src/tool/skill.ts +++ b/packages/opencode/src/tool/skill.ts @@ -62,7 +62,7 @@ export const SkillTool = Tool.define("skill", async (ctx) => { const skill = await Skill.get(params.name) if (!skill) { - const available = await Skill.all().then((x) => Object.keys(x).join(", ")) + const available = await Skill.all().then((x) => x.map((s) => s.name).join(", ")) throw new Error(`Skill "${params.name}" not found. Available skills: ${available || "none"}`) } diff --git a/packages/opencode/test/tool/skill.test.ts b/packages/opencode/test/tool/skill.test.ts index d5057ba9e7f4..e8e0f5d3beb3 100644 --- a/packages/opencode/test/tool/skill.test.ts +++ b/packages/opencode/test/tool/skill.test.ts @@ -18,6 +18,51 @@ const baseCtx: Omit = { } describe("tool.skill", () => { + test("error message lists skill names not array indices", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + const skillDir = path.join(dir, ".opencode", "skill", "existing-skill") + await Bun.write( + path.join(skillDir, "SKILL.md"), + `--- +name: existing-skill +description: An existing skill. +--- + +# Existing Skill +`, + ) + }, + }) + + const home = process.env.OPENCODE_TEST_HOME + process.env.OPENCODE_TEST_HOME = tmp.path + + try { + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const tool = await SkillTool.init() + const ctx: Tool.Context = { + ...baseCtx, + ask: async () => {}, + } + + try { + await tool.execute({ name: "nonexistent-skill" }, ctx) + expect.unreachable("should have thrown") + } catch (err: any) { + expect(err.message).toContain("existing-skill") + expect(err.message).not.toContain("Available skills: 0") + } + }, + }) + } finally { + process.env.OPENCODE_TEST_HOME = home + } + }) + test("description lists skill location URL", async () => { await using tmp = await tmpdir({ git: true,