diff --git a/packages/opencode/test/command/command-resilience.test.ts b/packages/opencode/test/command/command-resilience.test.ts index 6c01fbe1b..c54b64fee 100644 --- a/packages/opencode/test/command/command-resilience.test.ts +++ b/packages/opencode/test/command/command-resilience.test.ts @@ -90,6 +90,49 @@ describe("Command module", () => { expect(cmd).toBeUndefined() }) }) + + test("altimate builtin commands are registered", async () => { + await withInstance(async () => { + const commands = await Command.list() + const names = commands.map((c) => c.name) + expect(names).toContain("configure-claude") + expect(names).toContain("configure-codex") + expect(names).toContain("discover-and-add-mcps") + }) + }) + + test("discover-and-add-mcps has correct metadata", async () => { + await withInstance(async () => { + const cmd = await Command.get("discover-and-add-mcps") + expect(cmd).toBeDefined() + expect(cmd.source).toBe("command") + expect(cmd.description).toBe("discover MCP servers from external AI tool configs and add them") + }) + }) + + test("discover-and-add-mcps template references mcp_discover tool", async () => { + await withInstance(async () => { + const cmd = await Command.get("discover-and-add-mcps") + const template = await cmd.template + expect(template).toContain("mcp_discover") + }) + }) + + test("discover-and-add-mcps has $ARGUMENTS hint", async () => { + await withInstance(async () => { + const cmd = await Command.get("discover-and-add-mcps") + expect(cmd.hints).toContain("$ARGUMENTS") + }) + }) + + test("configure-claude has correct metadata", async () => { + await withInstance(async () => { + const cmd = await Command.get("configure-claude") + expect(cmd).toBeDefined() + expect(cmd.source).toBe("command") + expect(cmd.description).toBe("configure /altimate command in Claude Code") + }) + }) }) describe("user-defined commands from config", () => { diff --git a/packages/opencode/test/command/hints.test.ts b/packages/opencode/test/command/hints.test.ts new file mode 100644 index 000000000..b62d5a508 --- /dev/null +++ b/packages/opencode/test/command/hints.test.ts @@ -0,0 +1,34 @@ +import { describe, test, expect } from "bun:test" +import { Command } from "../../src/command/index" + +describe("Command.hints: template placeholder extraction", () => { + test("extracts numbered placeholders in sorted order", () => { + expect(Command.hints("Do $2 then $1")).toEqual(["$1", "$2"]) + }) + + test("deduplicates repeated placeholders", () => { + expect(Command.hints("Use $1 and $1 again")).toEqual(["$1"]) + }) + + test("extracts $ARGUMENTS", () => { + expect(Command.hints("Run with $ARGUMENTS")).toEqual(["$ARGUMENTS"]) + }) + + test("extracts both numbered and $ARGUMENTS", () => { + expect(Command.hints("Do $1 with $ARGUMENTS")).toEqual(["$1", "$ARGUMENTS"]) + }) + + test("returns empty for templates with no placeholders", () => { + expect(Command.hints("Just a plain prompt")).toEqual([]) + }) + + test("does not extract $ARGUMENTS as numbered", () => { + // $ARGUMENTS should only appear via the explicit check, not the numbered regex + expect(Command.hints("$ARGUMENTS only")).toEqual(["$ARGUMENTS"]) + }) + + test("handles double-digit placeholders with lexicographic sort", () => { + // Note: sort is lexicographic, so $10 < $2. This documents current behavior. + expect(Command.hints("$10 then $2 then $1")).toEqual(["$1", "$10", "$2"]) + }) +})