@claude-collective/cli 0.8.0 → 0.13.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 +127 -0
- package/README.md +26 -9
- package/dist/{chunk-TOPAIL5W.js → chunk-3U3R4NCG.js} +2 -2
- package/dist/chunk-3U3R4NCG.js.map +1 -0
- package/dist/{chunk-YKXBGCFD.js → chunk-57Y5RALO.js} +10 -10
- package/dist/chunk-57Y5RALO.js.map +1 -0
- package/dist/{chunk-ED73HCW2.js → chunk-6DCSSORF.js} +37 -88
- package/dist/chunk-6DCSSORF.js.map +1 -0
- package/dist/{chunk-6LS7XO3H.js → chunk-6Q3Y7KVB.js} +2 -2
- package/dist/chunk-6Q3Y7KVB.js.map +1 -0
- package/dist/{chunk-A3J6IAXK.js → chunk-76DWXGQE.js} +4 -2
- package/dist/chunk-76DWXGQE.js.map +1 -0
- package/dist/{chunk-Q6DR5QUH.js → chunk-7Q44DMSP.js} +62 -27
- package/dist/chunk-7Q44DMSP.js.map +1 -0
- package/dist/chunk-ACNBKXXJ.js +321 -0
- package/dist/chunk-ACNBKXXJ.js.map +1 -0
- package/dist/{chunk-QGGSLMO3.js → chunk-B7CCVP6Q.js} +41 -9
- package/dist/chunk-B7CCVP6Q.js.map +1 -0
- package/dist/{chunk-LVKRVFYR.js → chunk-BDLUZVKU.js} +2 -2
- package/dist/chunk-BDLUZVKU.js.map +1 -0
- package/dist/{chunk-HNDT5QRB.js → chunk-CDX4W4DM.js} +3 -3
- package/dist/chunk-CDX4W4DM.js.map +1 -0
- package/dist/{chunk-MYAVQ23U.js → chunk-CJEHB4TB.js} +23 -9
- package/dist/chunk-CJEHB4TB.js.map +1 -0
- package/dist/{chunk-DKGL77IY.js → chunk-CPZOTVCI.js} +15 -14
- package/dist/chunk-CPZOTVCI.js.map +1 -0
- package/dist/{chunk-K7PTOVX4.js → chunk-D237EVNB.js} +32 -3
- package/dist/chunk-D237EVNB.js.map +1 -0
- package/dist/{chunk-Q2LH2DAB.js → chunk-DRXPNNPB.js} +19 -18
- package/dist/chunk-DRXPNNPB.js.map +1 -0
- package/dist/{chunk-Y3V43XCU.js → chunk-E3FJH4TF.js} +12 -8
- package/dist/chunk-E3FJH4TF.js.map +1 -0
- package/dist/{chunk-3HBTELJN.js → chunk-ED4E6Q2T.js} +10 -10
- package/dist/chunk-ED4E6Q2T.js.map +1 -0
- package/dist/{chunk-SYQ7R2JO.js → chunk-EHS3TWWP.js} +3 -3
- package/dist/chunk-EHS3TWWP.js.map +1 -0
- package/dist/{chunk-LQTST4WY.js → chunk-GDH553MV.js} +6 -6
- package/dist/chunk-GDH553MV.js.map +1 -0
- package/dist/{chunk-A65SBAAJ.js → chunk-HLJX2FTL.js} +31 -5
- package/dist/chunk-HLJX2FTL.js.map +1 -0
- package/dist/chunk-I2DSLOXZ.js +75 -0
- package/dist/chunk-I2DSLOXZ.js.map +1 -0
- package/dist/{chunk-SEBPPFUW.js → chunk-I4TPKIYX.js} +33 -18
- package/dist/chunk-I4TPKIYX.js.map +1 -0
- package/dist/{chunk-NGBFJJ7Q.js → chunk-IMDW5ZUP.js} +19 -11
- package/dist/chunk-IMDW5ZUP.js.map +1 -0
- package/dist/{chunk-U4VYHKPM.js → chunk-JIPWV2FX.js} +6 -6
- package/dist/chunk-JIPWV2FX.js.map +1 -0
- package/dist/{chunk-G2FBJOZG.js → chunk-K7EVM5LY.js} +4 -4
- package/dist/chunk-K7EVM5LY.js.map +1 -0
- package/dist/{chunk-MJSFR562.js → chunk-KAAEN2PO.js} +3 -3
- package/dist/chunk-KAAEN2PO.js.map +1 -0
- package/dist/{chunk-FNOYEXUE.js → chunk-LE6IY6IT.js} +22 -17
- package/dist/chunk-LE6IY6IT.js.map +1 -0
- package/dist/{chunk-CIY5UBRB.js → chunk-NDY25DTL.js} +6 -6
- package/dist/chunk-NDY25DTL.js.map +1 -0
- package/dist/{chunk-OLBOTK3O.js → chunk-P26A2K5N.js} +7 -7
- package/dist/chunk-P26A2K5N.js.map +1 -0
- package/dist/{chunk-DHFFRMF6.js → chunk-RTE64SJA.js} +2 -2
- package/dist/chunk-RTE64SJA.js.map +1 -0
- package/dist/{chunk-3ZCB5K33.js → chunk-SGJ23HIP.js} +14 -11
- package/dist/chunk-SGJ23HIP.js.map +1 -0
- package/dist/{chunk-C4ZTIYFR.js → chunk-SVYPSDWY.js} +10 -10
- package/dist/chunk-SVYPSDWY.js.map +1 -0
- package/dist/{chunk-MMDXNZPF.js → chunk-TKFPKEV3.js} +2 -2
- package/dist/chunk-TKFPKEV3.js.map +1 -0
- package/dist/{chunk-M7YCPFIX.js → chunk-UQTEPWU7.js} +2 -2
- package/dist/chunk-UQTEPWU7.js.map +1 -0
- package/dist/{chunk-QESUUPOE.js → chunk-V46GGCCI.js} +80 -27
- package/dist/chunk-V46GGCCI.js.map +1 -0
- package/dist/{chunk-UOWHJ6BE.js → chunk-X6QONICW.js} +6 -3
- package/dist/chunk-X6QONICW.js.map +1 -0
- package/dist/chunk-Y2LW7R3Y.js +23 -0
- package/dist/chunk-Y2LW7R3Y.js.map +1 -0
- package/dist/chunk-Z2CWURZ6.js +78 -0
- package/dist/chunk-Z2CWURZ6.js.map +1 -0
- package/dist/chunk-Z7G4B5HJ.js +377 -0
- package/dist/chunk-Z7G4B5HJ.js.map +1 -0
- package/dist/{chunk-XKEG3SCV.js → chunk-ZENYS6KW.js} +13 -9
- package/dist/chunk-ZENYS6KW.js.map +1 -0
- package/dist/{cli-v2 → cli}/defaults/agent-mappings.yaml +5 -5
- package/dist/commands/build/marketplace.js +9 -9
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +12 -12
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +15 -15
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +21 -21
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +9 -8
- package/dist/commands/config/get.js.map +1 -1
- package/dist/commands/config/index.js +7 -6
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +8 -7
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/set-project.js +9 -8
- package/dist/commands/config/set-project.js.map +1 -1
- package/dist/commands/config/set.js +9 -8
- package/dist/commands/config/set.js.map +1 -1
- package/dist/commands/config/show.js +6 -5
- package/dist/commands/config/unset-project.js +9 -8
- package/dist/commands/config/unset-project.js.map +1 -1
- package/dist/commands/config/unset.js +9 -8
- package/dist/commands/config/unset.js.map +1 -1
- package/dist/commands/diff.js +12 -12
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +10 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +52 -49
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +180 -97
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +339 -0
- package/dist/commands/import/skill.js.map +1 -0
- package/dist/commands/info.js +9 -9
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +205 -78
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +9 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +19 -21
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/skill.js +11 -12
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +12 -12
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +205 -17
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/test-imports.js +18 -18
- package/dist/commands/test-imports.js.map +1 -1
- package/dist/commands/uninstall.js +58 -78
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +21 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +9 -9
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/version/bump.js +8 -8
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/version/index.js +8 -8
- package/dist/commands/version/index.js.map +1 -1
- package/dist/commands/version/set.js +7 -7
- package/dist/commands/version/set.js.map +1 -1
- package/dist/commands/version/show.js +8 -8
- package/dist/commands/version/show.js.map +1 -1
- package/dist/components/common/confirm.js +1 -1
- package/dist/components/common/message.js +1 -1
- package/dist/components/common/message.js.map +1 -1
- package/dist/components/common/spinner.js +1 -1
- package/dist/components/common/spinner.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +10 -0
- package/dist/components/skill-search/skill-search.js.map +1 -0
- package/dist/components/wizard/category-grid.js +1 -1
- package/dist/components/wizard/category-grid.test.js +213 -80
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/section-progress.js +1 -1
- package/dist/components/wizard/section-progress.test.js +2 -2
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/step-approach.js +4 -3
- package/dist/components/wizard/step-build.js +4 -3
- package/dist/components/wizard/step-build.test.js +29 -17
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +2 -1
- package/dist/components/wizard/step-refine.js +2 -1
- package/dist/components/wizard/step-refine.test.js +4 -3
- package/dist/components/wizard/step-refine.test.js.map +1 -1
- package/dist/components/wizard/step-stack-options.js +3 -3
- package/dist/components/wizard/step-stack.js +3 -3
- package/dist/components/wizard/wizard-footer.js +9 -0
- package/dist/components/wizard/wizard-footer.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +1 -1
- package/dist/components/wizard/wizard.js +14 -12
- package/dist/hooks/init.js +5 -4
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/stores/wizard-store.js +2 -2
- package/dist/stores/wizard-store.test.js +3 -3
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-3HBTELJN.js.map +0 -1
- package/dist/chunk-3ZCB5K33.js.map +0 -1
- package/dist/chunk-6LS7XO3H.js.map +0 -1
- package/dist/chunk-A3J6IAXK.js.map +0 -1
- package/dist/chunk-A65SBAAJ.js.map +0 -1
- package/dist/chunk-ALEPJ6YN.js +0 -80
- package/dist/chunk-ALEPJ6YN.js.map +0 -1
- package/dist/chunk-C4ZTIYFR.js.map +0 -1
- package/dist/chunk-CIY5UBRB.js.map +0 -1
- package/dist/chunk-DHFFRMF6.js.map +0 -1
- package/dist/chunk-DKGL77IY.js.map +0 -1
- package/dist/chunk-ED73HCW2.js.map +0 -1
- package/dist/chunk-FNOYEXUE.js.map +0 -1
- package/dist/chunk-G2FBJOZG.js.map +0 -1
- package/dist/chunk-HNDT5QRB.js.map +0 -1
- package/dist/chunk-K7PTOVX4.js.map +0 -1
- package/dist/chunk-LQTST4WY.js.map +0 -1
- package/dist/chunk-LVKRVFYR.js.map +0 -1
- package/dist/chunk-M7YCPFIX.js.map +0 -1
- package/dist/chunk-MJSFR562.js.map +0 -1
- package/dist/chunk-MMDXNZPF.js.map +0 -1
- package/dist/chunk-MYAVQ23U.js.map +0 -1
- package/dist/chunk-NGBFJJ7Q.js.map +0 -1
- package/dist/chunk-OLBOTK3O.js.map +0 -1
- package/dist/chunk-PPNTD5LO.js +0 -330
- package/dist/chunk-PPNTD5LO.js.map +0 -1
- package/dist/chunk-Q2LH2DAB.js.map +0 -1
- package/dist/chunk-Q6DR5QUH.js.map +0 -1
- package/dist/chunk-QESUUPOE.js.map +0 -1
- package/dist/chunk-QGGSLMO3.js.map +0 -1
- package/dist/chunk-SEBPPFUW.js.map +0 -1
- package/dist/chunk-SYQ7R2JO.js.map +0 -1
- package/dist/chunk-TOPAIL5W.js.map +0 -1
- package/dist/chunk-U4VYHKPM.js.map +0 -1
- package/dist/chunk-UOWHJ6BE.js.map +0 -1
- package/dist/chunk-XKEG3SCV.js.map +0 -1
- package/dist/chunk-Y3V43XCU.js.map +0 -1
- package/dist/chunk-YKXBGCFD.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/new/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { resolveAuthor } from \"../../lib/config.js\";\nimport { writeFile, directoryExists } from \"../../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\n\nconst DEFAULT_AUTHOR = \"@local\";\nconst DEFAULT_CATEGORY = \"local\";\nconst KEBAB_CASE_PATTERN = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Validates that a skill name follows kebab-case convention.\n * Must start with lowercase letter, followed by lowercase letters, numbers, or hyphens.\n */\nexport function validateSkillName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Skill name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Skill name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\n/**\n * Converts kebab-case to Title Case.\n * e.g., \"my-patterns\" -> \"My Patterns\"\n */\nexport function toTitleCase(kebabCase: string): string {\n return kebabCase\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/**\n * Generates the SKILL.md content with frontmatter.\n */\nexport function generateSkillMd(name: string, author: string): string {\n const titleName = toTitleCase(name);\n const skillId = `${name} (${author})`;\n\n return `---\nname: ${skillId}\ndescription: Brief description of this skill\n---\n\n# ${titleName}\n\n> **Quick Guide:** Add a brief summary of what this skill teaches.\n\n---\n\n<critical_requirements>\n\n## CRITICAL: Before Using This Skill\n\n**(Add critical requirements here)**\n\n</critical_requirements>\n\n---\n\n**When to use:**\n\n- Add use cases here\n\n**Key patterns covered:**\n\n- Add patterns here\n\n---\n\n<patterns>\n\n## Core Patterns\n\n### Pattern 1: Example Pattern\n\nAdd your patterns here.\n\n</patterns>\n\n---\n\n<critical_reminders>\n\n## CRITICAL REMINDERS\n\n**(Repeat critical requirements here)**\n\n</critical_reminders>\n`;\n}\n\n/**\n * Generates the metadata.yaml content.\n */\nexport function generateMetadataYaml(\n name: string,\n author: string,\n category: string,\n): string {\n const titleName = toTitleCase(name);\n\n return `# yaml-language-server: $schema=https://raw.githubusercontent.com/claude-collective/skills/main/schemas/metadata.schema.json\ncategory: ${category}\ncategory_exclusive: false\nauthor: \"${author}\"\nversion: 1\ncli_name: ${titleName}\ncli_description: Brief description\nusage_guidance: Use when <guidance>.\ntags:\n - local\n - custom\n`;\n}\n\nexport default class NewSkill extends BaseCommand {\n static summary = \"Create a new local skill with proper structure\";\n static description =\n \"Create a new local skill scaffold with SKILL.md and metadata.yaml files\";\n\n static args = {\n name: Args.string({\n description: \"Name of the skill to create (kebab-case)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n author: Flags.string({\n char: \"a\",\n description: \"Author identifier (e.g., @myhandle)\",\n required: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Skill category\",\n default: DEFAULT_CATEGORY,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skill directory\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewSkill);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(\"Create New Skill\");\n this.log(\"\");\n\n // Validate skill name\n const validationError = validateSkillName(args.name);\n if (validationError) {\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Determine author: flag > project config > default\n let author = flags.author;\n if (!author) {\n author = (await resolveAuthor(projectDir)) || DEFAULT_AUTHOR;\n }\n\n const category = flags.category;\n\n // Determine skill directory path\n const skillDir = path.join(projectDir, LOCAL_SKILLS_PATH, args.name);\n\n // Check if directory already exists\n if (await directoryExists(skillDir)) {\n if (!flags.force) {\n this.error(\n `Skill directory already exists: ${skillDir}\\nUse --force to overwrite.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n this.warn(`Overwriting existing skill at ${skillDir}`);\n }\n\n this.log(`Skill name: ${args.name}`);\n this.log(`Author: ${author}`);\n this.log(`Category: ${category}`);\n this.log(`Directory: ${skillDir}`);\n this.log(\"\");\n\n if (flags[\"dry-run\"]) {\n this.log(\"[DRY RUN] Would create skill files\");\n return;\n }\n\n this.log(\"Creating skill files...\");\n\n try {\n // Generate file contents\n const skillMdContent = generateSkillMd(args.name, author);\n const metadataContent = generateMetadataYaml(args.name, author, category);\n\n // Write files (writeFile automatically creates parent directories)\n const skillMdPath = path.join(skillDir, \"SKILL.md\");\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n\n await writeFile(skillMdPath, skillMdContent);\n await writeFile(metadataPath, metadataContent);\n\n this.log(\"\");\n this.logSuccess(`Created SKILL.md at ${skillMdPath}`);\n this.logSuccess(`Created metadata.yaml at ${metadataPath}`);\n this.log(\"\");\n this.log(\n \"Skill created successfully! Run 'cc compile' to include it in your agents.\",\n );\n this.log(\"\");\n } catch (error) {\n this.error(\n error instanceof Error ? error.message : \"Unknown error occurred\",\n { exit: EXIT_CODES.ERROR },\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
hashFile
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-KAAEN2PO.js";
|
|
5
5
|
import {
|
|
6
6
|
loadSkillsMatrixFromSource
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-QESUUPOE.js";
|
|
11
|
-
import {
|
|
12
|
-
LOCAL_SKILLS_PATH
|
|
13
|
-
} from "../chunk-A3J6IAXK.js";
|
|
7
|
+
} from "../chunk-CPZOTVCI.js";
|
|
8
|
+
import "../chunk-B7CCVP6Q.js";
|
|
9
|
+
import "../chunk-IMDW5ZUP.js";
|
|
14
10
|
import {
|
|
15
11
|
BaseCommand,
|
|
16
12
|
EXIT_CODES
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
13
|
+
} from "../chunk-EHS3TWWP.js";
|
|
14
|
+
import "../chunk-V46GGCCI.js";
|
|
15
|
+
import "../chunk-3U3R4NCG.js";
|
|
19
16
|
import {
|
|
20
17
|
fileExists,
|
|
21
18
|
listDirectories,
|
|
22
19
|
readFile
|
|
23
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-TKFPKEV3.js";
|
|
21
|
+
import {
|
|
22
|
+
LOCAL_SKILLS_PATH
|
|
23
|
+
} from "../chunk-76DWXGQE.js";
|
|
24
24
|
import {
|
|
25
25
|
init_esm_shims
|
|
26
26
|
} from "../chunk-DHET7RCE.js";
|
|
27
27
|
|
|
28
|
-
// src/cli
|
|
28
|
+
// src/cli/commands/outdated.ts
|
|
29
29
|
init_esm_shims();
|
|
30
30
|
import { Flags } from "@oclif/core";
|
|
31
31
|
import { printTable } from "@oclif/table";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli-v2/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { hashFile } from \"../lib/versioning.js\";\nimport { fileExists, readFile, listDirectories } from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\n\n/**\n * Status values for skill comparison\n */\ntype SkillStatus = \"current\" | \"outdated\" | \"local-only\";\n\n/**\n * Result of comparing a local skill to its source\n */\ninterface SkillComparisonResult {\n id: string;\n localHash: string | null;\n sourceHash: string | null;\n status: SkillStatus;\n}\n\n/**\n * Summary counts for the comparison results\n */\ninterface ComparisonSummary {\n outdated: number;\n current: number;\n localOnly: number;\n}\n\n/**\n * ForkedFrom metadata stored in local skill's metadata.yaml\n */\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\n/**\n * Local skill metadata structure\n */\ninterface LocalSkillMetadata {\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\n/**\n * Read forked_from metadata from a local skill's metadata.yaml\n */\nasync function readForkedFromMetadata(\n skillDir: string,\n): Promise<ForkedFromMetadata | null> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const metadata = parseYaml(content) as LocalSkillMetadata;\n\n return metadata.forked_from ?? null;\n}\n\n/**\n * Get local skills with their forked_from metadata\n */\nasync function getLocalSkillsWithMetadata(\n projectDir: string,\n): Promise<\n Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>\n> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const result = new Map<\n string,\n { dirName: string; forkedFrom: ForkedFromMetadata | null }\n >();\n\n if (!(await fileExists(localSkillsPath))) {\n return result;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const dirName of skillDirs) {\n const skillDir = path.join(localSkillsPath, dirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n // Use the skill_id from forked_from if available, otherwise use directory name\n const skillId = forkedFrom?.skill_id ?? dirName;\n\n result.set(skillId, { dirName, forkedFrom });\n }\n\n return result;\n}\n\n/**\n * Compute source hash for a skill's SKILL.md file\n */\nasync function computeSourceHash(\n sourcePath: string,\n skillPath: string,\n): Promise<string | null> {\n const skillMdPath = path.join(sourcePath, \"src\", skillPath, \"SKILL.md\");\n\n if (!(await fileExists(skillMdPath))) {\n return null;\n }\n\n return hashFile(skillMdPath);\n}\n\n/**\n * Compare local skills against source and determine status\n */\nasync function compareSkills(\n projectDir: string,\n sourcePath: string,\n sourceSkills: Record<string, { path: string }>,\n): Promise<SkillComparisonResult[]> {\n const results: SkillComparisonResult[] = [];\n const localSkills = await getLocalSkillsWithMetadata(projectDir);\n\n // Process local skills\n for (const [skillId, { forkedFrom }] of localSkills) {\n if (!forkedFrom) {\n // Local-only skill (no forked_from metadata)\n results.push({\n id: skillId,\n localHash: null,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const localHash = forkedFrom.content_hash;\n const sourceSkill = sourceSkills[forkedFrom.skill_id];\n\n if (!sourceSkill) {\n // Skill was forked from a source that no longer exists\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);\n\n if (sourceHash === null) {\n // Source skill's SKILL.md not found\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const status: SkillStatus =\n localHash === sourceHash ? \"current\" : \"outdated\";\n\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash,\n status,\n });\n }\n\n // Sort results by skill ID\n results.sort((a, b) => a.id.localeCompare(b.id));\n\n return results;\n}\n\n/**\n * Calculate summary counts from comparison results\n */\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n return {\n outdated: results.filter((r) => r.status === \"outdated\").length,\n current: results.filter((r) => r.status === \"current\").length,\n localOnly: results.filter((r) => r.status === \"local-only\").length,\n };\n}\n\n/**\n * Format hash for display\n */\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary =\n \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const projectDir = process.cwd();\n\n try {\n // Check if local skills directory exists\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n // Build source skills map for lookup\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(matrix.skills)) {\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Compare local skills against source\n const results = await compareSkills(projectDir, sourcePath, sourceSkills);\n const summary = calculateSummary(results);\n\n // Output results\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n // Use @oclif/table for table output\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n // Display summary\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n // Exit with appropriate code if there are outdated skills\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { hashFile } from \"../lib/versioning.js\";\nimport { fileExists, readFile, listDirectories } from \"../utils/fs.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\n\n/**\n * Status values for skill comparison\n */\ntype SkillStatus = \"current\" | \"outdated\" | \"local-only\";\n\n/**\n * Result of comparing a local skill to its source\n */\ninterface SkillComparisonResult {\n id: string;\n localHash: string | null;\n sourceHash: string | null;\n status: SkillStatus;\n}\n\n/**\n * Summary counts for the comparison results\n */\ninterface ComparisonSummary {\n outdated: number;\n current: number;\n localOnly: number;\n}\n\n/**\n * ForkedFrom metadata stored in local skill's metadata.yaml\n */\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\n/**\n * Local skill metadata structure\n */\ninterface LocalSkillMetadata {\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\n/**\n * Read forked_from metadata from a local skill's metadata.yaml\n */\nasync function readForkedFromMetadata(\n skillDir: string,\n): Promise<ForkedFromMetadata | null> {\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const metadata = parseYaml(content) as LocalSkillMetadata;\n\n return metadata.forked_from ?? null;\n}\n\n/**\n * Get local skills with their forked_from metadata\n */\nasync function getLocalSkillsWithMetadata(\n projectDir: string,\n): Promise<\n Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>\n> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const result = new Map<\n string,\n { dirName: string; forkedFrom: ForkedFromMetadata | null }\n >();\n\n if (!(await fileExists(localSkillsPath))) {\n return result;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const dirName of skillDirs) {\n const skillDir = path.join(localSkillsPath, dirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n // Use the skill_id from forked_from if available, otherwise use directory name\n const skillId = forkedFrom?.skill_id ?? dirName;\n\n result.set(skillId, { dirName, forkedFrom });\n }\n\n return result;\n}\n\n/**\n * Compute source hash for a skill's SKILL.md file\n */\nasync function computeSourceHash(\n sourcePath: string,\n skillPath: string,\n): Promise<string | null> {\n const skillMdPath = path.join(sourcePath, \"src\", skillPath, \"SKILL.md\");\n\n if (!(await fileExists(skillMdPath))) {\n return null;\n }\n\n return hashFile(skillMdPath);\n}\n\n/**\n * Compare local skills against source and determine status\n */\nasync function compareSkills(\n projectDir: string,\n sourcePath: string,\n sourceSkills: Record<string, { path: string }>,\n): Promise<SkillComparisonResult[]> {\n const results: SkillComparisonResult[] = [];\n const localSkills = await getLocalSkillsWithMetadata(projectDir);\n\n // Process local skills\n for (const [skillId, { forkedFrom }] of localSkills) {\n if (!forkedFrom) {\n // Local-only skill (no forked_from metadata)\n results.push({\n id: skillId,\n localHash: null,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const localHash = forkedFrom.content_hash;\n const sourceSkill = sourceSkills[forkedFrom.skill_id];\n\n if (!sourceSkill) {\n // Skill was forked from a source that no longer exists\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);\n\n if (sourceHash === null) {\n // Source skill's SKILL.md not found\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n });\n continue;\n }\n\n const status: SkillStatus =\n localHash === sourceHash ? \"current\" : \"outdated\";\n\n results.push({\n id: forkedFrom.skill_id,\n localHash,\n sourceHash,\n status,\n });\n }\n\n // Sort results by skill ID\n results.sort((a, b) => a.id.localeCompare(b.id));\n\n return results;\n}\n\n/**\n * Calculate summary counts from comparison results\n */\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n return {\n outdated: results.filter((r) => r.status === \"outdated\").length,\n current: results.filter((r) => r.status === \"current\").length,\n localOnly: results.filter((r) => r.status === \"local-only\").length,\n };\n}\n\n/**\n * Format hash for display\n */\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary =\n \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const projectDir = process.cwd();\n\n try {\n // Check if local skills directory exists\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\"No local skills found. Run `cc init` or `cc edit` first.\");\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n // Build source skills map for lookup\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(matrix.skills)) {\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Compare local skills against source\n const results = await compareSkills(projectDir, sourcePath, sourceSkills);\n const summary = calculateSummary(results);\n\n // Output results\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n // Use @oclif/table for table output\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n // Display summary\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n // Exit with appropriate code if there are outdated skills\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/commands/search.js
CHANGED
|
@@ -1,25 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SkillSearch
|
|
4
|
+
} from "../chunk-ACNBKXXJ.js";
|
|
5
|
+
import "../chunk-Z2CWURZ6.js";
|
|
2
6
|
import {
|
|
3
7
|
loadSkillsMatrixFromSource
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
} from "../chunk-CPZOTVCI.js";
|
|
9
|
+
import "../chunk-B7CCVP6Q.js";
|
|
10
|
+
import {
|
|
11
|
+
fetchFromSource
|
|
12
|
+
} from "../chunk-IMDW5ZUP.js";
|
|
13
|
+
import {
|
|
14
|
+
BaseCommand,
|
|
15
|
+
EXIT_CODES
|
|
16
|
+
} from "../chunk-EHS3TWWP.js";
|
|
17
|
+
import {
|
|
18
|
+
resolveAllSources
|
|
19
|
+
} from "../chunk-V46GGCCI.js";
|
|
20
|
+
import "../chunk-3U3R4NCG.js";
|
|
21
|
+
import {
|
|
22
|
+
copy,
|
|
23
|
+
ensureDir,
|
|
24
|
+
fileExists,
|
|
25
|
+
listDirectories
|
|
26
|
+
} from "../chunk-TKFPKEV3.js";
|
|
9
27
|
import {
|
|
10
|
-
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import "../chunk-TOPAIL5W.js";
|
|
13
|
-
import "../chunk-MMDXNZPF.js";
|
|
28
|
+
LOCAL_SKILLS_PATH
|
|
29
|
+
} from "../chunk-76DWXGQE.js";
|
|
14
30
|
import {
|
|
15
31
|
init_esm_shims
|
|
16
32
|
} from "../chunk-DHET7RCE.js";
|
|
17
33
|
|
|
18
|
-
// src/cli
|
|
34
|
+
// src/cli/commands/search.tsx
|
|
19
35
|
init_esm_shims();
|
|
20
36
|
import { Args, Flags } from "@oclif/core";
|
|
37
|
+
import { render } from "ink";
|
|
21
38
|
import { printTable } from "@oclif/table";
|
|
39
|
+
import path from "path";
|
|
40
|
+
|
|
41
|
+
// src/cli/components/skill-search/index.ts
|
|
42
|
+
init_esm_shims();
|
|
43
|
+
|
|
44
|
+
// src/cli/commands/search.tsx
|
|
45
|
+
import { jsx } from "react/jsx-runtime";
|
|
22
46
|
var MAX_DESCRIPTION_WIDTH = 50;
|
|
47
|
+
var DEFAULT_SKILLS_SUBDIR = "skills";
|
|
23
48
|
function truncate(str, maxLength) {
|
|
24
49
|
if (str.length <= maxLength) return str;
|
|
25
50
|
return str.slice(0, maxLength - 3) + "...";
|
|
@@ -40,25 +65,190 @@ function matchesCategory(skill, category) {
|
|
|
40
65
|
const lowerCategory = category.toLowerCase();
|
|
41
66
|
return skill.category.toLowerCase().includes(lowerCategory);
|
|
42
67
|
}
|
|
68
|
+
function toSourcedSkill(skill, sourceName, sourceUrl) {
|
|
69
|
+
return {
|
|
70
|
+
...skill,
|
|
71
|
+
sourceName,
|
|
72
|
+
sourceUrl
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function fetchSkillsFromSource(source, forceRefresh) {
|
|
76
|
+
try {
|
|
77
|
+
const result = await fetchFromSource(source.url, { forceRefresh });
|
|
78
|
+
const skillsDir = path.join(result.path, DEFAULT_SKILLS_SUBDIR);
|
|
79
|
+
if (!await fileExists(skillsDir)) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const skillDirs = await listDirectories(skillsDir);
|
|
83
|
+
const skills = [];
|
|
84
|
+
for (const skillDir of skillDirs) {
|
|
85
|
+
const skillMdPath = path.join(skillsDir, skillDir, "SKILL.md");
|
|
86
|
+
if (await fileExists(skillMdPath)) {
|
|
87
|
+
skills.push({
|
|
88
|
+
id: skillDir,
|
|
89
|
+
name: skillDir.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
|
|
90
|
+
description: `Skill from ${source.name}`,
|
|
91
|
+
category: "imported",
|
|
92
|
+
categoryExclusive: false,
|
|
93
|
+
tags: [],
|
|
94
|
+
author: "@" + source.name,
|
|
95
|
+
conflictsWith: [],
|
|
96
|
+
recommends: [],
|
|
97
|
+
recommendedBy: [],
|
|
98
|
+
requires: [],
|
|
99
|
+
requiredBy: [],
|
|
100
|
+
alternatives: [],
|
|
101
|
+
discourages: [],
|
|
102
|
+
compatibleWith: [],
|
|
103
|
+
requiresSetup: [],
|
|
104
|
+
providesSetupFor: [],
|
|
105
|
+
sourceName: source.name,
|
|
106
|
+
sourceUrl: source.url,
|
|
107
|
+
path: path.join(skillsDir, skillDir)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return skills;
|
|
112
|
+
} catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
43
116
|
var Search = class _Search extends BaseCommand {
|
|
44
117
|
static summary = "Search available skills";
|
|
45
|
-
static description = "Search skills by name, description, category, or tags
|
|
118
|
+
static description = "Search skills by name, description, category, or tags. Run without arguments or with -i for interactive mode with multi-select.";
|
|
119
|
+
static examples = [
|
|
120
|
+
{
|
|
121
|
+
description: "Search for React skills",
|
|
122
|
+
command: "<%= config.bin %> search react"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
description: "Interactive search mode",
|
|
126
|
+
command: "<%= config.bin %> search"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
description: "Interactive with pre-filled query",
|
|
130
|
+
command: "<%= config.bin %> search -i react"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
description: "Search with category filter",
|
|
134
|
+
command: "<%= config.bin %> search state -c frontend"
|
|
135
|
+
}
|
|
136
|
+
];
|
|
46
137
|
static args = {
|
|
47
138
|
query: Args.string({
|
|
48
139
|
description: "Search query (matches name, description, category, tags)",
|
|
49
|
-
required:
|
|
140
|
+
required: false
|
|
50
141
|
})
|
|
51
142
|
};
|
|
52
143
|
static flags = {
|
|
53
144
|
...BaseCommand.baseFlags,
|
|
145
|
+
interactive: Flags.boolean({
|
|
146
|
+
char: "i",
|
|
147
|
+
description: "Launch interactive search with multi-select",
|
|
148
|
+
default: false
|
|
149
|
+
}),
|
|
54
150
|
category: Flags.string({
|
|
55
151
|
char: "c",
|
|
56
152
|
description: "Filter by category",
|
|
57
153
|
required: false
|
|
154
|
+
}),
|
|
155
|
+
refresh: Flags.boolean({
|
|
156
|
+
description: "Force refresh from remote sources",
|
|
157
|
+
default: false
|
|
58
158
|
})
|
|
59
159
|
};
|
|
60
160
|
async run() {
|
|
61
161
|
const { args, flags } = await this.parse(_Search);
|
|
162
|
+
const projectDir = process.cwd();
|
|
163
|
+
const isInteractive = flags.interactive || !args.query;
|
|
164
|
+
if (isInteractive) {
|
|
165
|
+
await this.runInteractive(args.query, flags.refresh, projectDir);
|
|
166
|
+
} else {
|
|
167
|
+
await this.runStatic(args.query, flags);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Run interactive search mode with full-screen UI
|
|
172
|
+
*/
|
|
173
|
+
async runInteractive(initialQuery, forceRefresh, projectDir) {
|
|
174
|
+
this.log("Loading skills from all sources...");
|
|
175
|
+
try {
|
|
176
|
+
const { matrix, sourcePath } = await loadSkillsMatrixFromSource({
|
|
177
|
+
sourceFlag: void 0,
|
|
178
|
+
projectDir,
|
|
179
|
+
forceRefresh
|
|
180
|
+
});
|
|
181
|
+
const primarySkills = Object.values(matrix.skills).map(
|
|
182
|
+
(skill) => toSourcedSkill(skill, "marketplace", sourcePath)
|
|
183
|
+
);
|
|
184
|
+
const { extras } = await resolveAllSources(projectDir);
|
|
185
|
+
const extraSkillArrays = await Promise.all(
|
|
186
|
+
extras.map((source) => fetchSkillsFromSource(source, forceRefresh))
|
|
187
|
+
);
|
|
188
|
+
const allSkills = [
|
|
189
|
+
...primarySkills,
|
|
190
|
+
...extraSkillArrays.flat()
|
|
191
|
+
];
|
|
192
|
+
const sourceCount = 1 + extras.length;
|
|
193
|
+
this.log(
|
|
194
|
+
`Loaded ${allSkills.length} skills from ${sourceCount} source(s)`
|
|
195
|
+
);
|
|
196
|
+
this.log("");
|
|
197
|
+
const searchResultPromise = new Promise((resolve) => {
|
|
198
|
+
const { waitUntilExit } = render(
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
SkillSearch,
|
|
201
|
+
{
|
|
202
|
+
skills: allSkills,
|
|
203
|
+
sourceCount,
|
|
204
|
+
initialQuery,
|
|
205
|
+
onComplete: (result) => {
|
|
206
|
+
resolve(result);
|
|
207
|
+
},
|
|
208
|
+
onCancel: () => {
|
|
209
|
+
resolve({ selectedSkills: [], cancelled: true });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
);
|
|
214
|
+
waitUntilExit().then(() => {
|
|
215
|
+
resolve({ selectedSkills: [], cancelled: true });
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
const searchResult = await searchResultPromise;
|
|
219
|
+
if (searchResult.cancelled) {
|
|
220
|
+
this.log("Search cancelled");
|
|
221
|
+
this.exit(EXIT_CODES.CANCELLED);
|
|
222
|
+
}
|
|
223
|
+
if (searchResult.selectedSkills.length === 0) {
|
|
224
|
+
this.log("No skills selected");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this.log("");
|
|
228
|
+
this.log(`Importing ${searchResult.selectedSkills.length} skill(s)...`);
|
|
229
|
+
const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);
|
|
230
|
+
for (const skill of searchResult.selectedSkills) {
|
|
231
|
+
if (skill.path) {
|
|
232
|
+
const destPath = path.join(destDir, skill.id);
|
|
233
|
+
await ensureDir(path.dirname(destPath));
|
|
234
|
+
await copy(skill.path, destPath);
|
|
235
|
+
this.logSuccess(`Imported: ${skill.id}`);
|
|
236
|
+
} else {
|
|
237
|
+
this.warn(`Skipping ${skill.id}: No source path available`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
this.log("");
|
|
241
|
+
this.logSuccess("Import complete!");
|
|
242
|
+
this.log(`Skills location: ${destDir}`);
|
|
243
|
+
this.log("Run 'cc compile' to include imported skills in your agents.");
|
|
244
|
+
} catch (error) {
|
|
245
|
+
this.handleError(error);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Run static search mode with table output
|
|
250
|
+
*/
|
|
251
|
+
async runStatic(query, flags) {
|
|
62
252
|
try {
|
|
63
253
|
this.log("Loading skills...");
|
|
64
254
|
const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({
|
|
@@ -66,9 +256,7 @@ var Search = class _Search extends BaseCommand {
|
|
|
66
256
|
});
|
|
67
257
|
this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
|
|
68
258
|
const allSkills = Object.values(matrix.skills);
|
|
69
|
-
let results = allSkills.filter(
|
|
70
|
-
(skill) => matchesQuery(skill, args.query)
|
|
71
|
-
);
|
|
259
|
+
let results = allSkills.filter((skill) => matchesQuery(skill, query));
|
|
72
260
|
if (flags.category) {
|
|
73
261
|
results = results.filter(
|
|
74
262
|
(skill) => matchesCategory(skill, flags.category)
|
|
@@ -77,13 +265,13 @@ var Search = class _Search extends BaseCommand {
|
|
|
77
265
|
results.sort((a, b) => a.name.localeCompare(b.name));
|
|
78
266
|
this.log("");
|
|
79
267
|
if (results.length === 0) {
|
|
80
|
-
this.warn(`No skills found matching "${
|
|
268
|
+
this.warn(`No skills found matching "${query}"`);
|
|
81
269
|
if (flags.category) {
|
|
82
270
|
this.logInfo(`Category filter: ${flags.category}`);
|
|
83
271
|
}
|
|
84
272
|
} else {
|
|
85
273
|
this.logInfo(
|
|
86
|
-
`Found ${results.length} skill${results.length === 1 ? "" : "s"} matching "${
|
|
274
|
+
`Found ${results.length} skill${results.length === 1 ? "" : "s"} matching "${query}"`
|
|
87
275
|
);
|
|
88
276
|
if (flags.category) {
|
|
89
277
|
this.logInfo(`Category filter: ${flags.category}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli-v2/commands/search.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport type { ResolvedSkill } from \"../types-matrix.js\";\n\n/**\n * Maximum description width for table output\n */\nconst MAX_DESCRIPTION_WIDTH = 50;\n\n/**\n * Truncate a string to a maximum length with ellipsis\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 3) + \"...\";\n}\n\n/**\n * Check if a skill matches the search query (case-insensitive)\n */\nfunction matchesQuery(skill: ResolvedSkill, query: string): boolean {\n const lowerQuery = query.toLowerCase();\n\n // Match against name\n if (skill.name.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against ID\n if (skill.id.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against alias\n if (skill.alias?.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against description\n if (skill.description.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against category\n if (skill.category.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against tags\n if (skill.tags.some((tag) => tag.toLowerCase().includes(lowerQuery))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if a skill matches the category filter (case-insensitive)\n */\nfunction matchesCategory(skill: ResolvedSkill, category: string): boolean {\n const lowerCategory = category.toLowerCase();\n return skill.category.toLowerCase().includes(lowerCategory);\n}\n\nexport default class Search extends BaseCommand {\n static summary = \"Search available skills\";\n static description =\n \"Search skills by name, description, category, or tags and display results in a table\";\n\n static args = {\n query: Args.string({\n description: \"Search query (matches name, description, category, tags)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n category: Flags.string({\n char: \"c\",\n description: \"Filter by category\",\n required: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Search);\n\n try {\n this.log(\"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 // Get all skills as array\n const allSkills = Object.values(matrix.skills);\n\n // Filter by query\n let results = allSkills.filter((skill) =>\n matchesQuery(skill, args.query),\n );\n\n // Apply category filter if provided\n if (flags.category) {\n results = results.filter((skill) =>\n matchesCategory(skill, flags.category as string),\n );\n }\n\n // Sort results by name\n results.sort((a, b) => a.name.localeCompare(b.name));\n\n // Display results\n this.log(\"\");\n if (results.length === 0) {\n this.warn(`No skills found matching \"${args.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 \"${args.query}\"`,\n );\n if (flags.category) {\n this.logInfo(`Category filter: ${flags.category}`);\n }\n this.log(\"\");\n\n // Use @oclif/table for table output\n printTable({\n data: results.map((skill) => ({\n id: skill.alias || 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"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,MAAM,aAAa;AAC5B,SAAS,kBAAkB;AAQ3B,IAAM,wBAAwB;AAK9B,SAAS,SAAS,KAAa,WAA2B;AACxD,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI;AACvC;AAKA,SAAS,aAAa,OAAsB,OAAwB;AAClE,QAAM,aAAa,MAAM,YAAY;AAGrC,MAAI,MAAM,KAAK,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAG1D,MAAI,MAAM,GAAG,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAGxD,MAAI,MAAM,OAAO,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAG5D,MAAI,MAAM,YAAY,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAGjE,MAAI,MAAM,SAAS,YAAY,EAAE,SAAS,UAAU,EAAG,QAAO;AAG9D,MAAI,MAAM,KAAK,KAAK,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,UAAU,CAAC,GAAG;AACpE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,OAAsB,UAA2B;AACxE,QAAM,gBAAgB,SAAS,YAAY;AAC3C,SAAO,MAAM,SAAS,YAAY,EAAE,SAAS,aAAa;AAC5D;AAEA,IAAqB,SAArB,MAAqB,gBAAe,YAAY;AAAA,EAC9C,OAAO,UAAU;AAAA,EACjB,OAAO,cACL;AAAA,EAEF,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,UAAU,MAAM,OAAO;AAAA,MACrB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,OAAM;AAE/C,QAAI;AACF,WAAK,IAAI,mBAAmB;AAE5B,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;AAGrE,YAAM,YAAY,OAAO,OAAO,OAAO,MAAM;AAG7C,UAAI,UAAU,UAAU;AAAA,QAAO,CAAC,UAC9B,aAAa,OAAO,KAAK,KAAK;AAAA,MAChC;AAGA,UAAI,MAAM,UAAU;AAClB,kBAAU,QAAQ;AAAA,UAAO,CAAC,UACxB,gBAAgB,OAAO,MAAM,QAAkB;AAAA,QACjD;AAAA,MACF;AAGA,cAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAGnD,WAAK,IAAI,EAAE;AACX,UAAI,QAAQ,WAAW,GAAG;AACxB,aAAK,KAAK,6BAA6B,KAAK,KAAK,GAAG;AACpD,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,KAAK;AAAA,QACzF;AACA,YAAI,MAAM,UAAU;AAClB,eAAK,QAAQ,oBAAoB,MAAM,QAAQ,EAAE;AAAA,QACnD;AACA,aAAK,IAAI,EAAE;AAGX,mBAAW;AAAA,UACT,MAAM,QAAQ,IAAI,CAAC,WAAW;AAAA,YAC5B,IAAI,MAAM,SAAS,MAAM;AAAA,YACzB,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":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/search.tsx","../../src/cli/components/skill-search/index.ts"],"sourcesContent":["/**\n * Search available skills command.\n *\n * Supports two modes:\n * - Static mode (with query arg): Traditional table output for scripting\n * - Interactive mode (no args or -i flag): Full-screen search with multi-select\n *\n * Interactive mode features:\n * - Live filtering as you type\n * - Multi-select for batch import\n * - Keyboard navigation (arrows, vim keys)\n * - Copy skill link to clipboard\n */\nimport React from \"react\";\nimport { Args, Flags } from \"@oclif/core\";\nimport { render } from \"ink\";\nimport { printTable } from \"@oclif/table\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { resolveAllSources, type SourceEntry } from \"../lib/config.js\";\nimport { fetchFromSource } from \"../lib/source-fetcher.js\";\nimport { listDirectories, fileExists, copy, ensureDir } from \"../utils/fs.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n SkillSearch,\n type SkillSearchResult,\n} from \"../components/skill-search/index.js\";\nimport type { SourcedSkill } from \"../components/skill-search/skill-search.js\";\nimport type { ResolvedSkill } from \"../types-matrix.js\";\nimport { LOCAL_SKILLS_PATH } from \"../consts.js\";\n\n/**\n * Maximum description width for table output\n */\nconst MAX_DESCRIPTION_WIDTH = 50;\n\n/** Default skills subdirectory in third-party repos */\nconst DEFAULT_SKILLS_SUBDIR = \"skills\";\n\n/**\n * Truncate a string to a maximum length with ellipsis\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 3) + \"...\";\n}\n\n/**\n * Check if a skill matches the search query (case-insensitive)\n */\nfunction matchesQuery(skill: ResolvedSkill, query: string): boolean {\n const lowerQuery = query.toLowerCase();\n\n // Match against name\n if (skill.name.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against ID\n if (skill.id.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against alias\n if (skill.alias?.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against description\n if (skill.description.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against category\n if (skill.category.toLowerCase().includes(lowerQuery)) return true;\n\n // Match against tags\n if (skill.tags.some((tag) => tag.toLowerCase().includes(lowerQuery))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if a skill matches the category filter (case-insensitive)\n */\nfunction matchesCategory(skill: ResolvedSkill, category: string): boolean {\n const lowerCategory = category.toLowerCase();\n return skill.category.toLowerCase().includes(lowerCategory);\n}\n\n/**\n * Convert ResolvedSkill to SourcedSkill with source attribution\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\n/**\n * Fetch skills from a third-party source.\n * Returns array of SourcedSkills with source attribution.\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 // Check if skills directory exists\n if (!(await fileExists(skillsDir))) {\n return [];\n }\n\n // List skill directories\n const skillDirs = await listDirectories(skillsDir);\n const skills: SourcedSkill[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, \"SKILL.md\");\n if (await fileExists(skillMdPath)) {\n // Create a minimal skill entry\n skills.push({\n id: skillDir,\n name: skillDir\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \"),\n description: `Skill from ${source.name}`,\n category: \"imported\",\n categoryExclusive: false,\n tags: [],\n author: \"@\" + source.name,\n conflictsWith: [],\n recommends: [],\n recommendedBy: [],\n requires: [],\n requiredBy: [],\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 name, 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 // Determine mode: interactive if no query or -i flag\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 /**\n * Run interactive search mode with full-screen UI\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 // Load primary source skills\n const { matrix, sourcePath } = await loadSkillsMatrixFromSource({\n sourceFlag: undefined,\n projectDir,\n forceRefresh,\n });\n\n // Convert to SourcedSkills\n const primarySkills = Object.values(matrix.skills).map((skill) =>\n toSourcedSkill(skill, \"marketplace\", sourcePath),\n );\n\n // Get configured extra sources\n const { extras } = await resolveAllSources(projectDir);\n\n // Fetch skills from extra sources\n const extraSkillArrays = await Promise.all(\n extras.map((source) => fetchSkillsFromSource(source, forceRefresh)),\n );\n\n // Merge all skills (primary first, then extras)\n const allSkills: SourcedSkill[] = [\n ...primarySkills,\n ...extraSkillArrays.flat(),\n ];\n\n // Total source count\n const sourceCount = 1 + extras.length;\n\n this.log(\n `Loaded ${allSkills.length} skills from ${sourceCount} source(s)`,\n );\n this.log(\"\");\n\n // Render interactive search\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 // Also resolve on app exit\n waitUntilExit().then(() => {\n resolve({ selectedSkills: [], cancelled: true });\n });\n });\n\n const searchResult = await searchResultPromise;\n\n // Handle result\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 // Import selected skills\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(\"Import complete!\");\n this.log(`Skills location: ${destDir}`);\n this.log(\"Run 'cc compile' to include imported skills in your agents.\");\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Run static search mode with table output\n */\n private async runStatic(\n query: string,\n flags: { source?: string; category?: string },\n ): Promise<void> {\n try {\n this.log(\"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 // Get all skills as array\n const allSkills = Object.values(matrix.skills);\n\n // Filter by query\n let results = allSkills.filter((skill) => matchesQuery(skill, query));\n\n // Apply category filter if provided\n if (flags.category) {\n results = results.filter((skill) =>\n matchesCategory(skill, flags.category as string),\n );\n }\n\n // Sort results by name\n results.sort((a, b) => a.name.localeCompare(b.name));\n\n // Display results\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 // Use @oclif/table for table output\n printTable({\n data: results.map((skill) => ({\n id: skill.alias || 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 {\n SkillSearch,\n type SkillSearchProps,\n type SkillSearchResult,\n} from \"./skill-search.js\";\n"],"mappings":"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","names":[]}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getPluginInfo
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-57Y5RALO.js";
|
|
5
5
|
import {
|
|
6
6
|
validatePluginManifest
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-MYAVQ23U.js";
|
|
7
|
+
} from "../chunk-NDY25DTL.js";
|
|
8
|
+
import "../chunk-SGJ23HIP.js";
|
|
10
9
|
import {
|
|
11
10
|
compileAllAgents,
|
|
12
11
|
resolveSkillReference
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-I4TPKIYX.js";
|
|
13
|
+
import "../chunk-ED4E6Q2T.js";
|
|
14
|
+
import "../chunk-CJEHB4TB.js";
|
|
15
15
|
import {
|
|
16
16
|
loadSkillsMatrixFromSource
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
20
|
-
import {
|
|
21
|
-
loadGlobalConfig,
|
|
22
|
-
resolveSource
|
|
23
|
-
} from "../chunk-QESUUPOE.js";
|
|
24
|
-
import "../chunk-A3J6IAXK.js";
|
|
17
|
+
} from "../chunk-CPZOTVCI.js";
|
|
18
|
+
import "../chunk-B7CCVP6Q.js";
|
|
19
|
+
import "../chunk-IMDW5ZUP.js";
|
|
25
20
|
import {
|
|
26
21
|
BaseCommand,
|
|
27
22
|
EXIT_CODES
|
|
28
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-EHS3TWWP.js";
|
|
24
|
+
import {
|
|
25
|
+
loadGlobalConfig,
|
|
26
|
+
resolveSource
|
|
27
|
+
} from "../chunk-V46GGCCI.js";
|
|
29
28
|
import {
|
|
30
29
|
verbose
|
|
31
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-3U3R4NCG.js";
|
|
32
31
|
import {
|
|
33
32
|
fileExists,
|
|
34
33
|
readFile
|
|
35
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-TKFPKEV3.js";
|
|
35
|
+
import "../chunk-76DWXGQE.js";
|
|
36
36
|
import {
|
|
37
37
|
init_esm_shims
|
|
38
38
|
} from "../chunk-DHET7RCE.js";
|
|
39
39
|
|
|
40
|
-
// src/cli
|
|
40
|
+
// src/cli/commands/test-imports.ts
|
|
41
41
|
init_esm_shims();
|
|
42
42
|
var TestImports = class extends BaseCommand {
|
|
43
43
|
static summary = "Test that lib imports work (temporary command)";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/test-imports.ts"],"sourcesContent":["import { BaseCommand } from \"../base-command.js\";\n\n// Test imports from the existing lib\nimport { loadGlobalConfig, resolveSource } from \"../lib/config.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { getPluginInfo } from \"../lib/plugin-info.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/source-loader.js\";\nimport { validatePluginManifest } from \"../lib/plugin-validator.js\";\nimport { compileAllAgents } from \"../lib/compiler.js\";\nimport { resolveSkillReference } from \"../lib/resolver.js\";\nimport { fileExists, readFile } from \"../utils/fs.js\";\nimport { verbose } from \"../utils/logger.js\";\n\nexport default class TestImports extends BaseCommand {\n static summary = \"Test that lib imports work (temporary command)\";\n static hidden = true; // Hide from help\n\n async run(): Promise<void> {\n this.log(\"Testing imports from cli/lib/...\");\n\n // Test config loading from init hook\n this.log(\"\\nConfig from init hook:\");\n if (this.sourceConfig) {\n this.log(` ✓ Config loaded successfully`);\n this.log(` Source: ${this.sourceConfig.source}`);\n this.log(` Origin: ${this.sourceConfig.sourceOrigin}`);\n if (this.sourceConfig.marketplace) {\n this.log(` Marketplace: ${this.sourceConfig.marketplace}`);\n }\n } else {\n this.warn(\" Config not loaded - init hook may have failed\");\n }\n\n // Test lib/ utilities\n this.log(\"\\nLib utilities:\");\n this.log(` EXIT_CODES.SUCCESS = ${EXIT_CODES.SUCCESS}`);\n this.log(\n ` loadGlobalConfig is a function: ${typeof loadGlobalConfig === \"function\"}`,\n );\n this.log(\n ` resolveSource is a function: ${typeof resolveSource === \"function\"}`,\n );\n this.log(\n ` getPluginInfo is a function: ${typeof getPluginInfo === \"function\"}`,\n );\n this.log(\n ` loadSkillsMatrixFromSource is a function: ${typeof loadSkillsMatrixFromSource === \"function\"}`,\n );\n this.log(\n ` validatePluginManifest is a function: ${typeof validatePluginManifest === \"function\"}`,\n );\n this.log(\n ` compileAllAgents is a function: ${typeof compileAllAgents === \"function\"}`,\n );\n this.log(\n ` resolveSkillReference is a function: ${typeof resolveSkillReference === \"function\"}`,\n );\n\n // Test utils/ utilities\n this.log(\"\\nUtils utilities:\");\n this.log(` fileExists is a function: ${typeof fileExists === \"function\"}`);\n this.log(` readFile is a function: ${typeof readFile === \"function\"}`);\n this.log(` verbose is a function: ${typeof verbose === \"function\"}`);\n\n this.log(\"\\n✓ All imports successful!\");\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAaA,IAAqB,cAArB,cAAyC,YAAY;AAAA,EACnD,OAAO,UAAU;AAAA,EACjB,OAAO,SAAS;AAAA;AAAA,EAEhB,MAAM,MAAqB;AACzB,SAAK,IAAI,kCAAkC;AAG3C,SAAK,IAAI,0BAA0B;AACnC,QAAI,KAAK,cAAc;AACrB,WAAK,IAAI,qCAAgC;AACzC,WAAK,IAAI,aAAa,KAAK,aAAa,MAAM,EAAE;AAChD,WAAK,IAAI,aAAa,KAAK,aAAa,YAAY,EAAE;AACtD,UAAI,KAAK,aAAa,aAAa;AACjC,aAAK,IAAI,kBAAkB,KAAK,aAAa,WAAW,EAAE;AAAA,MAC5D;AAAA,IACF,OAAO;AACL,WAAK,KAAK,iDAAiD;AAAA,IAC7D;AAGA,SAAK,IAAI,kBAAkB;AAC3B,SAAK,IAAI,0BAA0B,WAAW,OAAO,EAAE;AACvD,SAAK;AAAA,MACH,qCAAqC,OAAO,qBAAqB,UAAU;AAAA,IAC7E;AACA,SAAK;AAAA,MACH,kCAAkC,OAAO,kBAAkB,UAAU;AAAA,IACvE;AACA,SAAK;AAAA,MACH,kCAAkC,OAAO,kBAAkB,UAAU;AAAA,IACvE;AACA,SAAK;AAAA,MACH,+CAA+C,OAAO,+BAA+B,UAAU;AAAA,IACjG;AACA,SAAK;AAAA,MACH,2CAA2C,OAAO,2BAA2B,UAAU;AAAA,IACzF;AACA,SAAK;AAAA,MACH,qCAAqC,OAAO,qBAAqB,UAAU;AAAA,IAC7E;AACA,SAAK;AAAA,MACH,0CAA0C,OAAO,0BAA0B,UAAU;AAAA,IACvF;AAGA,SAAK,IAAI,oBAAoB;AAC7B,SAAK,IAAI,+BAA+B,OAAO,eAAe,UAAU,EAAE;AAC1E,SAAK,IAAI,6BAA6B,OAAO,aAAa,UAAU,EAAE;AACtE,SAAK,IAAI,4BAA4B,OAAO,YAAY,UAAU,EAAE;AAEpE,SAAK,IAAI,kCAA6B;AAAA,EACxC;AACF;","names":[]}
|