@agents-inc/cli 0.47.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +113 -118
- package/config/skill-categories.yaml +344 -0
- package/config/skill-rules.yaml +740 -0
- package/config/stacks.yaml +0 -1
- package/dist/{chunk-CJFWO46A.js → chunk-26MXZUHU.js} +2 -2
- package/dist/{chunk-KQ27IDYL.js → chunk-2BWCR762.js} +2 -3
- package/dist/chunk-2BWCR762.js.map +1 -0
- package/dist/chunk-3VOL4WEG.js +31 -0
- package/dist/chunk-3VOL4WEG.js.map +1 -0
- package/dist/chunk-4QWDB2MD.js +571 -0
- package/dist/chunk-4QWDB2MD.js.map +1 -0
- package/dist/{chunk-LJ5E4GXC.js → chunk-4R52TQ3K.js} +2 -2
- package/dist/{chunk-SPSGZWTZ.js → chunk-5FCHJLM7.js} +34 -16
- package/dist/chunk-5FCHJLM7.js.map +1 -0
- package/dist/chunk-5FPIKTSA.js +40 -0
- package/dist/chunk-5FPIKTSA.js.map +1 -0
- package/dist/{chunk-HLTJK3XB.js → chunk-5L724R4C.js} +5 -6
- package/dist/{chunk-HLTJK3XB.js.map → chunk-5L724R4C.js.map} +1 -1
- package/dist/{chunk-JTTTXGHX.js → chunk-7LV4V6A4.js} +4 -4
- package/dist/{chunk-FTD5Z6QD.js → chunk-AWP5A6IM.js} +15 -7
- package/dist/chunk-AWP5A6IM.js.map +1 -0
- package/dist/chunk-C3Q43WLC.js +118 -0
- package/dist/chunk-C3Q43WLC.js.map +1 -0
- package/dist/{chunk-B4QYXVPZ.js → chunk-CMNKHDOX.js} +2 -2
- package/dist/{chunk-TBB3THSL.js → chunk-D72AFYQR.js} +8 -13
- package/dist/chunk-D72AFYQR.js.map +1 -0
- package/dist/{chunk-QR2TM4OY.js → chunk-DCE423KO.js} +46 -30
- package/dist/chunk-DCE423KO.js.map +1 -0
- package/dist/chunk-GBOW6FUW.js +74 -0
- package/dist/chunk-GBOW6FUW.js.map +1 -0
- package/dist/{chunk-GFDGYQ6M.js → chunk-HMSHB5EQ.js} +569 -269
- package/dist/chunk-HMSHB5EQ.js.map +1 -0
- package/dist/{chunk-NRCKIHND.js → chunk-HYEUETIC.js} +2 -2
- package/dist/{chunk-OEJDFGAF.js → chunk-I6IOGZSZ.js} +61 -52
- package/dist/chunk-I6IOGZSZ.js.map +1 -0
- package/dist/{chunk-3APMMQUA.js → chunk-JFF7P4LC.js} +30 -93
- package/dist/chunk-JFF7P4LC.js.map +1 -0
- package/dist/{chunk-N5OCAAXY.js → chunk-JWYRXE6C.js} +2 -2
- package/dist/{chunk-TWDVLTU6.js → chunk-KAO3LKB5.js} +3 -3
- package/dist/{chunk-XTRPYUWK.js → chunk-KQOU4POU.js} +26 -28
- package/dist/chunk-KQOU4POU.js.map +1 -0
- package/dist/{chunk-YTRFL3MR.js → chunk-M3GQ2R3E.js} +29 -28
- package/dist/chunk-M3GQ2R3E.js.map +1 -0
- package/dist/{chunk-LNA6M2IE.js → chunk-PGY5XROM.js} +2 -2
- package/dist/chunk-PGY5XROM.js.map +1 -0
- package/dist/{chunk-VAQJLHUW.js → chunk-QB5HHTAA.js} +8 -19
- package/dist/chunk-QB5HHTAA.js.map +1 -0
- package/dist/{chunk-VSZ5GDET.js → chunk-QYLCINGC.js} +2 -2
- package/dist/{chunk-IRJADQM7.js → chunk-RA2IPRO2.js} +2 -2
- package/dist/{chunk-DC333ZDC.js → chunk-RDWGYKDY.js} +4 -4
- package/dist/{chunk-FXQYEXLS.js → chunk-RFKDGJAJ.js} +26 -57
- package/dist/chunk-RFKDGJAJ.js.map +1 -0
- package/dist/{chunk-HPJP3HFD.js → chunk-SPFHPHYL.js} +7 -7
- package/dist/{chunk-EZ46ZTAQ.js → chunk-U2W5SENM.js} +3 -3
- package/dist/{chunk-MVEYK55V.js → chunk-U7X4V4HE.js} +2 -2
- package/dist/{chunk-INKJBMPJ.js → chunk-UAD3SC27.js} +4 -12
- package/dist/chunk-UAD3SC27.js.map +1 -0
- package/dist/{chunk-C4QI54PN.js → chunk-WBHPCBVN.js} +57 -34
- package/dist/chunk-WBHPCBVN.js.map +1 -0
- package/dist/chunk-WFFV254H.js +314 -0
- package/dist/chunk-WFFV254H.js.map +1 -0
- package/dist/{chunk-ZWAL2ZY7.js → chunk-WJHFV6RI.js} +3 -2
- package/dist/chunk-WJHFV6RI.js.map +1 -0
- package/dist/{chunk-2RQYJFKA.js → chunk-WLZHCM7O.js} +2 -2
- package/dist/{chunk-DVW6ASTO.js → chunk-XDSVV5GZ.js} +4 -4
- package/dist/{chunk-JZHIF3K7.js → chunk-YDYRAXSY.js} +57 -27
- package/dist/chunk-YDYRAXSY.js.map +1 -0
- package/dist/commands/build/marketplace.js +4 -4
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +11 -9
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +4 -4
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/set-project.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/config/unset-project.js +4 -4
- package/dist/commands/diff.js +4 -4
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/edit.js +58 -52
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +4 -4
- package/dist/commands/import/skill.js +7 -8
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +5 -5
- package/dist/commands/init.js +40 -435
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +4 -4
- package/dist/commands/new/agent.js +11 -10
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +24 -5
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +15 -209
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +11 -7
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +7 -8
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +6 -6
- package/dist/commands/update.js +6 -6
- package/dist/commands/validate.js +62 -250
- package/dist/commands/validate.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +3 -2
- package/dist/components/wizard/category-grid.test.js +112 -58
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/checkbox-grid.js +5 -3
- package/dist/components/wizard/checkbox-grid.test.js +5 -4
- package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
- package/dist/components/wizard/domain-selection.js +11 -9
- package/dist/components/wizard/help-modal.js +2 -2
- package/dist/components/wizard/menu-item.js +1 -1
- package/dist/components/wizard/search-modal.js +2 -2
- package/dist/components/wizard/search-modal.test.js +2 -2
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +2 -2
- package/dist/components/wizard/selection-card.js +2 -2
- package/dist/components/wizard/source-grid.js +4 -3
- package/dist/components/wizard/source-grid.test.js +4 -3
- package/dist/components/wizard/source-grid.test.js.map +1 -1
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -8
- package/dist/components/wizard/step-agents.test.js +18 -17
- package/dist/components/wizard/step-agents.test.js.map +1 -1
- package/dist/components/wizard/step-build.js +9 -8
- package/dist/components/wizard/step-build.test.js +17 -35
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +4 -4
- package/dist/components/wizard/step-confirm.test.js +8 -8
- package/dist/components/wizard/step-refine.js +2 -2
- package/dist/components/wizard/step-refine.test.js +2 -2
- package/dist/components/wizard/step-settings.js +7 -5
- package/dist/components/wizard/step-settings.test.js +10 -8
- package/dist/components/wizard/step-settings.test.js.map +1 -1
- package/dist/components/wizard/step-sources.js +11 -10
- package/dist/components/wizard/step-sources.test.js +12 -11
- package/dist/components/wizard/step-sources.test.js.map +1 -1
- package/dist/components/wizard/step-stack.js +15 -12
- package/dist/components/wizard/step-stack.test.js +16 -13
- package/dist/components/wizard/step-stack.test.js.map +1 -1
- package/dist/components/wizard/view-title.js +2 -2
- package/dist/components/wizard/wizard-layout.js +8 -8
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +2 -2
- package/dist/components/wizard/wizard.js +27 -25
- package/dist/config/skill-categories.yaml +344 -0
- package/dist/config/skill-rules.yaml +740 -0
- package/dist/config/stacks.yaml +0 -1
- package/dist/hooks/init.js +55 -3
- package/dist/hooks/init.js.map +1 -1
- package/dist/{source-manager-Q34LTUVM.js → source-manager-BVB2SG73.js} +4 -4
- package/dist/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
- package/dist/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
- package/dist/src/agents/meta/agent-summoner/examples.md +2 -2
- package/dist/src/agents/meta/agent-summoner/output-format.md +1 -1
- package/dist/src/agents/meta/agent-summoner/workflow.md +5 -7
- package/{src/agents/meta/documentor/agent.yaml → dist/src/agents/meta/documentor/metadata.yaml} +1 -0
- package/dist/stores/wizard-store.js +5 -5
- package/dist/stores/wizard-store.test.js +79 -27
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +5 -1
- package/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
- package/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
- package/src/agents/meta/agent-summoner/examples.md +2 -2
- package/src/agents/meta/agent-summoner/output-format.md +1 -1
- package/src/agents/meta/agent-summoner/workflow.md +5 -7
- package/{dist/src/agents/meta/documentor/agent.yaml → src/agents/meta/documentor/metadata.yaml} +1 -0
- package/src/schemas/agent.schema.json +1 -1
- package/src/schemas/metadata.schema.json +2 -5
- package/src/schemas/project-config.schema.json +0 -3
- package/src/schemas/project-source-config.schema.json +4 -1
- package/config/skills-matrix.yaml +0 -918
- package/dist/chunk-3APMMQUA.js.map +0 -1
- package/dist/chunk-C4QI54PN.js.map +0 -1
- package/dist/chunk-FMQ3A7W4.js +0 -29
- package/dist/chunk-FMQ3A7W4.js.map +0 -1
- package/dist/chunk-FTD5Z6QD.js.map +0 -1
- package/dist/chunk-FXQYEXLS.js.map +0 -1
- package/dist/chunk-GFDGYQ6M.js.map +0 -1
- package/dist/chunk-INKJBMPJ.js.map +0 -1
- package/dist/chunk-JZHIF3K7.js.map +0 -1
- package/dist/chunk-KQ27IDYL.js.map +0 -1
- package/dist/chunk-LNA6M2IE.js.map +0 -1
- package/dist/chunk-M4P5YJ45.js +0 -99
- package/dist/chunk-M4P5YJ45.js.map +0 -1
- package/dist/chunk-OEJDFGAF.js.map +0 -1
- package/dist/chunk-QR2TM4OY.js.map +0 -1
- package/dist/chunk-SPSGZWTZ.js.map +0 -1
- package/dist/chunk-TBB3THSL.js.map +0 -1
- package/dist/chunk-VAQJLHUW.js.map +0 -1
- package/dist/chunk-XTRPYUWK.js.map +0 -1
- package/dist/chunk-YTRFL3MR.js.map +0 -1
- package/dist/chunk-ZWAL2ZY7.js.map +0 -1
- package/dist/config/skills-matrix.yaml +0 -918
- package/dist/src/agents/migration/cli-migrator/agent.yaml +0 -12
- package/dist/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
- package/dist/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
- package/dist/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
- package/dist/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
- package/dist/src/agents/migration/cli-migrator/intro.md +0 -15
- package/dist/src/agents/migration/cli-migrator/output-format.md +0 -164
- package/dist/src/agents/migration/cli-migrator/workflow.md +0 -230
- package/src/agents/migration/cli-migrator/agent.yaml +0 -12
- package/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
- package/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
- package/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
- package/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
- package/src/agents/migration/cli-migrator/intro.md +0 -15
- package/src/agents/migration/cli-migrator/output-format.md +0 -164
- package/src/agents/migration/cli-migrator/workflow.md +0 -230
- package/src/schemas/skills-matrix.schema.json +0 -179
- /package/dist/{chunk-CJFWO46A.js.map → chunk-26MXZUHU.js.map} +0 -0
- /package/dist/{chunk-LJ5E4GXC.js.map → chunk-4R52TQ3K.js.map} +0 -0
- /package/dist/{chunk-JTTTXGHX.js.map → chunk-7LV4V6A4.js.map} +0 -0
- /package/dist/{chunk-B4QYXVPZ.js.map → chunk-CMNKHDOX.js.map} +0 -0
- /package/dist/{chunk-NRCKIHND.js.map → chunk-HYEUETIC.js.map} +0 -0
- /package/dist/{chunk-N5OCAAXY.js.map → chunk-JWYRXE6C.js.map} +0 -0
- /package/dist/{chunk-TWDVLTU6.js.map → chunk-KAO3LKB5.js.map} +0 -0
- /package/dist/{chunk-VSZ5GDET.js.map → chunk-QYLCINGC.js.map} +0 -0
- /package/dist/{chunk-IRJADQM7.js.map → chunk-RA2IPRO2.js.map} +0 -0
- /package/dist/{chunk-DC333ZDC.js.map → chunk-RDWGYKDY.js.map} +0 -0
- /package/dist/{chunk-HPJP3HFD.js.map → chunk-SPFHPHYL.js.map} +0 -0
- /package/dist/{chunk-EZ46ZTAQ.js.map → chunk-U2W5SENM.js.map} +0 -0
- /package/dist/{chunk-MVEYK55V.js.map → chunk-U7X4V4HE.js.map} +0 -0
- /package/dist/{chunk-2RQYJFKA.js.map → chunk-WLZHCM7O.js.map} +0 -0
- /package/dist/{chunk-DVW6ASTO.js.map → chunk-XDSVV5GZ.js.map} +0 -0
- /package/dist/{source-manager-Q34LTUVM.js.map → source-manager-BVB2SG73.js.map} +0 -0
- /package/dist/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/dist/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
- /package/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/search.tsx","../../src/cli/components/skill-search/index.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { SkillSearch, type SkillSearchResult } from \"../components/skill-search/index.js\";\nimport type { SourcedSkill } from \"../components/skill-search/skill-search.js\";\nimport { DEFAULT_SKILLS_SUBDIR, LOCAL_SKILLS_PATH, STANDARD_FILES } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { resolveAllSources, type SourceEntry } from \"../lib/configuration/index.js\";\nimport { loadSkillsMatrixFromSource, fetchFromSource } from \"../lib/loading/index.js\";\nimport type { CategoryPath, ResolvedSkill, SkillId } from \"../types/index.js\";\nimport { listDirectories, fileExists, copy, ensureDir } from \"../utils/fs.js\";\nimport { SUCCESS_MESSAGES, STATUS_MESSAGES, INFO_MESSAGES } from \"../utils/messages.js\";\n\nconst MAX_DESCRIPTION_WIDTH = 50;\n\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return `${str.slice(0, maxLength - 3)}...`;\n}\n\nfunction matchesQuery(skill: ResolvedSkill, query: string): boolean {\n const lowerQuery = query.toLowerCase();\n\n if (skill.id.toLowerCase().includes(lowerQuery)) return true;\n if (skill.displayName?.toLowerCase().includes(lowerQuery)) return true;\n if (skill.description.toLowerCase().includes(lowerQuery)) return true;\n if (skill.category.toLowerCase().includes(lowerQuery)) return true;\n\n return skill.tags.some((tag) => tag.toLowerCase().includes(lowerQuery));\n}\n\nfunction matchesCategory(skill: ResolvedSkill, category: CategoryPath): boolean {\n const lowerCategory = category.toLowerCase();\n return skill.category.toLowerCase().includes(lowerCategory);\n}\n\nfunction toSourcedSkill(\n skill: ResolvedSkill,\n sourceName: string,\n sourceUrl?: string,\n): SourcedSkill {\n return {\n ...skill,\n sourceName,\n sourceUrl,\n };\n}\n\nasync function fetchSkillsFromSource(\n source: SourceEntry,\n forceRefresh: boolean,\n): Promise<SourcedSkill[]> {\n try {\n const result = await fetchFromSource(source.url, { forceRefresh });\n const skillsDir = path.join(result.path, DEFAULT_SKILLS_SUBDIR);\n\n if (!(await fileExists(skillsDir))) {\n return [];\n }\n\n const skillDirs = await listDirectories(skillsDir);\n const skills: SourcedSkill[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n if (await fileExists(skillMdPath)) {\n skills.push({\n // Directory name is an untyped string — cast at data boundary\n id: skillDir as SkillId,\n description: `Skill from ${source.name}`,\n // Synthetic category for third-party sources — not in CategoryPath union\n category: \"imported\" as CategoryPath,\n categoryExclusive: false,\n tags: [],\n author: `@${source.name}`,\n conflictsWith: [],\n recommends: [],\n requires: [],\n alternatives: [],\n discourages: [],\n compatibleWith: [],\n requiresSetup: [],\n providesSetupFor: [],\n sourceName: source.name,\n sourceUrl: source.url,\n path: path.join(skillsDir, skillDir),\n });\n }\n }\n\n return skills;\n } catch {\n // Source unavailable, return empty\n return [];\n }\n}\n\nexport default class Search extends BaseCommand {\n static summary = \"Search available skills\";\n static description =\n \"Search skills by ID, alias, description, category, or tags. \" +\n \"Run without arguments or with -i for interactive mode with multi-select.\";\n\n static examples = [\n {\n description: \"Search for React skills\",\n command: \"<%= config.bin %> search react\",\n },\n {\n description: \"Interactive search mode\",\n command: \"<%= config.bin %> search\",\n },\n {\n description: \"Interactive with pre-filled query\",\n command: \"<%= config.bin %> search -i react\",\n },\n {\n description: \"Search with category filter\",\n command: \"<%= config.bin %> search state -c frontend\",\n },\n ];\n\n static args = {\n query: Args.string({\n description: \"Search query (matches name, description, category, tags)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n interactive: Flags.boolean({\n char: \"i\",\n description: \"Launch interactive search with multi-select\",\n default: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Filter by category\",\n required: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Search);\n const projectDir = process.cwd();\n\n const isInteractive = flags.interactive || !args.query;\n\n if (isInteractive) {\n await this.runInteractive(args.query, flags.refresh, projectDir);\n } else {\n await this.runStatic(args.query!, flags);\n }\n }\n\n private async runInteractive(\n initialQuery: string | undefined,\n forceRefresh: boolean,\n projectDir: string,\n ): Promise<void> {\n this.log(\"Loading skills from all sources...\");\n\n try {\n const { matrix, sourcePath } = await loadSkillsMatrixFromSource({\n sourceFlag: undefined,\n projectDir,\n forceRefresh,\n });\n\n const primarySkills = Object.values(matrix.skills)\n .filter((skill): skill is ResolvedSkill => skill !== undefined)\n .map((skill) => toSourcedSkill(skill, \"marketplace\", sourcePath));\n\n const { extras } = await resolveAllSources(projectDir);\n\n const extraSkillArrays = await Promise.all(\n extras.map((source) => fetchSkillsFromSource(source, forceRefresh)),\n );\n\n const allSkills: SourcedSkill[] = [...primarySkills, ...extraSkillArrays.flat()];\n const sourceCount = 1 + extras.length;\n\n this.log(`Loaded ${allSkills.length} skills from ${sourceCount} source(s)`);\n this.log(\"\");\n\n const searchResultPromise = new Promise<SkillSearchResult>((resolve) => {\n const { waitUntilExit } = render(\n <SkillSearch\n skills={allSkills}\n sourceCount={sourceCount}\n initialQuery={initialQuery}\n onComplete={(result) => {\n resolve(result);\n }}\n onCancel={() => {\n resolve({ selectedSkills: [], cancelled: true });\n }}\n />,\n );\n\n waitUntilExit().then(() => {\n resolve({ selectedSkills: [], cancelled: true });\n });\n });\n\n const searchResult = await searchResultPromise;\n\n if (searchResult.cancelled) {\n this.log(\"Search cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (searchResult.selectedSkills.length === 0) {\n this.log(\"No skills selected\");\n return;\n }\n\n this.log(\"\");\n this.log(`Importing ${searchResult.selectedSkills.length} skill(s)...`);\n\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n for (const skill of searchResult.selectedSkills) {\n if (skill.path) {\n const destPath = path.join(destDir, skill.id);\n await ensureDir(path.dirname(destPath));\n await copy(skill.path, destPath);\n this.logSuccess(`Imported: ${skill.id}`);\n } else {\n this.warn(`Skipping ${skill.id}: No source path available`);\n }\n }\n\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.IMPORT_COMPLETE);\n this.log(`Skills location: ${destDir}`);\n this.log(INFO_MESSAGES.RUN_COMPILE);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async runStatic(\n query: string,\n flags: { source?: string; category?: string },\n ): Promise<void> {\n try {\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n });\n\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n\n const allSkills = Object.values(matrix.skills).filter(\n (skill): skill is ResolvedSkill => skill !== undefined,\n );\n\n let results = allSkills.filter((skill) => matchesQuery(skill, query));\n\n if (flags.category) {\n // CLI flag is an untyped string — cast at data boundary\n results = results.filter((skill) => matchesCategory(skill, flags.category as CategoryPath));\n }\n\n results = sortBy(results, (r) => r.displayName || r.id);\n\n this.log(\"\");\n if (results.length === 0) {\n this.warn(`No skills found matching \"${query}\"`);\n if (flags.category) {\n this.logInfo(`Category filter: ${flags.category}`);\n }\n } else {\n this.logInfo(\n `Found ${results.length} skill${results.length === 1 ? \"\" : \"s\"} matching \"${query}\"`,\n );\n if (flags.category) {\n this.logInfo(`Category filter: ${flags.category}`);\n }\n this.log(\"\");\n\n printTable({\n data: results.map((skill) => ({\n id: skill.displayName || skill.id,\n category: skill.category,\n description: truncate(skill.description, MAX_DESCRIPTION_WIDTH),\n })),\n columns: [\n { key: \"id\", name: \"ID\" },\n { key: \"category\", name: \"Category\" },\n { key: \"description\", name: \"Description\" },\n ],\n headerOptions: { bold: true },\n });\n }\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n","export { SkillSearch, type SkillSearchResult } from \"./skill-search.js\";\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/search.tsx","../../src/cli/components/skill-search/index.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { SkillSearch, type SkillSearchResult } from \"../components/skill-search/index.js\";\nimport type { SourcedSkill } from \"../components/skill-search/skill-search.js\";\nimport { DEFAULT_SKILLS_SUBDIR, LOCAL_SKILLS_PATH, STANDARD_FILES } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { resolveAllSources, type SourceEntry } from \"../lib/configuration/index.js\";\nimport { loadSkillsMatrixFromSource, fetchFromSource } from \"../lib/loading/index.js\";\nimport type { CategoryPath, ResolvedSkill, SkillId } from \"../types/index.js\";\nimport { listDirectories, fileExists, copy, ensureDir } from \"../utils/fs.js\";\nimport { SUCCESS_MESSAGES, STATUS_MESSAGES, INFO_MESSAGES } from \"../utils/messages.js\";\n\nconst MAX_DESCRIPTION_WIDTH = 50;\n\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return `${str.slice(0, maxLength - 3)}...`;\n}\n\nfunction matchesQuery(skill: ResolvedSkill, query: string): boolean {\n const lowerQuery = query.toLowerCase();\n\n if (skill.id.toLowerCase().includes(lowerQuery)) return true;\n if (skill.displayName?.toLowerCase().includes(lowerQuery)) return true;\n if (skill.description.toLowerCase().includes(lowerQuery)) return true;\n if (skill.category.toLowerCase().includes(lowerQuery)) return true;\n\n return skill.tags.some((tag) => tag.toLowerCase().includes(lowerQuery));\n}\n\nfunction matchesCategory(skill: ResolvedSkill, category: CategoryPath): boolean {\n const lowerCategory = category.toLowerCase();\n return skill.category.toLowerCase().includes(lowerCategory);\n}\n\nfunction toSourcedSkill(\n skill: ResolvedSkill,\n sourceName: string,\n sourceUrl?: string,\n): SourcedSkill {\n return {\n ...skill,\n sourceName,\n sourceUrl,\n };\n}\n\nasync function fetchSkillsFromSource(\n source: SourceEntry,\n forceRefresh: boolean,\n): Promise<SourcedSkill[]> {\n try {\n const result = await fetchFromSource(source.url, { forceRefresh });\n const skillsDir = path.join(result.path, DEFAULT_SKILLS_SUBDIR);\n\n if (!(await fileExists(skillsDir))) {\n return [];\n }\n\n const skillDirs = await listDirectories(skillsDir);\n const skills: SourcedSkill[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n if (await fileExists(skillMdPath)) {\n skills.push({\n // Directory name is an untyped string — cast at data boundary\n id: skillDir as SkillId,\n description: `Skill from ${source.name}`,\n // Synthetic category for third-party sources — not in CategoryPath union\n category: \"imported\" as CategoryPath,\n tags: [],\n author: `@${source.name}`,\n conflictsWith: [],\n recommends: [],\n requires: [],\n alternatives: [],\n discourages: [],\n compatibleWith: [],\n requiresSetup: [],\n providesSetupFor: [],\n sourceName: source.name,\n sourceUrl: source.url,\n path: path.join(skillsDir, skillDir),\n });\n }\n }\n\n return skills;\n } catch {\n // Source unavailable, return empty\n return [];\n }\n}\n\nexport default class Search extends BaseCommand {\n static summary = \"Search available skills\";\n static description =\n \"Search skills by ID, alias, description, category, or tags. \" +\n \"Run without arguments or with -i for interactive mode with multi-select.\";\n\n static examples = [\n {\n description: \"Search for React skills\",\n command: \"<%= config.bin %> search react\",\n },\n {\n description: \"Interactive search mode\",\n command: \"<%= config.bin %> search\",\n },\n {\n description: \"Interactive with pre-filled query\",\n command: \"<%= config.bin %> search -i react\",\n },\n {\n description: \"Search with category filter\",\n command: \"<%= config.bin %> search state -c frontend\",\n },\n ];\n\n static args = {\n query: Args.string({\n description: \"Search query (matches name, description, category, tags)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n interactive: Flags.boolean({\n char: \"i\",\n description: \"Launch interactive search with multi-select\",\n default: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Filter by category\",\n required: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Search);\n const projectDir = process.cwd();\n\n const isInteractive = flags.interactive || !args.query;\n\n if (isInteractive) {\n await this.runInteractive(args.query, flags.refresh, projectDir);\n } else {\n await this.runStatic(args.query!, flags);\n }\n }\n\n private async runInteractive(\n initialQuery: string | undefined,\n forceRefresh: boolean,\n projectDir: string,\n ): Promise<void> {\n this.log(\"Loading skills from all sources...\");\n\n try {\n const { matrix, sourcePath } = await loadSkillsMatrixFromSource({\n sourceFlag: undefined,\n projectDir,\n forceRefresh,\n });\n\n const primarySkills = Object.values(matrix.skills)\n .filter((skill): skill is ResolvedSkill => skill !== undefined)\n .map((skill) => toSourcedSkill(skill, \"marketplace\", sourcePath));\n\n const { extras } = await resolveAllSources(projectDir);\n\n const extraSkillArrays = await Promise.all(\n extras.map((source) => fetchSkillsFromSource(source, forceRefresh)),\n );\n\n const allSkills: SourcedSkill[] = [...primarySkills, ...extraSkillArrays.flat()];\n const sourceCount = 1 + extras.length;\n\n this.log(`Loaded ${allSkills.length} skills from ${sourceCount} source(s)`);\n this.log(\"\");\n\n const searchResultPromise = new Promise<SkillSearchResult>((resolve) => {\n const { waitUntilExit } = render(\n <SkillSearch\n skills={allSkills}\n sourceCount={sourceCount}\n initialQuery={initialQuery}\n onComplete={(result) => {\n resolve(result);\n }}\n onCancel={() => {\n resolve({ selectedSkills: [], cancelled: true });\n }}\n />,\n );\n\n waitUntilExit().then(() => {\n resolve({ selectedSkills: [], cancelled: true });\n });\n });\n\n const searchResult = await searchResultPromise;\n\n if (searchResult.cancelled) {\n this.log(\"Search cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (searchResult.selectedSkills.length === 0) {\n this.log(\"No skills selected\");\n return;\n }\n\n this.log(\"\");\n this.log(`Importing ${searchResult.selectedSkills.length} skill(s)...`);\n\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n for (const skill of searchResult.selectedSkills) {\n if (skill.path) {\n const destPath = path.join(destDir, skill.id);\n await ensureDir(path.dirname(destPath));\n await copy(skill.path, destPath);\n this.logSuccess(`Imported: ${skill.id}`);\n } else {\n this.warn(`Skipping ${skill.id}: No source path available`);\n }\n }\n\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.IMPORT_COMPLETE);\n this.log(`Skills location: ${destDir}`);\n this.log(INFO_MESSAGES.RUN_COMPILE);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async runStatic(\n query: string,\n flags: { source?: string; category?: string },\n ): Promise<void> {\n try {\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n });\n\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n\n const allSkills = Object.values(matrix.skills).filter(\n (skill): skill is ResolvedSkill => skill !== undefined,\n );\n\n let results = allSkills.filter((skill) => matchesQuery(skill, query));\n\n if (flags.category) {\n // CLI flag is an untyped string — cast at data boundary\n results = results.filter((skill) => matchesCategory(skill, flags.category as CategoryPath));\n }\n\n results = sortBy(results, (r) => r.displayName || r.id);\n\n this.log(\"\");\n if (results.length === 0) {\n this.warn(`No skills found matching \"${query}\"`);\n if (flags.category) {\n this.logInfo(`Category filter: ${flags.category}`);\n }\n } else {\n this.logInfo(\n `Found ${results.length} skill${results.length === 1 ? \"\" : \"s\"} matching \"${query}\"`,\n );\n if (flags.category) {\n this.logInfo(`Category filter: ${flags.category}`);\n }\n this.log(\"\");\n\n printTable({\n data: results.map((skill) => ({\n id: skill.displayName || skill.id,\n category: skill.category,\n description: truncate(skill.description, MAX_DESCRIPTION_WIDTH),\n })),\n columns: [\n { key: \"id\", name: \"ID\" },\n { key: \"category\", name: \"Category\" },\n { key: \"description\", name: \"Description\" },\n ],\n headerOptions: { bold: true },\n });\n }\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n","export { SkillSearch, type SkillSearchResult } from \"./skill-search.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,MAAM,aAAa;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,OAAO,UAAU;AACjB,SAAS,cAAc;;;ACJvB;;;ADmMU;AAlLV,IAAM,wBAAwB;AAE9B,SAAS,SAAS,KAAa,WAA2B;AACxD,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,GAAG,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC;AACvC;AAEA,SAAS,aAAa,OAAsB,OAAwB;AAClE,QAAM,aAAa,MAAM,YAAY;AAErC,MAAI,MAAM,GAAG,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AACxD,MAAI,MAAM,aAAa,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAClE,MAAI,MAAM,YAAY,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AACjE,MAAI,MAAM,SAAS,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAE9D,SAAO,MAAM,KAAK,KAAK,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,UAAU,CAAC;AACxE;AAEA,SAAS,gBAAgB,OAAsB,UAAiC;AAC9E,QAAM,gBAAgB,SAAS,YAAY;AAC3C,SAAO,MAAM,SAAS,YAAY,EAAE,SAAS,aAAa;AAC5D;AAEA,SAAS,eACP,OACA,YACA,WACc;AACd,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,sBACb,QACA,cACyB;AACzB,MAAI;AACF,UAAM,SAAS,MAAM,gBAAgB,OAAO,KAAK,EAAE,aAAa,CAAC;AACjE,UAAM,YAAY,KAAK,KAAK,OAAO,MAAM,qBAAqB;AAE9D,QAAI,CAAE,MAAM,WAAW,SAAS,GAAI;AAClC,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,YAAY,MAAM,gBAAgB,SAAS;AACjD,UAAM,SAAyB,CAAC;AAEhC,eAAW,YAAY,WAAW;AAChC,YAAM,cAAc,KAAK,KAAK,WAAW,UAAU,eAAe,QAAQ;AAC1E,UAAI,MAAM,WAAW,WAAW,GAAG;AACjC,eAAO,KAAK;AAAA;AAAA,UAEV,IAAI;AAAA,UACJ,aAAa,cAAc,OAAO,IAAI;AAAA;AAAA,UAEtC,UAAU;AAAA,UACV,MAAM,CAAC;AAAA,UACP,QAAQ,IAAI,OAAO,IAAI;AAAA,UACvB,eAAe,CAAC;AAAA,UAChB,YAAY,CAAC;AAAA,UACb,UAAU,CAAC;AAAA,UACX,cAAc,CAAC;AAAA,UACf,aAAa,CAAC;AAAA,UACd,gBAAgB,CAAC;AAAA,UACjB,eAAe,CAAC;AAAA,UAChB,kBAAkB,CAAC;AAAA,UACnB,YAAY,OAAO;AAAA,UACnB,WAAW,OAAO;AAAA,UAClB,MAAM,KAAK,KAAK,WAAW,QAAQ;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,IAAqB,SAArB,MAAqB,gBAAe,YAAY;AAAA,EAC9C,OAAO,UAAU;AAAA,EACjB,OAAO,cACL;AAAA,EAGF,OAAO,WAAW;AAAA,IAChB;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,OAAO,OAAO;AAAA,IACZ,OAAO,KAAK,OAAO;AAAA,MACjB,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,aAAa,MAAM,QAAQ;AAAA,MACzB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,UAAU,MAAM,OAAO;AAAA,MACrB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,IACD,SAAS,MAAM,QAAQ;AAAA,MACrB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,OAAM;AAC/C,UAAM,aAAa,QAAQ,IAAI;AAE/B,UAAM,gBAAgB,MAAM,eAAe,CAAC,KAAK;AAEjD,QAAI,eAAe;AACjB,YAAM,KAAK,eAAe,KAAK,OAAO,MAAM,SAAS,UAAU;AAAA,IACjE,OAAO;AACL,YAAM,KAAK,UAAU,KAAK,OAAQ,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAc,eACZ,cACA,cACA,YACe;AACf,SAAK,IAAI,oCAAoC;AAE7C,QAAI;AACF,YAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,2BAA2B;AAAA,QAC9D,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,gBAAgB,OAAO,OAAO,OAAO,MAAM,EAC9C,OAAO,CAAC,UAAkC,UAAU,MAAS,EAC7D,IAAI,CAAC,UAAU,eAAe,OAAO,eAAe,UAAU,CAAC;AAElE,YAAM,EAAE,OAAO,IAAI,MAAM,kBAAkB,UAAU;AAErD,YAAM,mBAAmB,MAAM,QAAQ;AAAA,QACrC,OAAO,IAAI,CAAC,WAAW,sBAAsB,QAAQ,YAAY,CAAC;AAAA,MACpE;AAEA,YAAM,YAA4B,CAAC,GAAG,eAAe,GAAG,iBAAiB,KAAK,CAAC;AAC/E,YAAM,cAAc,IAAI,OAAO;AAE/B,WAAK,IAAI,UAAU,UAAU,MAAM,gBAAgB,WAAW,YAAY;AAC1E,WAAK,IAAI,EAAE;AAEX,YAAM,sBAAsB,IAAI,QAA2B,CAAC,YAAY;AACtE,cAAM,EAAE,cAAc,IAAI;AAAA,UACxB;AAAA,YAAC;AAAA;AAAA,cACC,QAAQ;AAAA,cACR;AAAA,cACA;AAAA,cACA,YAAY,CAAC,WAAW;AACtB,wBAAQ,MAAM;AAAA,cAChB;AAAA,cACA,UAAU,MAAM;AACd,wBAAQ,EAAE,gBAAgB,CAAC,GAAG,WAAW,KAAK,CAAC;AAAA,cACjD;AAAA;AAAA,UACF;AAAA,QACF;AAEA,sBAAc,EAAE,KAAK,MAAM;AACzB,kBAAQ,EAAE,gBAAgB,CAAC,GAAG,WAAW,KAAK,CAAC;AAAA,QACjD,CAAC;AAAA,MACH,CAAC;AAED,YAAM,eAAe,MAAM;AAE3B,UAAI,aAAa,WAAW;AAC1B,aAAK,IAAI,kBAAkB;AAC3B,aAAK,KAAK,WAAW,SAAS;AAAA,MAChC;AAEA,UAAI,aAAa,eAAe,WAAW,GAAG;AAC5C,aAAK,IAAI,oBAAoB;AAC7B;AAAA,MACF;AAEA,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,aAAa,aAAa,eAAe,MAAM,cAAc;AAEtE,YAAM,UAAU,KAAK,KAAK,YAAY,iBAAiB;AAEvD,iBAAW,SAAS,aAAa,gBAAgB;AAC/C,YAAI,MAAM,MAAM;AACd,gBAAM,WAAW,KAAK,KAAK,SAAS,MAAM,EAAE;AAC5C,gBAAM,UAAU,KAAK,QAAQ,QAAQ,CAAC;AACtC,gBAAM,KAAK,MAAM,MAAM,QAAQ;AAC/B,eAAK,WAAW,aAAa,MAAM,EAAE,EAAE;AAAA,QACzC,OAAO;AACL,eAAK,KAAK,YAAY,MAAM,EAAE,4BAA4B;AAAA,QAC5D;AAAA,MACF;AAEA,WAAK,IAAI,EAAE;AACX,WAAK,WAAW,iBAAiB,eAAe;AAChD,WAAK,IAAI,oBAAoB,OAAO,EAAE;AACtC,WAAK,IAAI,cAAc,WAAW;AAAA,IACpC,SAAS,OAAO;AACd,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,UACZ,OACA,OACe;AACf,QAAI;AACF,WAAK,IAAI,gBAAgB,cAAc;AAEvC,YAAM,EAAE,QAAQ,YAAY,QAAQ,IAAI,MAAM,2BAA2B;AAAA,QACvE,YAAY,MAAM;AAAA,MACpB,CAAC;AAED,WAAK,IAAI,eAAe,UAAU,UAAU,QAAQ,KAAK,UAAU,EAAE;AAErE,YAAM,YAAY,OAAO,OAAO,OAAO,MAAM,EAAE;AAAA,QAC7C,CAAC,UAAkC,UAAU;AAAA,MAC/C;AAEA,UAAI,UAAU,UAAU,OAAO,CAAC,UAAU,aAAa,OAAO,KAAK,CAAC;AAEpE,UAAI,MAAM,UAAU;AAElB,kBAAU,QAAQ,OAAO,CAAC,UAAU,gBAAgB,OAAO,MAAM,QAAwB,CAAC;AAAA,MAC5F;AAEA,gBAAU,OAAO,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE;AAEtD,WAAK,IAAI,EAAE;AACX,UAAI,QAAQ,WAAW,GAAG;AACxB,aAAK,KAAK,6BAA6B,KAAK,GAAG;AAC/C,YAAI,MAAM,UAAU;AAClB,eAAK,QAAQ,oBAAoB,MAAM,QAAQ,EAAE;AAAA,QACnD;AAAA,MACF,OAAO;AACL,aAAK;AAAA,UACH,SAAS,QAAQ,MAAM,SAAS,QAAQ,WAAW,IAAI,KAAK,GAAG,cAAc,KAAK;AAAA,QACpF;AACA,YAAI,MAAM,UAAU;AAClB,eAAK,QAAQ,oBAAoB,MAAM,QAAQ,EAAE;AAAA,QACnD;AACA,aAAK,IAAI,EAAE;AAEX,mBAAW;AAAA,UACT,MAAM,QAAQ,IAAI,CAAC,WAAW;AAAA,YAC5B,IAAI,MAAM,eAAe,MAAM;AAAA,YAC/B,UAAU,MAAM;AAAA,YAChB,aAAa,SAAS,MAAM,aAAa,qBAAqB;AAAA,UAChE,EAAE;AAAA,UACF,SAAS;AAAA,YACP,EAAE,KAAK,MAAM,MAAM,KAAK;AAAA,YACxB,EAAE,KAAK,YAAY,MAAM,WAAW;AAAA,YACpC,EAAE,KAAK,eAAe,MAAM,cAAc;AAAA,UAC5C;AAAA,UACA,eAAe,EAAE,MAAM,KAAK;AAAA,QAC9B,CAAC;AAAA,MACH;AACA,WAAK,IAAI,EAAE;AAAA,IACb,SAAS,OAAO;AACd,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AACF;","names":[]}
|
|
@@ -5,35 +5,35 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
claudePluginUninstall,
|
|
7
7
|
isClaudeCLIAvailable
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-26MXZUHU.js";
|
|
9
9
|
import {
|
|
10
10
|
DRY_RUN_MESSAGES,
|
|
11
11
|
INFO_MESSAGES,
|
|
12
12
|
SUCCESS_MESSAGES
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-WLZHCM7O.js";
|
|
14
14
|
import {
|
|
15
15
|
BaseCommand,
|
|
16
16
|
EXIT_CODES
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-PGY5XROM.js";
|
|
18
18
|
import {
|
|
19
19
|
getProjectPluginsDir,
|
|
20
20
|
listPluginNames,
|
|
21
21
|
loadProjectSourceConfig,
|
|
22
22
|
readForkedFromMetadata
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-HMSHB5EQ.js";
|
|
24
24
|
import "../chunk-T4EXUIBY.js";
|
|
25
25
|
import {
|
|
26
26
|
directoryExists,
|
|
27
27
|
getErrorMessage,
|
|
28
28
|
listDirectories,
|
|
29
29
|
remove
|
|
30
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-WBHPCBVN.js";
|
|
31
31
|
import {
|
|
32
32
|
CLAUDE_DIR,
|
|
33
33
|
CLAUDE_SRC_DIR,
|
|
34
34
|
CLI_COLORS,
|
|
35
35
|
DEFAULT_BRANDING
|
|
36
|
-
} from "../chunk-
|
|
36
|
+
} from "../chunk-AWP5A6IM.js";
|
|
37
37
|
import {
|
|
38
38
|
init_esm_shims
|
|
39
39
|
} from "../chunk-DHET7RCE.js";
|
package/dist/commands/update.js
CHANGED
|
@@ -4,32 +4,32 @@ import {
|
|
|
4
4
|
} from "../chunk-N6S7ZRIL.js";
|
|
5
5
|
import {
|
|
6
6
|
recompileAgents
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-7LV4V6A4.js";
|
|
8
8
|
import {
|
|
9
9
|
ERROR_MESSAGES,
|
|
10
10
|
INFO_MESSAGES,
|
|
11
11
|
STATUS_MESSAGES,
|
|
12
12
|
SUCCESS_MESSAGES
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-WLZHCM7O.js";
|
|
14
14
|
import {
|
|
15
15
|
BaseCommand,
|
|
16
16
|
EXIT_CODES
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-PGY5XROM.js";
|
|
18
18
|
import {
|
|
19
19
|
compareLocalSkillsWithSource,
|
|
20
20
|
injectForkedFromMetadata,
|
|
21
21
|
loadSkillsMatrixFromSource
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-HMSHB5EQ.js";
|
|
23
23
|
import "../chunk-T4EXUIBY.js";
|
|
24
24
|
import {
|
|
25
25
|
copy,
|
|
26
26
|
fileExists,
|
|
27
27
|
getErrorMessage
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-WBHPCBVN.js";
|
|
29
29
|
import {
|
|
30
30
|
CLI_BIN_NAME,
|
|
31
31
|
LOCAL_SKILLS_PATH
|
|
32
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-AWP5A6IM.js";
|
|
33
33
|
import {
|
|
34
34
|
init_esm_shims
|
|
35
35
|
} from "../chunk-DHET7RCE.js";
|
|
@@ -1,48 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ERROR_MESSAGES
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-WLZHCM7O.js";
|
|
5
5
|
import {
|
|
6
6
|
BaseCommand,
|
|
7
7
|
EXIT_CODES
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-PGY5XROM.js";
|
|
9
9
|
import {
|
|
10
10
|
checkMatrixHealth,
|
|
11
11
|
extractAllSkills,
|
|
12
|
-
extractFrontmatter,
|
|
13
12
|
loadProjectSourceConfig,
|
|
14
|
-
|
|
13
|
+
loadSkillCategories,
|
|
14
|
+
loadSkillRules,
|
|
15
15
|
mergeMatrixWithSkills,
|
|
16
16
|
parseFrontmatter,
|
|
17
17
|
printPluginValidationResult,
|
|
18
|
+
printValidationResults,
|
|
18
19
|
validateAllPlugins,
|
|
20
|
+
validateAllSchemas,
|
|
19
21
|
validatePlugin
|
|
20
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-HMSHB5EQ.js";
|
|
21
23
|
import "../chunk-T4EXUIBY.js";
|
|
22
24
|
import {
|
|
23
25
|
SKILL_ID_PATTERN,
|
|
24
|
-
agentFrontmatterValidationSchema,
|
|
25
|
-
agentYamlGenerationSchema,
|
|
26
26
|
directoryExists,
|
|
27
27
|
fileExists,
|
|
28
28
|
getErrorMessage,
|
|
29
29
|
glob,
|
|
30
|
-
log,
|
|
31
30
|
metadataValidationSchema,
|
|
32
|
-
pluginManifestSchema,
|
|
33
|
-
projectSourceConfigSchema,
|
|
34
31
|
readFile,
|
|
35
|
-
skillFrontmatterValidationSchema,
|
|
36
|
-
skillsMatrixConfigSchema,
|
|
37
|
-
stackConfigValidationSchema,
|
|
38
|
-
stacksConfigSchema,
|
|
39
32
|
verbose
|
|
40
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-WBHPCBVN.js";
|
|
41
34
|
import {
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
SKILL_CATEGORIES_YAML_PATH,
|
|
36
|
+
SKILL_RULES_YAML_PATH,
|
|
44
37
|
STANDARD_FILES
|
|
45
|
-
} from "../chunk-
|
|
38
|
+
} from "../chunk-AWP5A6IM.js";
|
|
46
39
|
import {
|
|
47
40
|
init_esm_shims
|
|
48
41
|
} from "../chunk-DHET7RCE.js";
|
|
@@ -50,222 +43,18 @@ import {
|
|
|
50
43
|
// src/cli/commands/validate.ts
|
|
51
44
|
init_esm_shims();
|
|
52
45
|
import { Args, Flags } from "@oclif/core";
|
|
53
|
-
import
|
|
46
|
+
import path2 from "path";
|
|
54
47
|
|
|
55
|
-
// src/cli/lib/
|
|
48
|
+
// src/cli/lib/source-validator.ts
|
|
56
49
|
init_esm_shims();
|
|
57
|
-
import { sumBy } from "remeda";
|
|
58
50
|
import path from "path";
|
|
59
51
|
import { parse as parseYaml } from "yaml";
|
|
60
|
-
import fg from "fast-glob";
|
|
61
|
-
var VALIDATION_TARGETS = [
|
|
62
|
-
{
|
|
63
|
-
name: "Skills Matrix",
|
|
64
|
-
schema: skillsMatrixConfigSchema,
|
|
65
|
-
pattern: STANDARD_FILES.SKILLS_MATRIX_YAML,
|
|
66
|
-
baseDir: "src/config"
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: "Skill Metadata",
|
|
70
|
-
schema: metadataValidationSchema,
|
|
71
|
-
pattern: `**/${STANDARD_FILES.METADATA_YAML}`,
|
|
72
|
-
baseDir: "src/skills"
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
name: "Stack Skill Metadata",
|
|
76
|
-
schema: metadataValidationSchema,
|
|
77
|
-
pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,
|
|
78
|
-
baseDir: "src/stacks"
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: "Stack Config",
|
|
82
|
-
schema: stackConfigValidationSchema,
|
|
83
|
-
pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,
|
|
84
|
-
baseDir: "src/stacks"
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: "Agent Definition",
|
|
88
|
-
schema: agentYamlGenerationSchema,
|
|
89
|
-
pattern: `**/${STANDARD_FILES.AGENT_YAML}`,
|
|
90
|
-
baseDir: "src/agents"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
name: "Skill Frontmatter",
|
|
94
|
-
schema: skillFrontmatterValidationSchema,
|
|
95
|
-
pattern: `**/${STANDARD_FILES.SKILL_MD}`,
|
|
96
|
-
baseDir: "src/skills",
|
|
97
|
-
extractor: extractFrontmatter
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: "Stack Skill Frontmatter",
|
|
101
|
-
schema: skillFrontmatterValidationSchema,
|
|
102
|
-
pattern: `**/skills/**/${STANDARD_FILES.SKILL_MD}`,
|
|
103
|
-
baseDir: "src/stacks",
|
|
104
|
-
extractor: extractFrontmatter
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: "Stacks Config",
|
|
108
|
-
schema: stacksConfigSchema,
|
|
109
|
-
pattern: "stacks.yaml",
|
|
110
|
-
baseDir: "config"
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
name: "Project Source Config",
|
|
114
|
-
schema: projectSourceConfigSchema,
|
|
115
|
-
pattern: STANDARD_FILES.CONFIG_YAML,
|
|
116
|
-
baseDir: CLAUDE_SRC_DIR
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
name: "Project Skill Metadata",
|
|
120
|
-
schema: metadataValidationSchema,
|
|
121
|
-
pattern: `*/${STANDARD_FILES.METADATA_YAML}`,
|
|
122
|
-
baseDir: `${CLAUDE_DIR}/skills`
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
name: "Project Skill Frontmatter",
|
|
126
|
-
schema: skillFrontmatterValidationSchema,
|
|
127
|
-
pattern: `*/${STANDARD_FILES.SKILL_MD}`,
|
|
128
|
-
baseDir: `${CLAUDE_DIR}/skills`,
|
|
129
|
-
extractor: extractFrontmatter
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
name: "Project Agent Frontmatter",
|
|
133
|
-
schema: agentFrontmatterValidationSchema,
|
|
134
|
-
pattern: "*.md",
|
|
135
|
-
baseDir: `${CLAUDE_DIR}/agents`,
|
|
136
|
-
extractor: extractFrontmatter
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
name: "Plugin Manifest",
|
|
140
|
-
schema: pluginManifestSchema,
|
|
141
|
-
pattern: `*/${STANDARD_FILES.PLUGIN_JSON}`,
|
|
142
|
-
baseDir: `${CLAUDE_DIR}/plugins`,
|
|
143
|
-
extractor: (content) => JSON.parse(content)
|
|
144
|
-
}
|
|
145
|
-
];
|
|
146
|
-
function formatZodErrors(error) {
|
|
147
|
-
return error.issues.map((issue) => {
|
|
148
|
-
const path4 = issue.path.join(".");
|
|
149
|
-
if (issue.code === "unrecognized_keys") {
|
|
150
|
-
return `Unrecognized key: "${issue.keys.join('", "')}"`;
|
|
151
|
-
}
|
|
152
|
-
return path4 ? `${path4}: ${issue.message}` : issue.message;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
async function validateFile(filePath, schema, extractor) {
|
|
156
|
-
try {
|
|
157
|
-
if (!await fileExists(filePath)) {
|
|
158
|
-
return { valid: false, errors: [`File not found: ${filePath}`] };
|
|
159
|
-
}
|
|
160
|
-
const content = await readFile(filePath);
|
|
161
|
-
let parsed;
|
|
162
|
-
if (extractor) {
|
|
163
|
-
parsed = extractor(content);
|
|
164
|
-
if (parsed === null) {
|
|
165
|
-
return {
|
|
166
|
-
valid: false,
|
|
167
|
-
errors: ["Failed to extract content (no valid frontmatter found)"]
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
parsed = parseYaml(content);
|
|
172
|
-
}
|
|
173
|
-
const result = schema.safeParse(parsed);
|
|
174
|
-
if (result.success) {
|
|
175
|
-
return { valid: true, errors: [] };
|
|
176
|
-
}
|
|
177
|
-
return { valid: false, errors: formatZodErrors(result.error) };
|
|
178
|
-
} catch (error) {
|
|
179
|
-
const message = getErrorMessage(error);
|
|
180
|
-
return { valid: false, errors: [`Failed to parse content: ${message}`] };
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
async function validateTarget(target, rootDir = process.cwd()) {
|
|
184
|
-
const baseDir = path.join(rootDir, target.baseDir);
|
|
185
|
-
const pattern = path.join(baseDir, target.pattern);
|
|
186
|
-
const files = await fg(pattern, { absolute: true });
|
|
187
|
-
const result = {
|
|
188
|
-
schemaName: target.name,
|
|
189
|
-
valid: true,
|
|
190
|
-
totalFiles: files.length,
|
|
191
|
-
validFiles: 0,
|
|
192
|
-
invalidFiles: []
|
|
193
|
-
};
|
|
194
|
-
if (files.length === 0) {
|
|
195
|
-
return result;
|
|
196
|
-
}
|
|
197
|
-
for (const file of files) {
|
|
198
|
-
const validation = await validateFile(file, target.schema, target.extractor);
|
|
199
|
-
const relativePath = path.relative(rootDir, file);
|
|
200
|
-
if (validation.valid) {
|
|
201
|
-
result.validFiles++;
|
|
202
|
-
} else {
|
|
203
|
-
result.valid = false;
|
|
204
|
-
result.invalidFiles.push({
|
|
205
|
-
file: relativePath,
|
|
206
|
-
errors: validation.errors
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
async function validateAllSchemas(rootDir = process.cwd()) {
|
|
213
|
-
const results = [];
|
|
214
|
-
for (const target of VALIDATION_TARGETS) {
|
|
215
|
-
const result = await validateTarget(target, rootDir);
|
|
216
|
-
results.push(result);
|
|
217
|
-
}
|
|
218
|
-
const summary = {
|
|
219
|
-
totalSchemas: results.length,
|
|
220
|
-
totalFiles: sumBy(results, (r) => r.totalFiles),
|
|
221
|
-
validFiles: sumBy(results, (r) => r.validFiles),
|
|
222
|
-
invalidFiles: sumBy(results, (r) => r.invalidFiles.length)
|
|
223
|
-
};
|
|
224
|
-
return {
|
|
225
|
-
valid: results.every((r) => r.valid),
|
|
226
|
-
results,
|
|
227
|
-
summary
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
function printValidationResults(result) {
|
|
231
|
-
log("\n Schema Validation Summary:");
|
|
232
|
-
log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
233
|
-
log(` Total schemas checked: ${result.summary.totalSchemas}`);
|
|
234
|
-
log(` Total files: ${result.summary.totalFiles}`);
|
|
235
|
-
log(` Valid: ${result.summary.validFiles}`);
|
|
236
|
-
log(` Invalid: ${result.summary.invalidFiles}`);
|
|
237
|
-
for (const schemaResult of result.results) {
|
|
238
|
-
if (schemaResult.totalFiles === 0) continue;
|
|
239
|
-
const status = schemaResult.valid ? "\u2713" : "\u2717";
|
|
240
|
-
log(
|
|
241
|
-
`
|
|
242
|
-
${status} ${schemaResult.schemaName}: ${schemaResult.validFiles}/${schemaResult.totalFiles} valid`
|
|
243
|
-
);
|
|
244
|
-
if (schemaResult.invalidFiles.length > 0) {
|
|
245
|
-
for (const file of schemaResult.invalidFiles) {
|
|
246
|
-
log(`
|
|
247
|
-
${file.file}:`);
|
|
248
|
-
file.errors.forEach((e) => log(` - ${e}`));
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (result.valid) {
|
|
253
|
-
log("\n \u2713 All schemas validated successfully\n");
|
|
254
|
-
} else {
|
|
255
|
-
log("\n \u2717 Validation failed\n");
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/cli/lib/source-validator.ts
|
|
260
|
-
init_esm_shims();
|
|
261
|
-
import path2 from "path";
|
|
262
|
-
import { parse as parseYaml2 } from "yaml";
|
|
263
52
|
function isSnakeCase(key) {
|
|
264
53
|
return /[a-z]_[a-z]/.test(key);
|
|
265
54
|
}
|
|
266
55
|
async function validateSource(sourcePath) {
|
|
267
56
|
const issues = [];
|
|
268
|
-
const resolvedPath =
|
|
57
|
+
const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);
|
|
269
58
|
if (!await directoryExists(resolvedPath)) {
|
|
270
59
|
issues.push({
|
|
271
60
|
severity: "error",
|
|
@@ -276,7 +65,7 @@ async function validateSource(sourcePath) {
|
|
|
276
65
|
}
|
|
277
66
|
const sourceProjectConfig = await loadProjectSourceConfig(resolvedPath);
|
|
278
67
|
const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? "src/skills";
|
|
279
|
-
const skillsDir =
|
|
68
|
+
const skillsDir = path.join(resolvedPath, skillsDirRelPath);
|
|
280
69
|
if (!await directoryExists(skillsDir)) {
|
|
281
70
|
issues.push({
|
|
282
71
|
severity: "error",
|
|
@@ -287,13 +76,13 @@ async function validateSource(sourcePath) {
|
|
|
287
76
|
}
|
|
288
77
|
const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
|
|
289
78
|
const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);
|
|
290
|
-
const skillMdDirs = new Set(skillMdFiles.map((f) =>
|
|
291
|
-
const metadataDirs = new Set(metadataFiles.map((f) =>
|
|
79
|
+
const skillMdDirs = new Set(skillMdFiles.map((f) => path.dirname(f)));
|
|
80
|
+
const metadataDirs = new Set(metadataFiles.map((f) => path.dirname(f)));
|
|
292
81
|
for (const dir of skillMdDirs) {
|
|
293
82
|
if (!metadataDirs.has(dir)) {
|
|
294
83
|
issues.push({
|
|
295
84
|
severity: "error",
|
|
296
|
-
file:
|
|
85
|
+
file: path.join(skillsDir, dir),
|
|
297
86
|
message: `Missing ${STANDARD_FILES.METADATA_YAML} \u2014 skill directory has ${STANDARD_FILES.SKILL_MD} but no metadata`
|
|
298
87
|
});
|
|
299
88
|
}
|
|
@@ -302,25 +91,25 @@ async function validateSource(sourcePath) {
|
|
|
302
91
|
if (!skillMdDirs.has(dir)) {
|
|
303
92
|
issues.push({
|
|
304
93
|
severity: "error",
|
|
305
|
-
file:
|
|
94
|
+
file: path.join(skillsDir, dir),
|
|
306
95
|
message: `Missing ${STANDARD_FILES.SKILL_MD} \u2014 skill directory has ${STANDARD_FILES.METADATA_YAML} but no SKILL.md`
|
|
307
96
|
});
|
|
308
97
|
}
|
|
309
98
|
}
|
|
310
99
|
let skillCount = 0;
|
|
311
100
|
for (const metadataFile of metadataFiles) {
|
|
312
|
-
const metadataPath =
|
|
313
|
-
const skillDir =
|
|
314
|
-
const skillMdPath =
|
|
101
|
+
const metadataPath = path.join(skillsDir, metadataFile);
|
|
102
|
+
const skillDir = path.dirname(metadataFile);
|
|
103
|
+
const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
|
|
315
104
|
if (!await fileExists(skillMdPath)) {
|
|
316
105
|
continue;
|
|
317
106
|
}
|
|
318
107
|
skillCount++;
|
|
319
|
-
const relPath =
|
|
108
|
+
const relPath = path.join(skillsDirRelPath, metadataFile);
|
|
320
109
|
let rawMetadata;
|
|
321
110
|
try {
|
|
322
111
|
const metadataContent = await readFile(metadataPath);
|
|
323
|
-
rawMetadata =
|
|
112
|
+
rawMetadata = parseYaml(metadataContent);
|
|
324
113
|
} catch (error) {
|
|
325
114
|
issues.push({
|
|
326
115
|
severity: "error",
|
|
@@ -353,12 +142,12 @@ async function validateSource(sourcePath) {
|
|
|
353
142
|
continue;
|
|
354
143
|
}
|
|
355
144
|
const metadata = result.data;
|
|
356
|
-
const dirName =
|
|
357
|
-
if (metadata.
|
|
145
|
+
const dirName = path.basename(skillDir);
|
|
146
|
+
if (metadata.displayName !== dirName) {
|
|
358
147
|
issues.push({
|
|
359
148
|
severity: "warning",
|
|
360
149
|
file: relPath,
|
|
361
|
-
message: `
|
|
150
|
+
message: `displayName '${metadata.displayName}' does not match directory name '${dirName}'`
|
|
362
151
|
});
|
|
363
152
|
}
|
|
364
153
|
const skillMdContent = await readFile(skillMdPath);
|
|
@@ -367,7 +156,7 @@ async function validateSource(sourcePath) {
|
|
|
367
156
|
if (!SKILL_ID_PATTERN.test(frontmatter.name)) {
|
|
368
157
|
issues.push({
|
|
369
158
|
severity: "warning",
|
|
370
|
-
file:
|
|
159
|
+
file: path.join(skillsDirRelPath, skillDir, STANDARD_FILES.SKILL_MD),
|
|
371
160
|
message: `SKILL.md name '${frontmatter.name}' does not match expected skill ID pattern (domain-subcategory-name)`
|
|
372
161
|
});
|
|
373
162
|
}
|
|
@@ -381,28 +170,51 @@ async function validateSource(sourcePath) {
|
|
|
381
170
|
}
|
|
382
171
|
}
|
|
383
172
|
try {
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
173
|
+
const categoriesPath = path.join(resolvedPath, SKILL_CATEGORIES_YAML_PATH);
|
|
174
|
+
const rulesPath = path.join(resolvedPath, SKILL_RULES_YAML_PATH);
|
|
175
|
+
const hasCats = await fileExists(categoriesPath);
|
|
176
|
+
const hasRules = await fileExists(rulesPath);
|
|
177
|
+
if (hasCats || hasRules) {
|
|
178
|
+
const cats = hasCats ? await loadSkillCategories(categoriesPath) : {};
|
|
179
|
+
const defaultRelationships = {
|
|
180
|
+
conflicts: [],
|
|
181
|
+
discourages: [],
|
|
182
|
+
recommends: [],
|
|
183
|
+
requires: [],
|
|
184
|
+
alternatives: []
|
|
185
|
+
};
|
|
186
|
+
const rules = hasRules ? await loadSkillRules(rulesPath) : {
|
|
187
|
+
version: "1.0.0",
|
|
188
|
+
aliases: {},
|
|
189
|
+
relationships: defaultRelationships,
|
|
190
|
+
perSkill: {}
|
|
191
|
+
};
|
|
388
192
|
const skills = await extractAllSkills(skillsDir);
|
|
389
|
-
const mergedMatrix = await mergeMatrixWithSkills(
|
|
193
|
+
const mergedMatrix = await mergeMatrixWithSkills(
|
|
194
|
+
cats,
|
|
195
|
+
rules.relationships,
|
|
196
|
+
rules.aliases,
|
|
197
|
+
skills,
|
|
198
|
+
rules.perSkill
|
|
199
|
+
);
|
|
390
200
|
const healthIssues = checkMatrixHealth(mergedMatrix);
|
|
391
201
|
for (const healthIssue of healthIssues) {
|
|
392
202
|
issues.push({
|
|
393
203
|
severity: healthIssue.severity,
|
|
394
|
-
file:
|
|
204
|
+
file: SKILL_CATEGORIES_YAML_PATH,
|
|
395
205
|
message: healthIssue.details
|
|
396
206
|
});
|
|
397
207
|
}
|
|
398
208
|
} else {
|
|
399
|
-
verbose(
|
|
209
|
+
verbose(
|
|
210
|
+
`No categories/rules files at '${resolvedPath}' \u2014 skipping cross-reference validation`
|
|
211
|
+
);
|
|
400
212
|
}
|
|
401
213
|
} catch (error) {
|
|
402
214
|
issues.push({
|
|
403
215
|
severity: "warning",
|
|
404
|
-
file:
|
|
405
|
-
message: `Cross-reference validation skipped: failed to load
|
|
216
|
+
file: SKILL_CATEGORIES_YAML_PATH,
|
|
217
|
+
message: `Cross-reference validation skipped: failed to load categories/rules`
|
|
406
218
|
});
|
|
407
219
|
}
|
|
408
220
|
return buildResult(issues, skillCount);
|
|
@@ -495,7 +307,7 @@ var Validate = class _Validate extends BaseCommand {
|
|
|
495
307
|
}
|
|
496
308
|
}
|
|
497
309
|
async validatePlugins(pluginPath, verbose2, all) {
|
|
498
|
-
const targetPath = pluginPath ?
|
|
310
|
+
const targetPath = pluginPath ? path2.resolve(pluginPath) : process.cwd();
|
|
499
311
|
if (all) {
|
|
500
312
|
await this.validateAllPluginsInDirectory(targetPath, verbose2);
|
|
501
313
|
} else {
|
|
@@ -541,7 +353,7 @@ var Validate = class _Validate extends BaseCommand {
|
|
|
541
353
|
const result = await validatePlugin(targetPath);
|
|
542
354
|
const summary = result.valid ? "Done: Plugin is valid" : "Done: Plugin has errors";
|
|
543
355
|
this.log(summary);
|
|
544
|
-
printPluginValidationResult(
|
|
356
|
+
printPluginValidationResult(path2.basename(targetPath), result, true);
|
|
545
357
|
if (result.valid && result.warnings.length === 0) {
|
|
546
358
|
this.log("");
|
|
547
359
|
this.logSuccess("Plugin validated successfully");
|