Showing the changes to packages/client-runtime/src (2 of 16 files). Show all
Unified · Split
| @@ -108,6 +108,30 @@ describe("getProviderSkillsForSlashMenu", () => { · 107 unmodified lines | |||
| 108 | }); | 108 | }); |
| 109 | }); | 109 | }); |
| 110 | 110 | ||
| 111 | describe("getProviderSkillsForSlashMenu", () => { | ||
| 112 | it("drops a skill the provider reserves for the agent", () => { | ||
| 113 | const skills = [ | ||
| 114 | { | ||
| 115 | name: "legacy-system-context", | ||
| 116 | path: "/Users/matt/.claude/skills/legacy-system-context/SKILL.md", | ||
| 117 | enabled: true, | ||
| 118 | userInvocable: false, | ||
| 119 | }, | ||
| 120 | { | ||
| 121 | name: "deploy", | ||
| 122 | path: "/Users/matt/.claude/skills/deploy/SKILL.md", | ||
| 123 | enabled: true, | ||
| 124 | // Reserved for the user, not the agent: still a valid pick. | ||
| 125 | userInvocationOnly: true, | ||
| 126 | }, | ||
| 127 | ]; | ||
| 128 | |||
| 129 | expect(getProviderSkillsForSlashMenu(skills, true).map((skill) => skill.name)).toEqual([ | ||
| 130 | "deploy", | ||
| 131 | ]); | ||
| 132 | }); | ||
| 133 | }); | ||
| 134 | |||
| 111 | describe("getProviderSlashCommandsForSlashMenu", () => { | 135 | describe("getProviderSlashCommandsForSlashMenu", () => { |
| 112 | const commands = [ | 136 | const commands = [ |
| 113 | { name: "ask-matt", description: "Ask which skill fits your situation." }, | 137 | { name: "ask-matt", description: "Ask which skill fits your situation." }, |
| @@ -39,12 +39,25 @@ export function dedupeProviderSkillsByName( · 38 unmodified lines | |||
| 39 | }); | 39 | }); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | /** | ||
| 43 | * Whether a composer pick can start this skill. A skill switched off in the | ||
| 44 | * provider's settings will not run, and one the provider reserves for the | ||
| 45 | * agent (Claude Code's `user-invocable: false`) rejects a user invocation. | ||
| 46 | * Everything else, including skills the agent may not start on its own, is | ||
| 47 | * fair game: the server dispatches the pick in the provider's native form. | ||
| 48 | */ | ||
| 49 | export function isProviderSkillUserInvocable( | ||
| 50 | skill: Pick<ServerProviderSkill, "enabled" | "userInvocable">, | ||
| 51 | ): boolean { | ||
| 52 | return skill.enabled && skill.userInvocable !== false; | ||
| 53 | } | ||
| 54 | |||
| 42 | export function getProviderSkillsForSlashMenu( | 55 | export function getProviderSkillsForSlashMenu( |
| 43 | skills: ReadonlyArray<ServerProviderSkill>, | 56 | skills: ReadonlyArray<ServerProviderSkill>, |
| 44 | showSkillsInSlashMenu: boolean, | 57 | showSkillsInSlashMenu: boolean, |
| 45 | ): ServerProviderSkill[] { | 58 | ): ServerProviderSkill[] { |
| 46 | return showSkillsInSlashMenu | 59 | return showSkillsInSlashMenu |
| 47 | ? dedupeProviderSkillsByName(skills.filter((skill) => skill.enabled)) | 60 | ? dedupeProviderSkillsByName(skills.filter(isProviderSkillUserInvocable)) |
| 48 | : []; | 61 | : []; |
| 49 | } | 62 | } |
| 50 | 63 | ||