@agents-inc/cli 0.90.0 → 0.91.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 +9 -0
- package/dist/{chunk-OWPIGGPP.js → chunk-2RXDM5HN.js} +2 -2
- package/dist/{chunk-JI44SVMW.js → chunk-35WALWDD.js} +2 -2
- package/dist/{chunk-D254XO7K.js → chunk-3O57Z6Q3.js} +2 -2
- package/dist/{chunk-TWOHWCKS.js → chunk-3STOCHK4.js} +2 -2
- package/dist/{chunk-BO4JY7BT.js → chunk-5IR4QU7G.js} +24 -19
- package/dist/chunk-5IR4QU7G.js.map +1 -0
- package/dist/chunk-7QWCPF6F.js +135 -0
- package/dist/chunk-7QWCPF6F.js.map +1 -0
- package/dist/{chunk-VJBCOPMG.js → chunk-AWB6DO24.js} +16 -9
- package/dist/chunk-AWB6DO24.js.map +1 -0
- package/dist/{chunk-SB2R5KHJ.js → chunk-BGICSUQK.js} +2 -2
- package/dist/{chunk-HK53FRMU.js → chunk-DVBA6PGR.js} +3 -7
- package/dist/{chunk-HK53FRMU.js.map → chunk-DVBA6PGR.js.map} +1 -1
- package/dist/{chunk-I5AZKNNL.js → chunk-FEKVKYCN.js} +2 -2
- package/dist/{chunk-7AUGC7PK.js → chunk-G3VPBEBC.js} +2 -2
- package/dist/chunk-M6J5YQ3P.js +100 -0
- package/dist/chunk-M6J5YQ3P.js.map +1 -0
- package/dist/{chunk-3T5XT2VU.js → chunk-MBEXASMU.js} +3 -3
- package/dist/{chunk-TEA5KBIA.js → chunk-NESVWSI7.js} +2 -2
- package/dist/{chunk-V36FRPAU.js → chunk-ORTNQZLF.js} +4 -2
- package/dist/{chunk-V36FRPAU.js.map → chunk-ORTNQZLF.js.map} +1 -1
- package/dist/{chunk-TP6BX5M2.js → chunk-RDQBXB3Y.js} +5 -5
- package/dist/{chunk-VYLF4IIK.js → chunk-TJHCK4OS.js} +2 -2
- package/dist/{chunk-Z5FXZFX2.js → chunk-UK572773.js} +2 -2
- package/dist/{chunk-4ITKYWVG.js → chunk-V75HVZTB.js} +3 -3
- package/dist/chunk-V75HVZTB.js.map +1 -0
- package/dist/commands/build/marketplace.js +58 -40
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +38 -29
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +35 -27
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +35 -32
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/diff.js +4 -3
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +8 -31
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +52 -59
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/import/skill.js +53 -43
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/init.js +17 -18
- package/dist/commands/new/marketplace.js +90 -75
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/outdated.js +82 -91
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +2 -2
- package/dist/commands/uninstall.js +33 -24
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +2 -2
- package/dist/components/wizard/category-grid.js +2 -2
- package/dist/components/wizard/category-grid.test.js +3 -3
- package/dist/components/wizard/domain-selection.js +2 -2
- package/dist/components/wizard/{help-modal.js → info-panel.js} +6 -6
- package/dist/components/wizard/search-modal.js +2 -2
- package/dist/components/wizard/search-modal.test.js +2 -2
- package/dist/components/wizard/source-grid.js +3 -3
- package/dist/components/wizard/source-grid.test.js +4 -4
- package/dist/components/wizard/stack-selection.js +2 -2
- package/dist/components/wizard/stats-panel.js +106 -5
- package/dist/components/wizard/stats-panel.js.map +1 -1
- package/dist/components/wizard/step-agents.js +2 -2
- package/dist/components/wizard/step-agents.test.js +2 -2
- package/dist/components/wizard/step-build.js +4 -5
- package/dist/components/wizard/step-build.test.js +4 -5
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.test.js +1 -1
- 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 +2 -2
- package/dist/components/wizard/step-settings.test.js +2 -2
- package/dist/components/wizard/step-sources.js +6 -6
- package/dist/components/wizard/step-sources.test.js +6 -6
- package/dist/components/wizard/step-stack.js +3 -3
- package/dist/components/wizard/step-stack.test.js +3 -3
- package/dist/components/wizard/wizard-layout.js +5 -5
- package/dist/components/wizard/wizard.js +16 -17
- package/dist/hooks/init.js +17 -18
- package/dist/hooks/init.js.map +1 -1
- package/dist/plugins/dummy-skill/.claude-plugin/.content-hash +1 -0
- package/dist/plugins/dummy-skill/.claude-plugin/plugin.json +13 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +31 -0
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +17 -0
- package/dist/src/agents/developer/ai-developer/examples.md +137 -0
- package/dist/src/agents/developer/ai-developer/intro.md +23 -0
- package/dist/src/agents/developer/ai-developer/metadata.yaml +12 -0
- package/dist/src/agents/developer/ai-developer/output-format.md +228 -0
- package/dist/src/agents/developer/ai-developer/workflow.md +464 -0
- package/dist/src/agents/planning/api-pm/critical-reminders.md +32 -0
- package/dist/src/agents/planning/api-pm/critical-requirements.md +21 -0
- package/dist/src/agents/planning/api-pm/examples.md +157 -0
- package/dist/src/agents/planning/api-pm/intro.md +14 -0
- package/dist/src/agents/planning/api-pm/metadata.yaml +12 -0
- package/dist/src/agents/planning/api-pm/output-format.md +317 -0
- package/dist/src/agents/planning/api-pm/workflow.md +214 -0
- package/dist/src/agents/reviewer/ai-reviewer/critical-reminders.md +23 -0
- package/dist/src/agents/reviewer/ai-reviewer/critical-requirements.md +19 -0
- package/dist/src/agents/reviewer/ai-reviewer/examples.md +131 -0
- package/dist/src/agents/reviewer/ai-reviewer/intro.md +23 -0
- package/dist/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
- package/dist/src/agents/reviewer/ai-reviewer/output-format.md +263 -0
- package/dist/src/agents/reviewer/ai-reviewer/workflow.md +177 -0
- package/dist/src/agents/reviewer/infra-reviewer/critical-reminders.md +21 -0
- package/dist/src/agents/reviewer/infra-reviewer/critical-requirements.md +19 -0
- package/dist/src/agents/reviewer/infra-reviewer/examples.md +123 -0
- package/dist/src/agents/reviewer/infra-reviewer/intro.md +25 -0
- package/dist/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
- package/dist/src/agents/reviewer/infra-reviewer/output-format.md +240 -0
- package/dist/src/agents/reviewer/infra-reviewer/workflow.md +250 -0
- package/dist/src/agents/tester/api-tester/critical-reminders.md +23 -0
- package/dist/src/agents/tester/api-tester/critical-requirements.md +19 -0
- package/dist/src/agents/tester/api-tester/examples.md +74 -0
- package/dist/src/agents/tester/api-tester/intro.md +21 -0
- package/dist/src/agents/tester/api-tester/metadata.yaml +12 -0
- package/dist/src/agents/tester/api-tester/output-format.md +209 -0
- package/dist/src/agents/tester/api-tester/workflow.md +364 -0
- package/dist/stores/wizard-store.js +1 -1
- package/dist/stores/wizard-store.test.js +17 -17
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/developer/ai-developer/critical-reminders.md +31 -0
- package/src/agents/developer/ai-developer/critical-requirements.md +17 -0
- package/src/agents/developer/ai-developer/examples.md +137 -0
- package/src/agents/developer/ai-developer/intro.md +23 -0
- package/src/agents/developer/ai-developer/metadata.yaml +12 -0
- package/src/agents/developer/ai-developer/output-format.md +228 -0
- package/src/agents/developer/ai-developer/workflow.md +464 -0
- package/src/agents/planning/api-pm/critical-reminders.md +32 -0
- package/src/agents/planning/api-pm/critical-requirements.md +21 -0
- package/src/agents/planning/api-pm/examples.md +157 -0
- package/src/agents/planning/api-pm/intro.md +14 -0
- package/src/agents/planning/api-pm/metadata.yaml +12 -0
- package/src/agents/planning/api-pm/output-format.md +317 -0
- package/src/agents/planning/api-pm/workflow.md +214 -0
- package/src/agents/reviewer/ai-reviewer/critical-reminders.md +23 -0
- package/src/agents/reviewer/ai-reviewer/critical-requirements.md +19 -0
- package/src/agents/reviewer/ai-reviewer/examples.md +131 -0
- package/src/agents/reviewer/ai-reviewer/intro.md +23 -0
- package/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
- package/src/agents/reviewer/ai-reviewer/output-format.md +263 -0
- package/src/agents/reviewer/ai-reviewer/workflow.md +177 -0
- package/src/agents/reviewer/infra-reviewer/critical-reminders.md +21 -0
- package/src/agents/reviewer/infra-reviewer/critical-requirements.md +19 -0
- package/src/agents/reviewer/infra-reviewer/examples.md +123 -0
- package/src/agents/reviewer/infra-reviewer/intro.md +25 -0
- package/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
- package/src/agents/reviewer/infra-reviewer/output-format.md +240 -0
- package/src/agents/reviewer/infra-reviewer/workflow.md +250 -0
- package/src/agents/tester/api-tester/critical-reminders.md +23 -0
- package/src/agents/tester/api-tester/critical-requirements.md +19 -0
- package/src/agents/tester/api-tester/examples.md +74 -0
- package/src/agents/tester/api-tester/intro.md +21 -0
- package/src/agents/tester/api-tester/metadata.yaml +12 -0
- package/src/agents/tester/api-tester/output-format.md +209 -0
- package/src/agents/tester/api-tester/workflow.md +364 -0
- package/dist/chunk-4ITKYWVG.js.map +0 -1
- package/dist/chunk-BO4JY7BT.js.map +0 -1
- package/dist/chunk-FGVCQBXH.js +0 -143
- package/dist/chunk-FGVCQBXH.js.map +0 -1
- package/dist/chunk-FQTYF3OU.js +0 -114
- package/dist/chunk-FQTYF3OU.js.map +0 -1
- package/dist/chunk-O423DMUE.js +0 -111
- package/dist/chunk-O423DMUE.js.map +0 -1
- package/dist/chunk-VJBCOPMG.js.map +0 -1
- /package/dist/{chunk-OWPIGGPP.js.map → chunk-2RXDM5HN.js.map} +0 -0
- /package/dist/{chunk-JI44SVMW.js.map → chunk-35WALWDD.js.map} +0 -0
- /package/dist/{chunk-D254XO7K.js.map → chunk-3O57Z6Q3.js.map} +0 -0
- /package/dist/{chunk-TWOHWCKS.js.map → chunk-3STOCHK4.js.map} +0 -0
- /package/dist/{chunk-SB2R5KHJ.js.map → chunk-BGICSUQK.js.map} +0 -0
- /package/dist/{chunk-I5AZKNNL.js.map → chunk-FEKVKYCN.js.map} +0 -0
- /package/dist/{chunk-7AUGC7PK.js.map → chunk-G3VPBEBC.js.map} +0 -0
- /package/dist/{chunk-3T5XT2VU.js.map → chunk-MBEXASMU.js.map} +0 -0
- /package/dist/{chunk-TEA5KBIA.js.map → chunk-NESVWSI7.js.map} +0 -0
- /package/dist/{chunk-TP6BX5M2.js.map → chunk-RDQBXB3Y.js.map} +0 -0
- /package/dist/{chunk-VYLF4IIK.js.map → chunk-TJHCK4OS.js.map} +0 -0
- /package/dist/{chunk-Z5FXZFX2.js.map → chunk-UK572773.js.map} +0 -0
- /package/dist/components/wizard/{help-modal.js.map → info-panel.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/edit.tsx"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render } from \"ink\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { Wizard, type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { CLAUDE_DIR, CLI_BIN_NAME, GLOBAL_INSTALL_ROOT, SOURCE_DISPLAY_NAMES } from \"../consts.js\";\nimport {\n detectProject,\n loadSource,\n copyLocalSkills,\n ensureMarketplace,\n installPluginSkills,\n uninstallPluginSkills,\n loadAgentDefs,\n type AgentDefs,\n writeProjectConfig,\n compileAgents,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n type Installation,\n detectMigrations,\n executeMigration,\n deriveInstallMode,\n} from \"../lib/installation/index.js\";\nimport { matrix, getSkillById } from \"../lib/matrix/matrix-provider\";\nimport type { SourceLoadResult } from \"../lib/loading/index.js\";\nimport { discoverAllPluginSkills } from \"../lib/plugins/index.js\";\nimport { deleteLocalSkill, migrateLocalSkillScope } from \"../lib/skills/index.js\";\nimport type { SkillId, AgentName, ProjectConfig } from \"../types/index.js\";\nimport { claudePluginInstall, claudePluginUninstall } from \"../utils/exec.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { remove } from \"../utils/fs.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport { ERROR_MESSAGES, INFO_MESSAGES, STATUS_MESSAGES } from \"../utils/messages.js\";\n\nfunction formatSourceDisplayName(sourceName: string): string {\n return SOURCE_DISPLAY_NAMES[sourceName] ?? sourceName;\n}\n\ntype EditContext = {\n installation: Installation;\n projectConfig: ProjectConfig | null;\n projectDir: string;\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n currentSkillIds: SkillId[];\n};\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static examples = [\n {\n description: \"Open the edit wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Edit with a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n {\n description: \"Force refresh skills from remote\",\n command: \"<%= config.bin %> <%= command.id %> --refresh\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n \"agent-source\": Flags.string({\n description: \"Remote agent partials source (default: local CLI)\",\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Edit);\n const cwd = process.cwd();\n\n const context = await this.loadContext(flags);\n const result = await this.runEditWizard(context, cwd);\n if (!result) this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n\n this.reportValidationErrors(result);\n\n const changes = detectConfigChanges(context.projectConfig, result, context.currentSkillIds);\n if (!hasAnyChanges(changes)) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n this.log(\"Plugin unchanged\\n\");\n return;\n }\n\n this.logChangeSummary(changes);\n const migratedSkillIds = await this.applyMigrations(changes, result, context, cwd);\n await this.applyScopeChanges(changes, result, context, cwd);\n await this.applySourceChanges(changes, result, context, cwd, migratedSkillIds);\n await this.applyPluginChanges(changes, result, context, cwd);\n await this.copyNewLocalSkills(changes, result, context, cwd);\n await this.writeConfigAndCompile(result, context, flags, cwd);\n await this.cleanupStaleAgentFiles(changes, cwd);\n this.logCompletionSummary(changes);\n }\n\n private async loadContext(flags: { source?: string; refresh: boolean }): Promise<EditContext> {\n const detected = await detectProject();\n if (!detected) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n const { installation, config: projectConfig } = detected;\n\n // Use installation.projectDir for reads (loading config, discovering installed skills).\n // Use cwd for writes (config saves, plugin installs, scope migrations, recompilation output)\n // and for the locked-items check (determining whether global items are read-only).\n const projectDir = installation.projectDir;\n\n let sourceResult: SourceLoadResult;\n let startupMessages: StartupMessage[] = [];\n try {\n const loaded = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n captureStartupMessages: true,\n });\n sourceResult = loaded.sourceResult;\n startupMessages = loaded.startupMessages;\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n startupMessages.push({\n level: \"info\",\n text: `Loaded ${Object.keys(matrix.skills).length} skills (${sourceInfo})`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n let currentSkillIds: SkillId[];\n try {\n const discoveredSkills = await discoverAllPluginSkills(projectDir);\n // Boundary cast: discoverAllPluginSkills keys are skill IDs from frontmatter\n const pluginSkillIds = Object.keys(discoveredSkills) as SkillId[];\n\n // Merge plugin-discovered skills with config skills (catches local skills and\n // global-scoped plugins that discoverAllPluginSkills doesn't find).\n const configSkillIds = projectConfig?.skills?.map((s) => s.id) ?? [];\n const mergedIds = new Set<SkillId>([...pluginSkillIds, ...configSkillIds]);\n currentSkillIds = [...mergedIds];\n\n startupMessages.push({\n level: \"info\",\n text: `Found ${currentSkillIds.length} installed skills`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n return {\n installation,\n projectConfig,\n projectDir,\n sourceResult,\n startupMessages,\n currentSkillIds,\n };\n }\n\n private async runEditWizard(context: EditContext, cwd: string): Promise<WizardResultV2 | null> {\n const { projectConfig, projectDir, currentSkillIds } = context;\n\n let wizardResult: WizardResultV2 | null = null;\n\n // D9: In project context, existing global items are read-only (locked).\n // When editing from ~/ (global context), nothing is locked.\n // Uses cwd (not projectDir) so that global items are correctly locked\n // even when detectInstallation() fell back to the global installation.\n const isGlobalDir = cwd === GLOBAL_INSTALL_ROOT;\n const lockedSkillIds = isGlobalDir\n ? undefined\n : projectConfig?.skills?.filter((s) => s.scope === \"global\").map((s) => s.id);\n const lockedAgentNames = isGlobalDir\n ? undefined\n : projectConfig?.agents?.filter((a) => a.scope === \"global\").map((a) => a.name);\n\n const { waitUntilExit } = render(\n <Wizard\n version={this.config.version}\n initialStep=\"build\"\n initialDomains={projectConfig?.domains}\n initialAgents={projectConfig?.selectedAgents}\n installedSkillIds={currentSkillIds}\n installedSkillConfigs={projectConfig?.skills}\n lockedSkillIds={lockedSkillIds}\n installedAgentConfigs={projectConfig?.agents}\n lockedAgentNames={lockedAgentNames}\n isEditingFromGlobalScope={isGlobalDir}\n projectDir={projectDir}\n startupMessages={context.startupMessages}\n onComplete={(result) => {\n wizardResult = result;\n }}\n onCancel={() => {\n this.log(\"\\nEdit cancelled\");\n }}\n />,\n );\n\n await waitUntilExit();\n\n // TypeScript can't track that onComplete callback mutates wizardResult before waitUntilExit resolves\n const result = wizardResult as WizardResultV2 | null;\n\n if (!result || result.cancelled) return null;\n return result;\n }\n\n private reportValidationErrors(result: WizardResultV2): void {\n if (result.validation.errors.length > 0) {\n for (const err of result.validation.errors) {\n this.warn(err.message);\n }\n }\n }\n\n private logChangeSummary(changes: ConfigChanges): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n } = changes;\n\n this.log(\"\\nChanges:\");\n for (const skillId of addedSkills) {\n this.log(` + ${getSkillById(skillId).displayName}`);\n }\n for (const skillId of removedSkills) {\n const skill = matrix.skills[skillId];\n this.log(` - ${skill?.displayName ?? skillId}`);\n }\n for (const agentName of addedAgents) {\n this.log(` + ${agentName} (agent)`);\n }\n for (const agentName of removedAgents) {\n this.log(` - ${agentName} (agent)`);\n }\n for (const [skillId, change] of sourceChanges) {\n const fromLabel = formatSourceDisplayName(change.from);\n const toLabel = formatSourceDisplayName(change.to);\n this.log(` ~ ${skillId} (${fromLabel} \\u2192 ${toLabel})`);\n }\n for (const [skillId, change] of scopeChanges) {\n const fromLabel = change.from === \"global\" ? \"[G]\" : \"[P]\";\n const toLabel = change.to === \"global\" ? \"[G]\" : \"[P]\";\n this.log(` ~ ${skillId} (${fromLabel} \\u2192 ${toLabel})`);\n }\n for (const [agentName, change] of agentScopeChanges) {\n const fromLabel = change.from === \"global\" ? \"[G]\" : \"[P]\";\n const toLabel = change.to === \"global\" ? \"[G]\" : \"[P]\";\n this.log(` ~ ${agentName} (${fromLabel} \\u2192 ${toLabel})`);\n }\n this.log(\"\");\n }\n\n private async applyMigrations(\n _changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<Set<SkillId>> {\n const oldSkills = context.projectConfig?.skills ?? [];\n const migrationPlan = detectMigrations(oldSkills, result.skills);\n const hasMigrations = migrationPlan.toLocal.length > 0 || migrationPlan.toPlugin.length > 0;\n\n if (hasMigrations) {\n if (migrationPlan.toLocal.length > 0) {\n this.log(`Switching ${migrationPlan.toLocal.length} skill(s) to local:`);\n for (const migration of migrationPlan.toLocal) {\n this.log(` - ${migration.id}`);\n }\n }\n if (migrationPlan.toPlugin.length > 0) {\n this.log(`Switching ${migrationPlan.toPlugin.length} skill(s) to plugin:`);\n for (const migration of migrationPlan.toPlugin) {\n this.log(` - ${migration.id}`);\n }\n }\n\n const migrationResult = await executeMigration(migrationPlan, cwd, context.sourceResult);\n\n for (const warning of migrationResult.warnings) {\n this.warn(warning);\n }\n }\n\n return new Set([\n ...migrationPlan.toLocal.map((m) => m.id),\n ...migrationPlan.toPlugin.map((m) => m.id),\n ]);\n }\n\n private async applyScopeChanges(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { scopeChanges } = changes;\n\n // Handle scope migrations (P->G or G->P) for local-mode skills\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = result.skills.find((s) => s.id === skillId);\n if (skillConfig?.source === \"local\") {\n await migrateLocalSkillScope(skillId, change.from, cwd);\n }\n }\n\n // Handle scope migrations for plugin-mode skills\n if (context.sourceResult.marketplace && scopeChanges.size > 0) {\n const pluginScopeResult = await migratePluginSkillScopes(\n scopeChanges,\n result.skills,\n context.sourceResult.marketplace,\n cwd,\n );\n for (const item of pluginScopeResult.failed) {\n this.warn(`Failed to migrate plugin scope for ${item.id}: ${item.error}`);\n }\n }\n }\n\n private async applySourceChanges(\n changes: ConfigChanges,\n _result: WizardResultV2,\n context: EditContext,\n cwd: string,\n migratedSkillIds: Set<SkillId>,\n ): Promise<void> {\n const { sourceChanges } = changes;\n\n // Handle remaining non-migration source changes (e.g., marketplace A -> marketplace B)\n for (const [skillId, change] of sourceChanges) {\n // Skip skills already handled by mode migration\n if (migratedSkillIds.has(skillId)) {\n continue;\n }\n if (change.from === \"local\") {\n const oldSkill = context.projectConfig?.skills?.find((s) => s.id === skillId);\n const deleteDir = oldSkill?.scope === \"global\" ? os.homedir() : cwd;\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n }\n\n private async applyPluginChanges(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { addedSkills, removedSkills } = changes;\n\n if (context.sourceResult.marketplace) {\n const mpResult = await ensureMarketplace(context.sourceResult);\n if (mpResult.registered) {\n this.log(`Registered marketplace: ${mpResult.marketplace}`);\n }\n\n const addedPluginSkills = result.skills.filter(\n (s) => addedSkills.includes(s.id) && s.source !== \"local\",\n );\n if (addedPluginSkills.length > 0) {\n const pluginResult = await installPluginSkills(\n addedPluginSkills,\n context.sourceResult.marketplace,\n cwd,\n );\n for (const item of pluginResult.installed) {\n this.log(`Installing plugin: ${item.ref}...`);\n }\n for (const item of pluginResult.failed) {\n this.warn(`Failed to install plugin ${item.id}: ${item.error}`);\n }\n }\n\n if (removedSkills.length > 0) {\n const uninstallResult = await uninstallPluginSkills(\n removedSkills,\n context.projectConfig?.skills ?? [],\n cwd,\n );\n for (const id of uninstallResult.uninstalled) {\n this.log(`Uninstalling plugin: ${id}...`);\n }\n for (const item of uninstallResult.failed) {\n this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);\n }\n }\n }\n }\n\n private async copyNewLocalSkills(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { addedSkills } = changes;\n\n // Copy newly added local-source skills to .claude/skills/ (split by scope)\n const addedLocalSkills = result.skills.filter(\n (s) => addedSkills.includes(s.id) && s.source === \"local\",\n );\n\n if (addedLocalSkills.length > 0) {\n const copyResult = await copyLocalSkills(addedLocalSkills, cwd, context.sourceResult);\n this.log(`Copied ${copyResult.totalCopied} local skill(s) to .claude/skills/`);\n }\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n context: EditContext,\n flags: { source?: string; refresh: boolean; \"agent-source\"?: string },\n cwd: string,\n ): Promise<void> {\n // Load agent definitions — needed for both config-types.ts and recompilation\n let agentDefsResult: AgentDefs;\n this.log(\n flags[\"agent-source\"]\n ? STATUS_MESSAGES.FETCHING_AGENT_PARTIALS\n : STATUS_MESSAGES.LOADING_AGENT_PARTIALS,\n );\n try {\n agentDefsResult = await loadAgentDefs(flags[\"agent-source\"], {\n forceRefresh: flags.refresh,\n });\n this.log(flags[\"agent-source\"] ? \"✓ Agent partials fetched\\n\" : \"✓ Agent partials loaded\\n\");\n } catch (error) {\n this.handleError(error);\n }\n\n // Persist wizard result to config.ts and config-types.ts (split by scope when in project context)\n try {\n await writeProjectConfig({\n wizardResult: result,\n sourceResult: context.sourceResult,\n projectDir: cwd,\n sourceFlag: flags.source,\n agents: agentDefsResult.agents,\n });\n } catch (error) {\n this.warn(`Could not update config: ${getErrorMessage(error)}`);\n }\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const agentScopeMap = new Map(result.agentConfigs.map((a) => [a.name, a.scope] as const));\n const { allSkills } = await discoverInstalledSkills(cwd);\n const compilationResult = await compileAgents({\n projectDir: cwd,\n sourcePath: agentDefsResult.sourcePath,\n skills: allSkills,\n pluginDir: cwd,\n outputDir: path.join(cwd, CLAUDE_DIR, \"agents\"),\n installMode: deriveInstallMode(result.skills),\n agentScopeMap,\n });\n\n if (compilationResult.failed.length > 0) {\n this.log(\n `✓ Recompiled ${compilationResult.compiled.length} agents (${compilationResult.failed.length} failed)\\n`,\n );\n for (const warning of compilationResult.warnings) {\n this.warn(warning);\n }\n } else if (compilationResult.compiled.length > 0) {\n this.log(`✓ Recompiled ${compilationResult.compiled.length} agents\\n`);\n } else {\n this.log(\"✓ No agents to recompile\\n\");\n }\n } catch (error) {\n this.warn(`Agent recompilation failed: ${getErrorMessage(error)}`);\n this.log(`You can manually recompile with '${CLI_BIN_NAME} compile'.\\n`);\n }\n }\n\n private async cleanupStaleAgentFiles(changes: ConfigChanges, cwd: string): Promise<void> {\n const { agentScopeChanges } = changes;\n\n // Clean up old agent .md files after scope changes.\n // Recompilation wrote the new file to the correct scope directory;\n // now delete the stale copy from the old scope directory.\n for (const [agentName, change] of agentScopeChanges) {\n const oldBaseDir = change.from === \"global\" ? os.homedir() : cwd;\n const oldAgentPath = path.join(oldBaseDir, CLAUDE_DIR, \"agents\", `${agentName}.md`);\n try {\n await remove(oldAgentPath);\n } catch (error) {\n this.warn(`Could not remove old agent file ${oldAgentPath}: ${getErrorMessage(error)}`);\n }\n }\n }\n\n private logCompletionSummary(changes: ConfigChanges): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n } = changes;\n\n const hasAgentChanges = addedAgents.length > 0 || removedAgents.length > 0;\n const hasSourceChanges = sourceChanges.size > 0;\n const hasScopeChanges = scopeChanges.size > 0;\n const hasAgentScopeChanges = agentScopeChanges.size > 0;\n\n const summaryParts = [`${addedSkills.length} added`, `${removedSkills.length} removed`];\n if (hasAgentChanges) {\n summaryParts.push(\n `${addedAgents.length} agent${addedAgents.length !== 1 ? \"s\" : \"\"} added, ${removedAgents.length} agent${removedAgents.length !== 1 ? \"s\" : \"\"} removed`,\n );\n }\n if (hasSourceChanges) {\n summaryParts.push(`${sourceChanges.size} source${sourceChanges.size > 1 ? \"s\" : \"\"} changed`);\n }\n if (hasScopeChanges || hasAgentScopeChanges) {\n const totalScopeChanges = scopeChanges.size + agentScopeChanges.size;\n summaryParts.push(`${totalScopeChanges} scope${totalScopeChanges > 1 ? \"s\" : \"\"} changed`);\n }\n this.log(`\\n\\u2713 Plugin updated! (${summaryParts.join(\", \")})\\n`);\n }\n}\n\ntype ConfigChanges = {\n addedSkills: SkillId[];\n removedSkills: SkillId[];\n addedAgents: AgentName[];\n removedAgents: AgentName[];\n sourceChanges: Map<SkillId, { from: string; to: string }>;\n scopeChanges: Map<SkillId, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>;\n agentScopeChanges: Map<AgentName, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>;\n};\n\nfunction detectConfigChanges(\n oldConfig: ProjectConfig | null,\n wizardResult: WizardResultV2,\n currentSkillIds: SkillId[],\n): ConfigChanges {\n const newSkillIds = wizardResult.skills.map((s) => s.id);\n const addedSkills = newSkillIds.filter((id) => !currentSkillIds.includes(id));\n const removedSkills = currentSkillIds.filter((id) => !newSkillIds.includes(id));\n\n const oldAgentNames = oldConfig?.agents?.map((a) => a.name) ?? [];\n const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);\n const addedAgents = newAgentNames.filter((name) => !oldAgentNames.includes(name));\n const removedAgents = oldAgentNames.filter((name) => !newAgentNames.includes(name));\n\n const sourceChanges = new Map<SkillId, { from: string; to: string }>();\n const scopeChanges = new Map<SkillId, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>();\n if (oldConfig?.skills) {\n for (const newSkill of wizardResult.skills) {\n const oldSkill = oldConfig.skills.find((s) => s.id === newSkill.id);\n if (oldSkill && oldSkill.source !== newSkill.source) {\n sourceChanges.set(newSkill.id, {\n from: oldSkill.source,\n to: newSkill.source,\n });\n }\n if (oldSkill && oldSkill.scope !== newSkill.scope) {\n scopeChanges.set(newSkill.id, {\n from: oldSkill.scope,\n to: newSkill.scope,\n });\n }\n }\n }\n\n const agentScopeChanges = new Map<\n AgentName,\n { from: \"project\" | \"global\"; to: \"project\" | \"global\" }\n >();\n if (oldConfig?.agents) {\n for (const newAgent of wizardResult.agentConfigs) {\n const oldAgent = oldConfig.agents.find((a) => a.name === newAgent.name);\n if (oldAgent && oldAgent.scope !== newAgent.scope) {\n agentScopeChanges.set(newAgent.name, {\n from: oldAgent.scope,\n to: newAgent.scope,\n });\n }\n }\n }\n\n return {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n };\n}\n\nfunction hasAnyChanges(changes: ConfigChanges): boolean {\n return (\n changes.addedSkills.length > 0 ||\n changes.removedSkills.length > 0 ||\n changes.addedAgents.length > 0 ||\n changes.removedAgents.length > 0 ||\n changes.sourceChanges.size > 0 ||\n changes.scopeChanges.size > 0 ||\n changes.agentScopeChanges.size > 0\n );\n}\n\ntype PluginScopeMigrationResult = {\n migrated: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\nasync function migratePluginSkillScopes(\n scopeChanges: Map<SkillId, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>,\n skills: Array<{ id: SkillId; source: string }>,\n marketplace: string,\n projectDir: string,\n): Promise<PluginScopeMigrationResult> {\n const migrated: SkillId[] = [];\n const failed: PluginScopeMigrationResult[\"failed\"] = [];\n\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = skills.find((s) => s.id === skillId);\n if (!skillConfig || skillConfig.source === \"local\") {\n continue;\n }\n\n const oldPluginScope = change.from === \"global\" ? \"user\" : \"project\";\n const newPluginScope = change.to === \"global\" ? \"user\" : \"project\";\n const pluginRef = `${skillId}@${marketplace}`;\n\n try {\n await claudePluginUninstall(skillId, oldPluginScope, projectDir);\n await claudePluginInstall(pluginRef, newPluginScope, projectDir);\n migrated.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { migrated, failed };\n}\n"],"mappings":"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","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/edit.tsx"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render } from \"ink\";\n\nimport { difference, indexBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { Wizard, type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { CLAUDE_DIR, CLI_BIN_NAME, GLOBAL_INSTALL_ROOT, SOURCE_DISPLAY_NAMES } from \"../consts.js\";\nimport {\n detectProject,\n loadSource,\n copyLocalSkills,\n ensureMarketplace,\n installPluginSkills,\n uninstallPluginSkills,\n loadAgentDefs,\n type AgentDefs,\n writeProjectConfig,\n compileAgents,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n type Installation,\n detectMigrations,\n executeMigration,\n deriveInstallMode,\n} from \"../lib/installation/index.js\";\nimport { matrix, getSkillById } from \"../lib/matrix/matrix-provider\";\nimport type { SourceLoadResult } from \"../lib/loading/index.js\";\nimport { discoverAllPluginSkills } from \"../lib/plugins/index.js\";\nimport { deleteLocalSkill, migrateLocalSkillScope } from \"../lib/skills/index.js\";\nimport type { SkillId, AgentName, ProjectConfig } from \"../types/index.js\";\nimport { claudePluginInstall, claudePluginUninstall } from \"../utils/exec.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { remove } from \"../utils/fs.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport { ERROR_MESSAGES, INFO_MESSAGES, STATUS_MESSAGES } from \"../utils/messages.js\";\n\nfunction formatSourceDisplayName(sourceName: string): string {\n return SOURCE_DISPLAY_NAMES[sourceName] ?? sourceName;\n}\n\ntype EditContext = {\n installation: Installation;\n projectConfig: ProjectConfig | null;\n projectDir: string;\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n currentSkillIds: SkillId[];\n};\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static examples = [\n {\n description: \"Open the edit wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Edit with a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n {\n description: \"Force refresh skills from remote\",\n command: \"<%= config.bin %> <%= command.id %> --refresh\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n refresh: Flags.boolean({\n description: \"Force refresh from remote sources\",\n default: false,\n }),\n \"agent-source\": Flags.string({\n description: \"Remote agent partials source (default: local CLI)\",\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Edit);\n const cwd = process.cwd();\n\n const context = await this.loadContext(flags);\n const result = await this.runEditWizard(context, cwd);\n if (!result) this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n\n this.reportValidationErrors(result);\n\n const changes = detectConfigChanges(context.projectConfig, result, context.currentSkillIds);\n if (!hasAnyChanges(changes)) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n this.log(\"Plugin unchanged\\n\");\n return;\n }\n\n this.logChangeSummary(changes);\n const migratedSkillIds = await this.applyMigrations(changes, result, context, cwd);\n await this.applyScopeChanges(changes, result, context, cwd);\n await this.applySourceChanges(changes, result, context, cwd, migratedSkillIds);\n await this.applyPluginChanges(changes, result, context, cwd);\n await this.copyNewLocalSkills(changes, result, context, cwd);\n await this.writeConfigAndCompile(result, context, flags, cwd);\n await this.cleanupStaleAgentFiles(changes, cwd);\n this.logCompletionSummary(changes);\n }\n\n private async loadContext(flags: { source?: string; refresh: boolean }): Promise<EditContext> {\n const detected = await detectProject();\n if (!detected) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n const { installation, config: projectConfig } = detected;\n\n // Use installation.projectDir for reads (loading config, discovering installed skills).\n // Use cwd for writes (config saves, plugin installs, scope migrations, recompilation output)\n // and for the locked-items check (determining whether global items are read-only).\n const projectDir = installation.projectDir;\n\n let sourceResult: SourceLoadResult;\n let startupMessages: StartupMessage[] = [];\n try {\n const loaded = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n captureStartupMessages: true,\n });\n sourceResult = loaded.sourceResult;\n startupMessages = loaded.startupMessages;\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n startupMessages.push({\n level: \"info\",\n text: `Loaded ${Object.keys(matrix.skills).length} skills (${sourceInfo})`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n let currentSkillIds: SkillId[];\n try {\n const discoveredSkills = await discoverAllPluginSkills(projectDir);\n // Boundary cast: discoverAllPluginSkills keys are skill IDs from frontmatter\n const pluginSkillIds = Object.keys(discoveredSkills) as SkillId[];\n\n // Merge plugin-discovered skills with config skills (catches local skills and\n // global-scoped plugins that discoverAllPluginSkills doesn't find).\n const configSkillIds = projectConfig?.skills?.map((s) => s.id) ?? [];\n const mergedIds = new Set<SkillId>([...pluginSkillIds, ...configSkillIds]);\n currentSkillIds = [...mergedIds];\n\n startupMessages.push({\n level: \"info\",\n text: `Found ${currentSkillIds.length} installed skills`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n return {\n installation,\n projectConfig,\n projectDir,\n sourceResult,\n startupMessages,\n currentSkillIds,\n };\n }\n\n private async runEditWizard(context: EditContext, cwd: string): Promise<WizardResultV2 | null> {\n const { projectConfig, projectDir, currentSkillIds } = context;\n\n let wizardResult: WizardResultV2 | null = null;\n\n // D9: In project context, existing global items are read-only (locked).\n // When editing from ~/ (global context), nothing is locked.\n // Uses cwd (not projectDir) so that global items are correctly locked\n // even when detectInstallation() fell back to the global installation.\n const isGlobalDir = cwd === GLOBAL_INSTALL_ROOT;\n const lockedSkillIds = isGlobalDir\n ? undefined\n : projectConfig?.skills?.filter((s) => s.scope === \"global\").map((s) => s.id);\n const lockedAgentNames = isGlobalDir\n ? undefined\n : projectConfig?.agents?.filter((a) => a.scope === \"global\").map((a) => a.name);\n\n const { waitUntilExit } = render(\n <Wizard\n version={this.config.version}\n initialStep=\"build\"\n initialDomains={projectConfig?.domains}\n initialAgents={projectConfig?.selectedAgents}\n installedSkillIds={currentSkillIds}\n installedSkillConfigs={projectConfig?.skills}\n lockedSkillIds={lockedSkillIds}\n installedAgentConfigs={projectConfig?.agents}\n lockedAgentNames={lockedAgentNames}\n isEditingFromGlobalScope={isGlobalDir}\n projectDir={projectDir}\n startupMessages={context.startupMessages}\n onComplete={(result) => {\n wizardResult = result;\n }}\n onCancel={() => {\n this.log(\"\\nEdit cancelled\");\n }}\n />,\n );\n\n await waitUntilExit();\n\n // TypeScript can't track that onComplete callback mutates wizardResult before waitUntilExit resolves\n const result = wizardResult as WizardResultV2 | null;\n\n if (!result || result.cancelled) return null;\n return result;\n }\n\n private reportValidationErrors(result: WizardResultV2): void {\n if (result.validation.errors.length > 0) {\n for (const err of result.validation.errors) {\n this.warn(err.message);\n }\n }\n }\n\n private logChangeSummary(changes: ConfigChanges): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n } = changes;\n\n this.log(\"\\nChanges:\");\n for (const skillId of addedSkills) {\n this.log(` + ${getSkillById(skillId).displayName}`);\n }\n for (const skillId of removedSkills) {\n const skill = matrix.skills[skillId];\n this.log(` - ${skill?.displayName ?? skillId}`);\n }\n for (const agentName of addedAgents) {\n this.log(` + ${agentName} (agent)`);\n }\n for (const agentName of removedAgents) {\n this.log(` - ${agentName} (agent)`);\n }\n for (const [skillId, change] of sourceChanges) {\n const fromLabel = formatSourceDisplayName(change.from);\n const toLabel = formatSourceDisplayName(change.to);\n this.log(` ~ ${skillId} (${fromLabel} \\u2192 ${toLabel})`);\n }\n for (const [skillId, change] of scopeChanges) {\n const fromLabel = change.from === \"global\" ? \"[G]\" : \"[P]\";\n const toLabel = change.to === \"global\" ? \"[G]\" : \"[P]\";\n this.log(` ~ ${skillId} (${fromLabel} \\u2192 ${toLabel})`);\n }\n for (const [agentName, change] of agentScopeChanges) {\n const fromLabel = change.from === \"global\" ? \"[G]\" : \"[P]\";\n const toLabel = change.to === \"global\" ? \"[G]\" : \"[P]\";\n this.log(` ~ ${agentName} (${fromLabel} \\u2192 ${toLabel})`);\n }\n this.log(\"\");\n }\n\n private async applyMigrations(\n _changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<Set<SkillId>> {\n const oldSkills = context.projectConfig?.skills ?? [];\n const migrationPlan = detectMigrations(oldSkills, result.skills);\n const hasMigrations = migrationPlan.toLocal.length > 0 || migrationPlan.toPlugin.length > 0;\n\n if (hasMigrations) {\n if (migrationPlan.toLocal.length > 0) {\n this.log(`Switching ${migrationPlan.toLocal.length} skill(s) to local:`);\n for (const migration of migrationPlan.toLocal) {\n this.log(` - ${migration.id}`);\n }\n }\n if (migrationPlan.toPlugin.length > 0) {\n this.log(`Switching ${migrationPlan.toPlugin.length} skill(s) to plugin:`);\n for (const migration of migrationPlan.toPlugin) {\n this.log(` - ${migration.id}`);\n }\n }\n\n const migrationResult = await executeMigration(migrationPlan, cwd, context.sourceResult);\n\n for (const warning of migrationResult.warnings) {\n this.warn(warning);\n }\n }\n\n return new Set([\n ...migrationPlan.toLocal.map((m) => m.id),\n ...migrationPlan.toPlugin.map((m) => m.id),\n ]);\n }\n\n private async applyScopeChanges(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { scopeChanges } = changes;\n\n // Handle scope migrations (P->G or G->P) for local-mode skills\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = result.skills.find((s) => s.id === skillId);\n if (skillConfig?.source === \"local\") {\n await migrateLocalSkillScope(skillId, change.from, cwd);\n }\n }\n\n // Handle scope migrations for plugin-mode skills\n if (context.sourceResult.marketplace && scopeChanges.size > 0) {\n const pluginScopeResult = await migratePluginSkillScopes(\n scopeChanges,\n result.skills,\n context.sourceResult.marketplace,\n cwd,\n );\n for (const item of pluginScopeResult.failed) {\n this.warn(`Failed to migrate plugin scope for ${item.id}: ${item.error}`);\n }\n }\n }\n\n private async applySourceChanges(\n changes: ConfigChanges,\n _result: WizardResultV2,\n context: EditContext,\n cwd: string,\n migratedSkillIds: Set<SkillId>,\n ): Promise<void> {\n const { sourceChanges } = changes;\n\n // Handle remaining non-migration source changes (e.g., marketplace A -> marketplace B)\n for (const [skillId, change] of sourceChanges) {\n // Skip skills already handled by mode migration\n if (migratedSkillIds.has(skillId)) {\n continue;\n }\n if (change.from === \"local\") {\n const oldSkill = context.projectConfig?.skills?.find((s) => s.id === skillId);\n const deleteDir = oldSkill?.scope === \"global\" ? os.homedir() : cwd;\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n }\n\n private async applyPluginChanges(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { addedSkills, removedSkills } = changes;\n\n if (context.sourceResult.marketplace) {\n const mpResult = await ensureMarketplace(context.sourceResult);\n if (mpResult.registered) {\n this.log(`Registered marketplace: ${mpResult.marketplace}`);\n }\n\n const addedPluginSkills = result.skills.filter(\n (s) => addedSkills.includes(s.id) && s.source !== \"local\",\n );\n if (addedPluginSkills.length > 0) {\n const pluginResult = await installPluginSkills(\n addedPluginSkills,\n context.sourceResult.marketplace,\n cwd,\n );\n for (const item of pluginResult.installed) {\n this.log(`Installing plugin: ${item.ref}...`);\n }\n for (const item of pluginResult.failed) {\n this.warn(`Failed to install plugin ${item.id}: ${item.error}`);\n }\n }\n\n if (removedSkills.length > 0) {\n const uninstallResult = await uninstallPluginSkills(\n removedSkills,\n context.projectConfig?.skills ?? [],\n cwd,\n );\n for (const id of uninstallResult.uninstalled) {\n this.log(`Uninstalling plugin: ${id}...`);\n }\n for (const item of uninstallResult.failed) {\n this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);\n }\n }\n }\n }\n\n private async copyNewLocalSkills(\n changes: ConfigChanges,\n result: WizardResultV2,\n context: EditContext,\n cwd: string,\n ): Promise<void> {\n const { addedSkills } = changes;\n\n // Copy newly added local-source skills to .claude/skills/ (split by scope)\n const addedLocalSkills = result.skills.filter(\n (s) => addedSkills.includes(s.id) && s.source === \"local\",\n );\n\n if (addedLocalSkills.length > 0) {\n const copyResult = await copyLocalSkills(addedLocalSkills, cwd, context.sourceResult);\n this.log(`Copied ${copyResult.totalCopied} local skill(s) to .claude/skills/`);\n }\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n context: EditContext,\n flags: { source?: string; refresh: boolean; \"agent-source\"?: string },\n cwd: string,\n ): Promise<void> {\n // Load agent definitions — needed for both config-types.ts and recompilation\n let agentDefsResult: AgentDefs;\n this.log(\n flags[\"agent-source\"]\n ? STATUS_MESSAGES.FETCHING_AGENT_PARTIALS\n : STATUS_MESSAGES.LOADING_AGENT_PARTIALS,\n );\n try {\n agentDefsResult = await loadAgentDefs(flags[\"agent-source\"], {\n forceRefresh: flags.refresh,\n });\n this.log(flags[\"agent-source\"] ? \"✓ Agent partials fetched\\n\" : \"✓ Agent partials loaded\\n\");\n } catch (error) {\n this.handleError(error);\n }\n\n // Persist wizard result to config.ts and config-types.ts (split by scope when in project context)\n try {\n await writeProjectConfig({\n wizardResult: result,\n sourceResult: context.sourceResult,\n projectDir: cwd,\n sourceFlag: flags.source,\n agents: agentDefsResult.agents,\n });\n } catch (error) {\n this.warn(`Could not update config: ${getErrorMessage(error)}`);\n }\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const agentScopeMap = new Map(result.agentConfigs.map((a) => [a.name, a.scope] as const));\n const { allSkills } = await discoverInstalledSkills(cwd);\n const compilationResult = await compileAgents({\n projectDir: cwd,\n sourcePath: agentDefsResult.sourcePath,\n skills: allSkills,\n pluginDir: cwd,\n outputDir: path.join(cwd, CLAUDE_DIR, \"agents\"),\n installMode: deriveInstallMode(result.skills),\n agentScopeMap,\n });\n\n if (compilationResult.failed.length > 0) {\n this.log(\n `✓ Recompiled ${compilationResult.compiled.length} agents (${compilationResult.failed.length} failed)\\n`,\n );\n for (const warning of compilationResult.warnings) {\n this.warn(warning);\n }\n } else if (compilationResult.compiled.length > 0) {\n this.log(`✓ Recompiled ${compilationResult.compiled.length} agents\\n`);\n } else {\n this.log(\"✓ No agents to recompile\\n\");\n }\n } catch (error) {\n this.warn(`Agent recompilation failed: ${getErrorMessage(error)}`);\n this.log(`You can manually recompile with '${CLI_BIN_NAME} compile'.\\n`);\n }\n }\n\n private async cleanupStaleAgentFiles(changes: ConfigChanges, cwd: string): Promise<void> {\n const { agentScopeChanges } = changes;\n\n // Clean up old agent .md files after scope changes.\n // Recompilation wrote the new file to the correct scope directory;\n // now delete the stale copy from the old scope directory.\n for (const [agentName, change] of agentScopeChanges) {\n const oldBaseDir = change.from === \"global\" ? os.homedir() : cwd;\n const oldAgentPath = path.join(oldBaseDir, CLAUDE_DIR, \"agents\", `${agentName}.md`);\n try {\n await remove(oldAgentPath);\n } catch (error) {\n this.warn(`Could not remove old agent file ${oldAgentPath}: ${getErrorMessage(error)}`);\n }\n }\n }\n\n private logCompletionSummary(changes: ConfigChanges): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n } = changes;\n\n const hasAgentChanges = addedAgents.length > 0 || removedAgents.length > 0;\n const hasSourceChanges = sourceChanges.size > 0;\n const hasScopeChanges = scopeChanges.size > 0;\n const hasAgentScopeChanges = agentScopeChanges.size > 0;\n\n const summaryParts = [`${addedSkills.length} added`, `${removedSkills.length} removed`];\n if (hasAgentChanges) {\n summaryParts.push(\n `${addedAgents.length} agent${addedAgents.length !== 1 ? \"s\" : \"\"} added, ${removedAgents.length} agent${removedAgents.length !== 1 ? \"s\" : \"\"} removed`,\n );\n }\n if (hasSourceChanges) {\n summaryParts.push(`${sourceChanges.size} source${sourceChanges.size > 1 ? \"s\" : \"\"} changed`);\n }\n if (hasScopeChanges || hasAgentScopeChanges) {\n const totalScopeChanges = scopeChanges.size + agentScopeChanges.size;\n summaryParts.push(`${totalScopeChanges} scope${totalScopeChanges > 1 ? \"s\" : \"\"} changed`);\n }\n this.log(`\\n\\u2713 Plugin updated! (${summaryParts.join(\", \")})\\n`);\n }\n}\n\ntype ConfigChanges = {\n addedSkills: SkillId[];\n removedSkills: SkillId[];\n addedAgents: AgentName[];\n removedAgents: AgentName[];\n sourceChanges: Map<SkillId, { from: string; to: string }>;\n scopeChanges: Map<SkillId, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>;\n agentScopeChanges: Map<AgentName, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>;\n};\n\nfunction detectConfigChanges(\n oldConfig: ProjectConfig | null,\n wizardResult: WizardResultV2,\n currentSkillIds: SkillId[],\n): ConfigChanges {\n const newSkillIds = wizardResult.skills.map((s) => s.id);\n const oldAgentNames = oldConfig?.agents?.map((a) => a.name) ?? [];\n const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);\n\n const oldSkillsById = indexBy(oldConfig?.skills ?? [], (s) => s.id);\n const oldAgentsByName = indexBy(oldConfig?.agents ?? [], (a) => a.name);\n\n return {\n addedSkills: difference(newSkillIds, currentSkillIds),\n removedSkills: difference(currentSkillIds, newSkillIds),\n addedAgents: difference(newAgentNames, oldAgentNames),\n removedAgents: difference(oldAgentNames, newAgentNames),\n sourceChanges: detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.source,\n ),\n scopeChanges: detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.scope,\n ),\n agentScopeChanges: detectPropertyChanges(\n wizardResult.agentConfigs,\n oldAgentsByName,\n (a) => a.name,\n (a) => a.scope,\n ),\n };\n}\n\nfunction detectPropertyChanges<T, K extends string, V>(\n newItems: T[],\n oldByKey: Record<string, T>,\n getKey: (item: T) => K,\n getValue: (item: T) => V,\n): Map<K, { from: V; to: V }> {\n const changes = new Map<K, { from: V; to: V }>();\n for (const item of newItems) {\n const key = getKey(item);\n const old = oldByKey[key];\n if (old && getValue(old) !== getValue(item)) {\n changes.set(key, { from: getValue(old), to: getValue(item) });\n }\n }\n return changes;\n}\n\nfunction hasAnyChanges(changes: ConfigChanges): boolean {\n return (\n changes.addedSkills.length > 0 ||\n changes.removedSkills.length > 0 ||\n changes.addedAgents.length > 0 ||\n changes.removedAgents.length > 0 ||\n changes.sourceChanges.size > 0 ||\n changes.scopeChanges.size > 0 ||\n changes.agentScopeChanges.size > 0\n );\n}\n\ntype PluginScopeMigrationResult = {\n migrated: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\nasync function migratePluginSkillScopes(\n scopeChanges: Map<SkillId, { from: \"project\" | \"global\"; to: \"project\" | \"global\" }>,\n skills: Array<{ id: SkillId; source: string }>,\n marketplace: string,\n projectDir: string,\n): Promise<PluginScopeMigrationResult> {\n const migrated: SkillId[] = [];\n const failed: PluginScopeMigrationResult[\"failed\"] = [];\n\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = skills.find((s) => s.id === skillId);\n if (!skillConfig || skillConfig.source === \"local\") {\n continue;\n }\n\n const oldPluginScope = change.from === \"global\" ? \"user\" : \"project\";\n const newPluginScope = change.to === \"global\" ? \"user\" : \"project\";\n const pluginRef = `${skillId}@${marketplace}`;\n\n try {\n await claudePluginUninstall(skillId, oldPluginScope, projectDir);\n await claudePluginInstall(pluginRef, newPluginScope, projectDir);\n migrated.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { migrated, failed };\n}\n"],"mappings":"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","names":["result"]}
|
|
@@ -310,64 +310,71 @@ Create one with:
|
|
|
310
310
|
await injectImportedForkedFromMetadata(destPath, skillName, displaySource, contentHash);
|
|
311
311
|
}
|
|
312
312
|
async function injectImportedForkedFromMetadata(destPath, skillName, source, contentHash) {
|
|
313
|
-
const metadataYamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);
|
|
314
|
-
const metadataJsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);
|
|
315
313
|
const forkedFrom = {
|
|
316
314
|
source,
|
|
317
315
|
skillName,
|
|
318
316
|
contentHash,
|
|
319
317
|
date: getCurrentDate()
|
|
320
318
|
};
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
319
|
+
const yamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);
|
|
320
|
+
const jsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);
|
|
321
|
+
if (await fileExists(yamlPath)) {
|
|
322
|
+
return mergeForkedFromIntoYaml(yamlPath, forkedFrom);
|
|
323
|
+
}
|
|
324
|
+
if (await fileExists(jsonPath)) {
|
|
325
|
+
return convertJsonToYamlWithForkedFrom(jsonPath, yamlPath, forkedFrom);
|
|
326
|
+
}
|
|
327
|
+
return createMinimalMetadata(yamlPath, skillName, forkedFrom);
|
|
328
|
+
}
|
|
329
|
+
async function mergeForkedFromIntoYaml(yamlPath, forkedFrom) {
|
|
330
|
+
const rawContent = await readFile(yamlPath);
|
|
331
|
+
const lines = rawContent.split("\n");
|
|
332
|
+
let yamlContent = rawContent;
|
|
333
|
+
let schemaComment = "";
|
|
334
|
+
if (lines[0]?.startsWith("# yaml-language-server:")) {
|
|
335
|
+
schemaComment = `${lines[0]}
|
|
328
336
|
`;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
337
|
+
yamlContent = lines.slice(1).join("\n");
|
|
338
|
+
}
|
|
339
|
+
const raw = parseYaml(yamlContent);
|
|
340
|
+
const parseResult = importedSkillMetadataSchema.safeParse(raw);
|
|
341
|
+
if (!parseResult.success) {
|
|
342
|
+
warn(
|
|
343
|
+
`Malformed metadata.yaml at ${yamlPath} \u2014 existing fields may be lost
|
|
336
344
|
Validation errors: ${parseResult.error.issues.map((i) => i.message).join(", ")}
|
|
337
345
|
Expected fields: displayName (string), cliDescription (string), category (string)
|
|
338
346
|
Validate your YAML syntax at https://yamllint.com`
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
const metadata = parseResult.success ? parseResult.data : { forkedFrom: void 0 };
|
|
342
|
-
metadata.forkedFrom = forkedFrom;
|
|
343
|
-
const newYamlContent = stringifyYaml(metadata, {
|
|
344
|
-
lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE
|
|
345
|
-
});
|
|
346
|
-
await writeFile(metadataYamlPath, schemaComment + newYamlContent);
|
|
347
|
-
return;
|
|
347
|
+
);
|
|
348
348
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
349
|
+
const metadata = parseResult.success ? parseResult.data : { forkedFrom: void 0 };
|
|
350
|
+
metadata.forkedFrom = forkedFrom;
|
|
351
|
+
const newYamlContent = stringifyYaml(metadata, {
|
|
352
|
+
lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE
|
|
353
|
+
});
|
|
354
|
+
await writeFile(yamlPath, schemaComment + newYamlContent);
|
|
355
|
+
}
|
|
356
|
+
async function convertJsonToYamlWithForkedFrom(jsonPath, yamlPath, forkedFrom) {
|
|
357
|
+
const rawContent = await readFile(jsonPath);
|
|
358
|
+
let jsonParsed;
|
|
359
|
+
try {
|
|
360
|
+
jsonParsed = JSON.parse(rawContent);
|
|
361
|
+
} catch {
|
|
362
|
+
warn(
|
|
363
|
+
`Malformed JSON in ${jsonPath} \u2014 skipping metadata injection
|
|
357
364
|
Common issues: trailing commas, unquoted keys, single quotes instead of double quotes
|
|
358
365
|
Validate your JSON at https://jsonlint.com`
|
|
359
|
-
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);
|
|
363
|
-
const metadata = jsonResult.success ? jsonResult.data : { forkedFrom: void 0 };
|
|
364
|
-
metadata.forkedFrom = forkedFrom;
|
|
365
|
-
const yamlContent2 = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });
|
|
366
|
-
await writeFile(metadataYamlPath, yamlContent2);
|
|
366
|
+
);
|
|
367
367
|
return;
|
|
368
368
|
}
|
|
369
|
+
const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);
|
|
370
|
+
const metadata = jsonResult.success ? jsonResult.data : { forkedFrom: void 0 };
|
|
371
|
+
metadata.forkedFrom = forkedFrom;
|
|
372
|
+
const yamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });
|
|
373
|
+
await writeFile(yamlPath, yamlContent);
|
|
374
|
+
}
|
|
375
|
+
async function createMinimalMetadata(yamlPath, skillName, forkedFrom) {
|
|
369
376
|
const minimalMetadata = {
|
|
370
|
-
displayName: skillName
|
|
377
|
+
displayName: toTitleCase(skillName),
|
|
371
378
|
cliDescription: "Imported from third-party repository",
|
|
372
379
|
category: IMPORT_DEFAULTS.CATEGORY,
|
|
373
380
|
author: IMPORT_DEFAULTS.AUTHOR,
|
|
@@ -376,7 +383,10 @@ async function injectImportedForkedFromMetadata(destPath, skillName, source, con
|
|
|
376
383
|
const yamlContent = stringifyYaml(minimalMetadata, {
|
|
377
384
|
lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE
|
|
378
385
|
});
|
|
379
|
-
await writeFile(
|
|
386
|
+
await writeFile(yamlPath, yamlContent);
|
|
387
|
+
}
|
|
388
|
+
function toTitleCase(kebab) {
|
|
389
|
+
return kebab.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
380
390
|
}
|
|
381
391
|
export {
|
|
382
392
|
ImportSkill as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/commands/import/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { fetchFromSource } from \"../../lib/loading/index.js\";\nimport { importedSkillMetadataSchema } from \"../../lib/schemas.js\";\nimport { getCurrentDate, computeFileHash } from \"../../lib/versioning.js\";\nimport {\n copy,\n directoryExists,\n fileExists,\n listDirectories,\n readFile,\n writeFile,\n ensureDir,\n} from \"../../utils/fs.js\";\nimport { warn } from \"../../utils/logger.js\";\nimport {\n DEFAULT_SKILLS_SUBDIR,\n GITHUB_SOURCE,\n LOCAL_SKILLS_PATH,\n STANDARD_FILES,\n YAML_FORMATTING,\n} from \"../../consts.js\";\nimport { IMPORT_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { STATUS_MESSAGES, INFO_MESSAGES } from \"../../utils/messages.js\";\n\nexport default class ImportSkill extends BaseCommand {\n static summary = \"Import a skill from a third-party GitHub repository\";\n static description =\n \"Download and import skills from external GitHub repositories into your local \" +\n \".claude/skills/ directory. Supports importing specific skills or listing available skills.\";\n\n static examples = [\n {\n description: \"List available skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --list\",\n },\n {\n description: \"Import a specific skill\",\n command:\n \"<%= config.bin %> import skill github:vercel-labs/agent-skills --skill react-best-practices\",\n },\n {\n description: \"Import all skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --all\",\n },\n {\n description: \"Import with custom skills directory\",\n command:\n \"<%= config.bin %> import skill github:owner/repo --skill my-skill --subdir custom-skills\",\n },\n ];\n\n static args = {\n source: Args.string({\n description:\n \"GitHub repository source (github:owner/repo, https://github.com/owner/repo, or owner/repo)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n skill: Flags.string({\n char: \"n\",\n description: \"Name of the specific skill to import\",\n required: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Import all skills from the repository\",\n default: false,\n }),\n list: Flags.boolean({\n char: \"l\",\n description: \"List available skills without importing\",\n default: false,\n }),\n subdir: Flags.string({\n description: \"Subdirectory containing skills (default: skills)\",\n default: DEFAULT_SKILLS_SUBDIR,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skills\",\n default: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote (ignore cache)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(ImportSkill);\n const projectDir = process.cwd();\n\n this.printHeader();\n this.validateFlags(flags);\n\n const { gigetSource, displaySource } = parseGitHubSource(args.source);\n this.log(`Source: ${displaySource}`);\n\n const repoPath = await this.fetchRepository(gigetSource, args.source, flags.refresh);\n const skillsDir = this.resolveSkillsDir(repoPath, flags.subdir);\n const availableSkills = await this.discoverAndValidate(skillsDir, flags.subdir);\n\n if (flags.list) {\n this.listAvailableSkills(availableSkills);\n return;\n }\n\n const skillsToImport = this.resolveSkillsToImport(flags, availableSkills);\n await this.importSkills(skillsToImport, skillsDir, projectDir, displaySource, flags.force);\n }\n\n private printHeader(): void {\n this.log(\"\");\n this.log(\"Import Third-Party Skill\");\n this.log(\"\");\n }\n\n private validateFlags(flags: { list: boolean; skill?: string; all: boolean }): void {\n if (!flags.list && !flags.skill && !flags.all) {\n this.error(\"Please specify --skill <name>, --all, or --list to list available skills\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (flags.skill && flags.all) {\n this.error(\"Cannot use --skill and --all together\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n }\n\n private async fetchRepository(\n gigetSource: string,\n sourceArg: string,\n refresh: boolean,\n ): Promise<string> {\n this.log(STATUS_MESSAGES.FETCHING_REPOSITORY);\n\n try {\n const result = await fetchSkillSource({\n gigetSource,\n forceRefresh: refresh,\n });\n this.log(result.fromCache ? \"Using cached source\" : \"Downloaded fresh copy\");\n return result.path;\n } catch (error) {\n this.error(error instanceof Error ? error.message : `Failed to fetch: ${sourceArg}`, {\n exit: EXIT_CODES.NETWORK_ERROR,\n });\n }\n }\n\n private resolveSkillsDir(repoPath: string, subdir: string): string {\n if (/\\0/.test(subdir)) {\n this.error(\"--subdir contains null bytes\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n if (path.isAbsolute(subdir)) {\n this.error(`--subdir must be a relative path, got: ${subdir}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n const skillsDir = path.resolve(path.join(repoPath, subdir));\n const resolvedRepoPath = path.resolve(repoPath);\n if (!skillsDir.startsWith(resolvedRepoPath + path.sep) && skillsDir !== resolvedRepoPath) {\n this.error(`--subdir path escapes repository boundary: ${subdir}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return skillsDir;\n }\n\n private async discoverAndValidate(skillsDir: string, subdir: string): Promise<string[]> {\n if (!(await directoryExists(skillsDir))) {\n this.error(\n `Skills directory not found: ${subdir}\\n` +\n `The repository doesn't have a '${subdir}' directory.\\n` +\n `Use --subdir to specify a different location.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n const availableSkills = await discoverValidSkills(skillsDir);\n\n if (availableSkills.length === 0) {\n this.error(`No valid skills found in ${subdir}/\\nSkills must have a SKILL.md file.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return availableSkills;\n }\n\n private listAvailableSkills(skills: string[]): void {\n this.log(\"\");\n this.log(`Available skills (${skills.length}):`);\n this.log(\"\");\n for (const skill of skills) {\n this.log(` - ${skill}`);\n }\n this.log(\"\");\n this.log(\"Use --skill <name> to import a specific skill, or --all to import all.\");\n }\n\n private resolveSkillsToImport(\n flags: { all: boolean; skill?: string },\n availableSkills: string[],\n ): string[] {\n if (flags.all) {\n return availableSkills;\n }\n\n if (flags.skill) {\n if (!availableSkills.includes(flags.skill)) {\n this.error(\n `Skill '${flags.skill}' not found in repository.\\n` +\n `Available skills: ${availableSkills.join(\", \")}\\n` +\n `Use --list to see all available skills.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n return [flags.skill];\n }\n\n return [];\n }\n\n private async importSkills(\n skillsToImport: string[],\n skillsDir: string,\n projectDir: string,\n displaySource: string,\n force: boolean,\n ): Promise<void> {\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n this.log(\"\");\n this.log(`Importing ${skillsToImport.length} skill(s)...`);\n\n let imported = 0;\n let skipped = 0;\n\n for (const skillName of skillsToImport) {\n const sourcePath = path.join(skillsDir, skillName);\n const destPath = path.join(destDir, skillName);\n\n if (await directoryExists(destPath)) {\n if (!force) {\n this.warn(`Skipping '${skillName}': already exists. Use --force to overwrite.`);\n skipped++;\n continue;\n }\n }\n\n try {\n await importSkillFromSource({ sourcePath, destPath, skillName, displaySource });\n this.logSuccess(`Imported: ${skillName}`);\n imported++;\n } catch (error) {\n this.warn(`Failed to import '${skillName}': ${getErrorMessage(error)}`);\n skipped++;\n }\n }\n\n this.log(\"\");\n this.logSuccess(`Import complete: ${imported} imported, ${skipped} skipped`);\n this.log(`Skills location: ${destDir}`);\n this.log(\"\");\n this.log(INFO_MESSAGES.RUN_COMPILE);\n this.log(\"\");\n }\n}\n\ntype ImportedForkedFromMetadata = {\n source: string;\n skillName: string;\n contentHash: string;\n date: string;\n};\n\ntype SkillMetadata = {\n forkedFrom?: ImportedForkedFromMetadata;\n [key: string]: unknown;\n};\n\ntype ParsedGitHubSource = {\n gigetSource: string;\n displaySource: string;\n};\n\ntype FetchSourceOptions = {\n gigetSource: string;\n forceRefresh?: boolean;\n};\n\ntype FetchedSource = {\n path: string;\n fromCache: boolean;\n};\n\ntype ImportSkillOptions = {\n sourcePath: string;\n destPath: string;\n skillName: string;\n displaySource: string;\n};\n\n/**\n * Parses various GitHub URL formats into a normalized giget source string\n * and a human-readable display URL.\n *\n * Supports: `https://github.com/owner/repo`, `github:owner/repo`,\n * `gh:owner/repo`, and bare `owner/repo` formats.\n */\nfunction parseGitHubSource(source: string): ParsedGitHubSource {\n if (source.startsWith(GITHUB_SOURCE.HTTPS_PREFIX)) {\n const path = source.replace(GITHUB_SOURCE.HTTPS_PREFIX, \"\");\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${path}`,\n displaySource: source,\n };\n }\n\n if (\n source.startsWith(GITHUB_SOURCE.GITHUB_PREFIX) ||\n source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ) {\n const normalized = source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ? GITHUB_SOURCE.GITHUB_PREFIX + source.slice(GITHUB_SOURCE.GH_PREFIX.length)\n : source;\n return {\n gigetSource: normalized,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${normalized.replace(GITHUB_SOURCE.GITHUB_PREFIX, \"\")}`,\n };\n }\n\n if (source.includes(\"/\") && !source.includes(\":\")) {\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${source}`,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${source}`,\n };\n }\n\n return {\n gigetSource: source,\n displaySource: source,\n };\n}\n\n/**\n * Fetches a source repository using giget. Wraps `fetchFromSource` from the\n * loading layer.\n */\nasync function fetchSkillSource(options: FetchSourceOptions): Promise<FetchedSource> {\n const result = await fetchFromSource(options.gigetSource, {\n forceRefresh: options.forceRefresh,\n });\n return { path: result.path, fromCache: result.fromCache };\n}\n\n/**\n * Discovers valid skill directories within a source path by checking\n * for the presence of SKILL.md files.\n *\n * @returns Sorted list of directory names that contain a SKILL.md file.\n */\nasync function discoverValidSkills(skillsDir: string): Promise<string[]> {\n const skillDirs = await listDirectories(skillsDir);\n const validSkills: string[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n if (await fileExists(skillMdPath)) {\n validSkills.push(skillDir);\n }\n }\n\n return validSkills.sort();\n}\n\n/**\n * Imports a single skill from a source directory into the destination.\n *\n * Validates that the source skill has a SKILL.md file, copies the directory,\n * and injects `forkedFrom` metadata into the destination's metadata.yaml.\n *\n * @throws {Error} If the source skill is missing a SKILL.md file.\n */\nasync function importSkillFromSource(options: ImportSkillOptions): Promise<void> {\n const { sourcePath, destPath, skillName, displaySource } = options;\n const skillMdPath = path.join(sourcePath, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Missing required SKILL.md file at ${skillMdPath}\\n` +\n `Every skill must have a SKILL.md file containing the skill's prompt content.\\n` +\n `Create one with:\\n` +\n ` echo \"# ${skillName}\" > ${path.join(sourcePath, STANDARD_FILES.SKILL_MD)}`,\n );\n }\n\n const contentHash = await computeFileHash(skillMdPath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectImportedForkedFromMetadata(destPath, skillName, displaySource, contentHash);\n}\n\n/**\n * Injects `forkedFrom` metadata into a third-party imported skill's metadata.yaml.\n *\n * Handles three cases:\n * 1. Existing metadata.yaml -- preserves fields, adds/overwrites forkedFrom\n * 2. Existing metadata.json -- converts to YAML, adds forkedFrom\n * 3. No metadata file -- creates minimal metadata.yaml with forkedFrom\n *\n * Different from `injectForkedFromMetadata` in `skill-metadata.ts` which tracks\n * internal marketplace fork lineage using `skillId`. This function tracks\n * third-party imports using `source` + `skillName`.\n */\nasync function injectImportedForkedFromMetadata(\n destPath: string,\n skillName: string,\n source: string,\n contentHash: string,\n): Promise<void> {\n const metadataYamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);\n const metadataJsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);\n\n const forkedFrom: ImportedForkedFromMetadata = {\n source,\n skillName,\n contentHash,\n date: getCurrentDate(),\n };\n\n if (await fileExists(metadataYamlPath)) {\n const rawContent = await readFile(metadataYamlPath);\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n let schemaComment = \"\";\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = `${lines[0]}\\n`;\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const raw = parseYaml(yamlContent);\n const parseResult = importedSkillMetadataSchema.safeParse(raw);\n if (!parseResult.success) {\n warn(\n `Malformed metadata.yaml at ${metadataYamlPath} — existing fields may be lost\\n` +\n ` Validation errors: ${parseResult.error.issues.map((i) => i.message).join(\", \")}\\n` +\n ` Expected fields: displayName (string), cliDescription (string), category (string)\\n` +\n ` Validate your YAML syntax at https://yamllint.com`,\n );\n }\n const metadata = parseResult.success\n ? (parseResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const newYamlContent = stringifyYaml(metadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(metadataYamlPath, schemaComment + newYamlContent);\n return;\n }\n\n if (await fileExists(metadataJsonPath)) {\n const rawContent = await readFile(metadataJsonPath);\n let jsonParsed: unknown;\n try {\n jsonParsed = JSON.parse(rawContent);\n } catch {\n warn(\n `Malformed JSON in ${metadataJsonPath} — skipping metadata injection\\n` +\n ` Common issues: trailing commas, unquoted keys, single quotes instead of double quotes\\n` +\n ` Validate your JSON at https://jsonlint.com`,\n );\n return;\n }\n const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);\n const metadata = jsonResult.success\n ? (jsonResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const yamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(metadataYamlPath, yamlContent);\n return;\n }\n\n const minimalMetadata: SkillMetadata = {\n displayName: skillName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \"),\n cliDescription: \"Imported from third-party repository\",\n category: IMPORT_DEFAULTS.CATEGORY,\n author: IMPORT_DEFAULTS.AUTHOR,\n forkedFrom,\n };\n\n const yamlContent = stringifyYaml(minimalMetadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(metadataYamlPath, yamlContent);\n}\n"],"mappings":"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","names":["path","yamlContent"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/import/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { fetchFromSource } from \"../../lib/loading/index.js\";\nimport { importedSkillMetadataSchema } from \"../../lib/schemas.js\";\nimport { getCurrentDate, computeFileHash } from \"../../lib/versioning.js\";\nimport {\n copy,\n directoryExists,\n fileExists,\n listDirectories,\n readFile,\n writeFile,\n ensureDir,\n} from \"../../utils/fs.js\";\nimport { warn } from \"../../utils/logger.js\";\nimport {\n DEFAULT_SKILLS_SUBDIR,\n GITHUB_SOURCE,\n LOCAL_SKILLS_PATH,\n STANDARD_FILES,\n YAML_FORMATTING,\n} from \"../../consts.js\";\nimport { IMPORT_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { STATUS_MESSAGES, INFO_MESSAGES } from \"../../utils/messages.js\";\n\nexport default class ImportSkill extends BaseCommand {\n static summary = \"Import a skill from a third-party GitHub repository\";\n static description =\n \"Download and import skills from external GitHub repositories into your local \" +\n \".claude/skills/ directory. Supports importing specific skills or listing available skills.\";\n\n static examples = [\n {\n description: \"List available skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --list\",\n },\n {\n description: \"Import a specific skill\",\n command:\n \"<%= config.bin %> import skill github:vercel-labs/agent-skills --skill react-best-practices\",\n },\n {\n description: \"Import all skills from a repository\",\n command: \"<%= config.bin %> import skill github:vercel-labs/agent-skills --all\",\n },\n {\n description: \"Import with custom skills directory\",\n command:\n \"<%= config.bin %> import skill github:owner/repo --skill my-skill --subdir custom-skills\",\n },\n ];\n\n static args = {\n source: Args.string({\n description:\n \"GitHub repository source (github:owner/repo, https://github.com/owner/repo, or owner/repo)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n skill: Flags.string({\n char: \"n\",\n description: \"Name of the specific skill to import\",\n required: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Import all skills from the repository\",\n default: false,\n }),\n list: Flags.boolean({\n char: \"l\",\n description: \"List available skills without importing\",\n default: false,\n }),\n subdir: Flags.string({\n description: \"Subdirectory containing skills (default: skills)\",\n default: DEFAULT_SKILLS_SUBDIR,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skills\",\n default: false,\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote (ignore cache)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(ImportSkill);\n const projectDir = process.cwd();\n\n this.printHeader();\n this.validateFlags(flags);\n\n const { gigetSource, displaySource } = parseGitHubSource(args.source);\n this.log(`Source: ${displaySource}`);\n\n const repoPath = await this.fetchRepository(gigetSource, args.source, flags.refresh);\n const skillsDir = this.resolveSkillsDir(repoPath, flags.subdir);\n const availableSkills = await this.discoverAndValidate(skillsDir, flags.subdir);\n\n if (flags.list) {\n this.listAvailableSkills(availableSkills);\n return;\n }\n\n const skillsToImport = this.resolveSkillsToImport(flags, availableSkills);\n await this.importSkills(skillsToImport, skillsDir, projectDir, displaySource, flags.force);\n }\n\n private printHeader(): void {\n this.log(\"\");\n this.log(\"Import Third-Party Skill\");\n this.log(\"\");\n }\n\n private validateFlags(flags: { list: boolean; skill?: string; all: boolean }): void {\n if (!flags.list && !flags.skill && !flags.all) {\n this.error(\"Please specify --skill <name>, --all, or --list to list available skills\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (flags.skill && flags.all) {\n this.error(\"Cannot use --skill and --all together\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n }\n\n private async fetchRepository(\n gigetSource: string,\n sourceArg: string,\n refresh: boolean,\n ): Promise<string> {\n this.log(STATUS_MESSAGES.FETCHING_REPOSITORY);\n\n try {\n const result = await fetchSkillSource({\n gigetSource,\n forceRefresh: refresh,\n });\n this.log(result.fromCache ? \"Using cached source\" : \"Downloaded fresh copy\");\n return result.path;\n } catch (error) {\n this.error(error instanceof Error ? error.message : `Failed to fetch: ${sourceArg}`, {\n exit: EXIT_CODES.NETWORK_ERROR,\n });\n }\n }\n\n private resolveSkillsDir(repoPath: string, subdir: string): string {\n if (/\\0/.test(subdir)) {\n this.error(\"--subdir contains null bytes\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n if (path.isAbsolute(subdir)) {\n this.error(`--subdir must be a relative path, got: ${subdir}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n const skillsDir = path.resolve(path.join(repoPath, subdir));\n const resolvedRepoPath = path.resolve(repoPath);\n if (!skillsDir.startsWith(resolvedRepoPath + path.sep) && skillsDir !== resolvedRepoPath) {\n this.error(`--subdir path escapes repository boundary: ${subdir}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return skillsDir;\n }\n\n private async discoverAndValidate(skillsDir: string, subdir: string): Promise<string[]> {\n if (!(await directoryExists(skillsDir))) {\n this.error(\n `Skills directory not found: ${subdir}\\n` +\n `The repository doesn't have a '${subdir}' directory.\\n` +\n `Use --subdir to specify a different location.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n const availableSkills = await discoverValidSkills(skillsDir);\n\n if (availableSkills.length === 0) {\n this.error(`No valid skills found in ${subdir}/\\nSkills must have a SKILL.md file.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return availableSkills;\n }\n\n private listAvailableSkills(skills: string[]): void {\n this.log(\"\");\n this.log(`Available skills (${skills.length}):`);\n this.log(\"\");\n for (const skill of skills) {\n this.log(` - ${skill}`);\n }\n this.log(\"\");\n this.log(\"Use --skill <name> to import a specific skill, or --all to import all.\");\n }\n\n private resolveSkillsToImport(\n flags: { all: boolean; skill?: string },\n availableSkills: string[],\n ): string[] {\n if (flags.all) {\n return availableSkills;\n }\n\n if (flags.skill) {\n if (!availableSkills.includes(flags.skill)) {\n this.error(\n `Skill '${flags.skill}' not found in repository.\\n` +\n `Available skills: ${availableSkills.join(\", \")}\\n` +\n `Use --list to see all available skills.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n return [flags.skill];\n }\n\n return [];\n }\n\n private async importSkills(\n skillsToImport: string[],\n skillsDir: string,\n projectDir: string,\n displaySource: string,\n force: boolean,\n ): Promise<void> {\n const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n this.log(\"\");\n this.log(`Importing ${skillsToImport.length} skill(s)...`);\n\n let imported = 0;\n let skipped = 0;\n\n for (const skillName of skillsToImport) {\n const sourcePath = path.join(skillsDir, skillName);\n const destPath = path.join(destDir, skillName);\n\n if (await directoryExists(destPath)) {\n if (!force) {\n this.warn(`Skipping '${skillName}': already exists. Use --force to overwrite.`);\n skipped++;\n continue;\n }\n }\n\n try {\n await importSkillFromSource({ sourcePath, destPath, skillName, displaySource });\n this.logSuccess(`Imported: ${skillName}`);\n imported++;\n } catch (error) {\n this.warn(`Failed to import '${skillName}': ${getErrorMessage(error)}`);\n skipped++;\n }\n }\n\n this.log(\"\");\n this.logSuccess(`Import complete: ${imported} imported, ${skipped} skipped`);\n this.log(`Skills location: ${destDir}`);\n this.log(\"\");\n this.log(INFO_MESSAGES.RUN_COMPILE);\n this.log(\"\");\n }\n}\n\ntype ImportedForkedFromMetadata = {\n source: string;\n skillName: string;\n contentHash: string;\n date: string;\n};\n\ntype SkillMetadata = {\n forkedFrom?: ImportedForkedFromMetadata;\n [key: string]: unknown;\n};\n\ntype ParsedGitHubSource = {\n gigetSource: string;\n displaySource: string;\n};\n\ntype FetchSourceOptions = {\n gigetSource: string;\n forceRefresh?: boolean;\n};\n\ntype FetchedSource = {\n path: string;\n fromCache: boolean;\n};\n\ntype ImportSkillOptions = {\n sourcePath: string;\n destPath: string;\n skillName: string;\n displaySource: string;\n};\n\n/**\n * Parses various GitHub URL formats into a normalized giget source string\n * and a human-readable display URL.\n *\n * Supports: `https://github.com/owner/repo`, `github:owner/repo`,\n * `gh:owner/repo`, and bare `owner/repo` formats.\n */\nfunction parseGitHubSource(source: string): ParsedGitHubSource {\n if (source.startsWith(GITHUB_SOURCE.HTTPS_PREFIX)) {\n const path = source.replace(GITHUB_SOURCE.HTTPS_PREFIX, \"\");\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${path}`,\n displaySource: source,\n };\n }\n\n if (\n source.startsWith(GITHUB_SOURCE.GITHUB_PREFIX) ||\n source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ) {\n const normalized = source.startsWith(GITHUB_SOURCE.GH_PREFIX)\n ? GITHUB_SOURCE.GITHUB_PREFIX + source.slice(GITHUB_SOURCE.GH_PREFIX.length)\n : source;\n return {\n gigetSource: normalized,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${normalized.replace(GITHUB_SOURCE.GITHUB_PREFIX, \"\")}`,\n };\n }\n\n if (source.includes(\"/\") && !source.includes(\":\")) {\n return {\n gigetSource: `${GITHUB_SOURCE.GITHUB_PREFIX}${source}`,\n displaySource: `${GITHUB_SOURCE.HTTPS_PREFIX}${source}`,\n };\n }\n\n return {\n gigetSource: source,\n displaySource: source,\n };\n}\n\n/**\n * Fetches a source repository using giget. Wraps `fetchFromSource` from the\n * loading layer.\n */\nasync function fetchSkillSource(options: FetchSourceOptions): Promise<FetchedSource> {\n const result = await fetchFromSource(options.gigetSource, {\n forceRefresh: options.forceRefresh,\n });\n return { path: result.path, fromCache: result.fromCache };\n}\n\n/**\n * Discovers valid skill directories within a source path by checking\n * for the presence of SKILL.md files.\n *\n * @returns Sorted list of directory names that contain a SKILL.md file.\n */\nasync function discoverValidSkills(skillsDir: string): Promise<string[]> {\n const skillDirs = await listDirectories(skillsDir);\n const validSkills: string[] = [];\n\n for (const skillDir of skillDirs) {\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n if (await fileExists(skillMdPath)) {\n validSkills.push(skillDir);\n }\n }\n\n return validSkills.sort();\n}\n\n/**\n * Imports a single skill from a source directory into the destination.\n *\n * Validates that the source skill has a SKILL.md file, copies the directory,\n * and injects `forkedFrom` metadata into the destination's metadata.yaml.\n *\n * @throws {Error} If the source skill is missing a SKILL.md file.\n */\nasync function importSkillFromSource(options: ImportSkillOptions): Promise<void> {\n const { sourcePath, destPath, skillName, displaySource } = options;\n const skillMdPath = path.join(sourcePath, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Missing required SKILL.md file at ${skillMdPath}\\n` +\n `Every skill must have a SKILL.md file containing the skill's prompt content.\\n` +\n `Create one with:\\n` +\n ` echo \"# ${skillName}\" > ${path.join(sourcePath, STANDARD_FILES.SKILL_MD)}`,\n );\n }\n\n const contentHash = await computeFileHash(skillMdPath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectImportedForkedFromMetadata(destPath, skillName, displaySource, contentHash);\n}\n\n/**\n * Injects `forkedFrom` metadata into a third-party imported skill's metadata.yaml.\n *\n * Handles three cases:\n * 1. Existing metadata.yaml -- preserves fields, adds/overwrites forkedFrom\n * 2. Existing metadata.json -- converts to YAML, adds forkedFrom\n * 3. No metadata file -- creates minimal metadata.yaml with forkedFrom\n *\n * Different from `injectForkedFromMetadata` in `skill-metadata.ts` which tracks\n * internal marketplace fork lineage using `skillId`. This function tracks\n * third-party imports using `source` + `skillName`.\n */\nasync function injectImportedForkedFromMetadata(\n destPath: string,\n skillName: string,\n source: string,\n contentHash: string,\n): Promise<void> {\n const forkedFrom: ImportedForkedFromMetadata = {\n source,\n skillName,\n contentHash,\n date: getCurrentDate(),\n };\n\n const yamlPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);\n const jsonPath = path.join(destPath, STANDARD_FILES.METADATA_JSON);\n\n if (await fileExists(yamlPath)) {\n return mergeForkedFromIntoYaml(yamlPath, forkedFrom);\n }\n if (await fileExists(jsonPath)) {\n return convertJsonToYamlWithForkedFrom(jsonPath, yamlPath, forkedFrom);\n }\n return createMinimalMetadata(yamlPath, skillName, forkedFrom);\n}\n\nasync function mergeForkedFromIntoYaml(\n yamlPath: string,\n forkedFrom: ImportedForkedFromMetadata,\n): Promise<void> {\n const rawContent = await readFile(yamlPath);\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n let schemaComment = \"\";\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n schemaComment = `${lines[0]}\\n`;\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const raw = parseYaml(yamlContent);\n const parseResult = importedSkillMetadataSchema.safeParse(raw);\n if (!parseResult.success) {\n warn(\n `Malformed metadata.yaml at ${yamlPath} — existing fields may be lost\\n` +\n ` Validation errors: ${parseResult.error.issues.map((i) => i.message).join(\", \")}\\n` +\n ` Expected fields: displayName (string), cliDescription (string), category (string)\\n` +\n ` Validate your YAML syntax at https://yamllint.com`,\n );\n }\n const metadata = parseResult.success\n ? (parseResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const newYamlContent = stringifyYaml(metadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(yamlPath, schemaComment + newYamlContent);\n}\n\nasync function convertJsonToYamlWithForkedFrom(\n jsonPath: string,\n yamlPath: string,\n forkedFrom: ImportedForkedFromMetadata,\n): Promise<void> {\n const rawContent = await readFile(jsonPath);\n let jsonParsed: unknown;\n try {\n jsonParsed = JSON.parse(rawContent);\n } catch {\n warn(\n `Malformed JSON in ${jsonPath} — skipping metadata injection\\n` +\n ` Common issues: trailing commas, unquoted keys, single quotes instead of double quotes\\n` +\n ` Validate your JSON at https://jsonlint.com`,\n );\n return;\n }\n const jsonResult = importedSkillMetadataSchema.safeParse(jsonParsed);\n const metadata = jsonResult.success\n ? (jsonResult.data as SkillMetadata)\n : { forkedFrom: undefined };\n metadata.forkedFrom = forkedFrom;\n\n const yamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(yamlPath, yamlContent);\n}\n\nasync function createMinimalMetadata(\n yamlPath: string,\n skillName: string,\n forkedFrom: ImportedForkedFromMetadata,\n): Promise<void> {\n const minimalMetadata: SkillMetadata = {\n displayName: toTitleCase(skillName),\n cliDescription: \"Imported from third-party repository\",\n category: IMPORT_DEFAULTS.CATEGORY,\n author: IMPORT_DEFAULTS.AUTHOR,\n forkedFrom,\n };\n\n const yamlContent = stringifyYaml(minimalMetadata, {\n lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE,\n });\n await writeFile(yamlPath, yamlContent);\n}\n\nfunction toTitleCase(kebab: string): string {\n return kebab\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n"],"mappings":"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","names":["path"]}
|
package/dist/commands/init.js
CHANGED
|
@@ -4,38 +4,37 @@ import {
|
|
|
4
4
|
formatDashboardText,
|
|
5
5
|
getDashboardData,
|
|
6
6
|
showDashboard
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-MBEXASMU.js";
|
|
8
|
+
import "../chunk-5IR4QU7G.js";
|
|
9
|
+
import "../chunk-AWB6DO24.js";
|
|
10
10
|
import "../chunk-YVFGISUO.js";
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-FQTYF3OU.js";
|
|
11
|
+
import "../chunk-3STOCHK4.js";
|
|
12
|
+
import "../chunk-RDQBXB3Y.js";
|
|
13
|
+
import "../chunk-ORTNQZLF.js";
|
|
14
|
+
import "../chunk-G3VPBEBC.js";
|
|
15
|
+
import "../chunk-UK572773.js";
|
|
16
|
+
import "../chunk-TJHCK4OS.js";
|
|
17
|
+
import "../chunk-M6J5YQ3P.js";
|
|
19
18
|
import "../chunk-K77I4XGL.js";
|
|
20
19
|
import "../chunk-OVY7IV3C.js";
|
|
21
20
|
import "../chunk-6XEZLWG5.js";
|
|
22
|
-
import "../chunk-
|
|
21
|
+
import "../chunk-35WALWDD.js";
|
|
23
22
|
import "../chunk-7SOPVGDV.js";
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-BGICSUQK.js";
|
|
24
|
+
import "../chunk-3O57Z6Q3.js";
|
|
26
25
|
import "../chunk-P2FHS5IS.js";
|
|
27
|
-
import "../chunk-
|
|
26
|
+
import "../chunk-2RXDM5HN.js";
|
|
28
27
|
import "../chunk-UHARXISZ.js";
|
|
29
28
|
import "../chunk-HSKKGAOW.js";
|
|
30
29
|
import "../chunk-4QA5TIBU.js";
|
|
31
30
|
import "../chunk-WJXWYSBT.js";
|
|
32
|
-
import "../chunk-
|
|
31
|
+
import "../chunk-7QWCPF6F.js";
|
|
33
32
|
import "../chunk-XO6X5QE5.js";
|
|
34
33
|
import "../chunk-KUV24B5M.js";
|
|
35
|
-
import "../chunk-
|
|
34
|
+
import "../chunk-V75HVZTB.js";
|
|
36
35
|
import "../chunk-HEQVUIHQ.js";
|
|
37
36
|
import "../chunk-U3IGFMCY.js";
|
|
38
|
-
import "../chunk-
|
|
37
|
+
import "../chunk-DVBA6PGR.js";
|
|
39
38
|
import "../chunk-B7KZLXHV.js";
|
|
40
39
|
import "../chunk-4DZNTUK7.js";
|
|
41
40
|
import "../chunk-N6A7A4RA.js";
|