@@ -251,4 +251,146 @@ describe('UseSkillTool', () => {
251251 expect ( result ) . toBe ( false ) ;
252252 } ) ;
253253 } ) ;
254+
255+ describe ( 'skill name matching' , ( ) => {
256+ it ( 'should match skill by exact name (case-insensitive)' , async ( ) => {
257+ const mockSkill = {
258+ id : 'marketplace:plugin:pptx' ,
259+ name : 'pptx' ,
260+ description : 'Test skill' ,
261+ pluginId : 'marketplace:plugin' ,
262+ marketplaceId : 'marketplace' ,
263+ path : '/mock/path' ,
264+ skillFilePath : '/mock/path/SKILL.md' ,
265+ metadata : { name : 'pptx' } ,
266+ enabled : true ,
267+ loadLevel : SkillLoadLevel . RESOURCES ,
268+ scripts : [ ] ,
269+ } ;
270+
271+ mockLoaderInstance = {
272+ loadEnabledSkills : ( ) => [ mockSkill ] ,
273+ } ;
274+ mockInjectorInstance = {
275+ loadSkillLevel2 : ( ) => '# Test\n\nTest content' ,
276+ } ;
277+
278+ // Test case-insensitive matching
279+ const result1 = await useSkillTool . execute ( { skillName : 'pptx' } , mockAbortSignal ) ;
280+ expect ( result1 . returnDisplay ) . toContain ( '✅ Loaded skill' ) ;
281+
282+ const result2 = await useSkillTool . execute ( { skillName : 'PPTX' } , mockAbortSignal ) ;
283+ expect ( result2 . returnDisplay ) . toContain ( '✅ Loaded skill' ) ;
284+
285+ const result3 = await useSkillTool . execute ( { skillName : 'PpTx' } , mockAbortSignal ) ;
286+ expect ( result3 . returnDisplay ) . toContain ( '✅ Loaded skill' ) ;
287+ } ) ;
288+
289+ it ( 'should match skill by ID suffix' , async ( ) => {
290+ const mockSkill = {
291+ id : 'marketplace:plugin:my-skill' ,
292+ name : 'my-skill' ,
293+ description : 'Test skill' ,
294+ pluginId : 'marketplace:plugin' ,
295+ marketplaceId : 'marketplace' ,
296+ path : '/mock/path' ,
297+ skillFilePath : '/mock/path/SKILL.md' ,
298+ metadata : { name : 'my-skill' } ,
299+ enabled : true ,
300+ loadLevel : SkillLoadLevel . RESOURCES ,
301+ scripts : [ ] ,
302+ } ;
303+
304+ mockLoaderInstance = {
305+ loadEnabledSkills : ( ) => [ mockSkill ] ,
306+ } ;
307+ mockInjectorInstance = {
308+ loadSkillLevel2 : ( ) => '# Test\n\nTest content' ,
309+ } ;
310+
311+ // Should match by just the skill name
312+ const result = await useSkillTool . execute ( { skillName : 'my-skill' } , mockAbortSignal ) ;
313+ expect ( result . returnDisplay ) . toContain ( '✅ Loaded skill' ) ;
314+ } ) ;
315+
316+ it ( 'should match skill by full ID' , async ( ) => {
317+ const mockSkill = {
318+ id : 'marketplace:plugin:my-skill' ,
319+ name : 'my-skill' ,
320+ description : 'Test skill' ,
321+ pluginId : 'marketplace:plugin' ,
322+ marketplaceId : 'marketplace' ,
323+ path : '/mock/path' ,
324+ skillFilePath : '/mock/path/SKILL.md' ,
325+ metadata : { name : 'my-skill' } ,
326+ enabled : true ,
327+ loadLevel : SkillLoadLevel . RESOURCES ,
328+ scripts : [ ] ,
329+ } ;
330+
331+ mockLoaderInstance = {
332+ loadEnabledSkills : ( ) => [ mockSkill ] ,
333+ } ;
334+ mockInjectorInstance = {
335+ loadSkillLevel2 : ( ) => '# Test\n\nTest content' ,
336+ } ;
337+
338+ // Should match by full ID
339+ const result = await useSkillTool . execute (
340+ { skillName : 'marketplace:plugin:my-skill' } ,
341+ mockAbortSignal
342+ ) ;
343+ expect ( result . returnDisplay ) . toContain ( '✅ Loaded skill' ) ;
344+ } ) ;
345+
346+ it ( 'should provide detailed debug info when skill not found' , async ( ) => {
347+ const mockSkills = [
348+ {
349+ id : 'marketplace:plugin1:skill1' ,
350+ name : 'skill1' ,
351+ description : 'Skill 1' ,
352+ pluginId : 'marketplace:plugin1' ,
353+ marketplaceId : 'marketplace' ,
354+ path : '/mock/path1' ,
355+ skillFilePath : '/mock/path1/SKILL.md' ,
356+ metadata : { name : 'skill1' } ,
357+ enabled : true ,
358+ loadLevel : SkillLoadLevel . RESOURCES ,
359+ scripts : [ ] ,
360+ } ,
361+ {
362+ id : 'marketplace:plugin2:skill2' ,
363+ name : 'skill2' ,
364+ description : 'Skill 2' ,
365+ pluginId : 'marketplace:plugin2' ,
366+ marketplaceId : 'marketplace' ,
367+ path : '/mock/path2' ,
368+ skillFilePath : '/mock/path2/SKILL.md' ,
369+ metadata : { name : 'skill2' } ,
370+ enabled : true ,
371+ loadLevel : SkillLoadLevel . RESOURCES ,
372+ scripts : [ ] ,
373+ } ,
374+ ] ;
375+
376+ mockLoaderInstance = {
377+ loadEnabledSkills : ( ) => mockSkills ,
378+ } ;
379+
380+ const result = await useSkillTool . execute ( { skillName : 'nonexistent' } , mockAbortSignal ) ;
381+
382+ // Should provide debug information
383+ expect ( result . llmContent ) . toContain ( '❌ Skill "nonexistent" not found' ) ;
384+ expect ( result . llmContent ) . toContain ( '📊 Debug Information' ) ;
385+ expect ( result . llmContent ) . toContain ( 'Total skills loaded: 2' ) ;
386+ expect ( result . llmContent ) . toContain ( 'Normalized search: "nonexistent"' ) ;
387+ expect ( result . llmContent ) . toContain ( 'By name:' ) ;
388+ expect ( result . llmContent ) . toContain ( 'skill1' ) ;
389+ expect ( result . llmContent ) . toContain ( 'skill2' ) ;
390+ expect ( result . llmContent ) . toContain ( 'By ID:' ) ;
391+ expect ( result . llmContent ) . toContain ( 'marketplace:plugin1:skill1' ) ;
392+ expect ( result . llmContent ) . toContain ( 'marketplace:plugin2:skill2' ) ;
393+ expect ( result . llmContent ) . toContain ( 'Inconsistency between list and use_skill' ) ;
394+ } ) ;
395+ } ) ;
254396} ) ;
0 commit comments