@jaimevalasek/aioson 1.3.0 → 1.5.1
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 +31 -1
- package/LICENSE +661 -21
- package/README.md +22 -3
- package/docs/en/squad-dashboard.md +372 -0
- package/docs/openclaw-bridge.md +308 -0
- package/docs/pt/README.md +62 -2
- package/docs/pt/advisor-spec.md +5 -5
- package/docs/pt/agentes-customizados.md +670 -0
- package/docs/pt/agentes.md +235 -23
- package/docs/pt/automacao-squads.md +407 -0
- package/docs/pt/cenarios.md +49 -5
- package/docs/pt/clientes-ai.md +62 -0
- package/docs/pt/comandos-cli.md +226 -17
- package/docs/pt/deyvin.md +115 -0
- package/docs/pt/genome-3.0-spec.md +11 -11
- package/docs/pt/inicio-rapido.md +63 -2
- package/docs/pt/memoria-contexto.md +255 -0
- package/docs/pt/output-strategy-delivery.md +655 -0
- package/docs/pt/profiler-system.md +17 -17
- package/docs/pt/runtime-observability.md +5 -1
- package/docs/pt/skills.md +175 -0
- package/docs/pt/squad-dashboard.md +373 -0
- package/docs/pt/{squad-genoma.md → squad-genome.md} +81 -75
- package/docs/testing/genome-2.0-matrix.md +5 -5
- package/docs/testing/genome-2.0-rollout.md +10 -10
- package/package.json +4 -4
- package/src/agents.js +21 -5
- package/src/backup-local.js +74 -0
- package/src/backup-provider.js +303 -0
- package/src/cli.js +276 -2
- package/src/commands/agents.js +22 -4
- package/src/commands/backup-local-cmd.js +25 -0
- package/src/commands/backup.js +533 -0
- package/src/commands/cloud.js +17 -17
- package/src/commands/context-pack.js +45 -0
- package/src/commands/implementation-plan.js +340 -0
- package/src/commands/learning.js +134 -0
- package/src/commands/live.js +1583 -0
- package/src/commands/runtime.js +1075 -2
- package/src/commands/scan-project.js +288 -24
- package/src/commands/setup-context.js +30 -2
- package/src/commands/skill.js +558 -0
- package/src/commands/squad-agent-create.js +788 -0
- package/src/commands/squad-daemon.js +209 -0
- package/src/commands/squad-dashboard.js +39 -0
- package/src/commands/squad-deploy.js +64 -0
- package/src/commands/squad-doctor.js +103 -1
- package/src/commands/squad-investigate.js +261 -0
- package/src/commands/squad-learning.js +209 -0
- package/src/commands/squad-mcp.js +270 -0
- package/src/commands/squad-pipeline.js +247 -1
- package/src/commands/squad-plan.js +329 -0
- package/src/commands/squad-processes.js +56 -0
- package/src/commands/squad-recovery.js +42 -0
- package/src/commands/squad-roi.js +291 -0
- package/src/commands/squad-score.js +250 -0
- package/src/commands/squad-status.js +38 -2
- package/src/commands/squad-validate.js +118 -1
- package/src/commands/squad-webhook.js +160 -0
- package/src/commands/squad-worker.js +191 -0
- package/src/commands/squad-worktrees.js +75 -0
- package/src/commands/test-agents.js +6 -1
- package/src/commands/web-map.js +70 -0
- package/src/commands/web-scrape.js +71 -0
- package/src/commands/workflow-next.js +8 -1
- package/src/commands/workflow-status.js +250 -0
- package/src/constants.js +88 -16
- package/src/context-memory.js +837 -0
- package/src/context-writer.js +47 -1
- package/src/delivery-runner.js +319 -0
- package/src/genome-files.js +1 -1
- package/src/genome-format.js +1 -1
- package/src/i18n/messages/en.js +333 -8
- package/src/i18n/messages/es.js +240 -6
- package/src/i18n/messages/fr.js +239 -5
- package/src/i18n/messages/pt-BR.js +330 -12
- package/src/installer.js +30 -2
- package/src/lib/genomes/compat.js +1 -1
- package/src/lib/webhook-server.js +328 -0
- package/src/mcp-connectors/registry.js +602 -0
- package/src/runtime-store.js +1037 -42
- package/src/session-handoff.js +77 -0
- package/src/squad/external-session.js +180 -0
- package/src/squad/inter-squad.js +74 -0
- package/src/squad/recovery-context.js +201 -0
- package/src/squad/worktree-manager.js +114 -0
- package/src/squad-daemon.js +490 -0
- package/src/squad-dashboard/api.js +223 -0
- package/src/squad-dashboard/attachment-handler.js +93 -0
- package/src/squad-dashboard/context-monitor.js +157 -0
- package/src/squad-dashboard/execution-logs.js +115 -0
- package/src/squad-dashboard/hunk-review.js +209 -0
- package/src/squad-dashboard/metrics.js +133 -0
- package/src/squad-dashboard/process-monitor.js +125 -0
- package/src/squad-dashboard/renderer.js +858 -0
- package/src/squad-dashboard/server.js +232 -0
- package/src/squad-dashboard/styles.js +525 -0
- package/src/squad-dashboard/token-tracker.js +99 -0
- package/src/web.js +284 -0
- package/src/worker-runner.js +339 -0
- package/template/.aioson/agents/analyst.md +40 -9
- package/template/.aioson/agents/architect.md +24 -5
- package/template/.aioson/agents/dev.md +254 -25
- package/template/.aioson/agents/deyvin.md +174 -0
- package/template/.aioson/agents/discovery-design-doc.md +25 -1
- package/template/.aioson/agents/{genoma.md → genome.md} +20 -20
- package/template/.aioson/agents/neo.md +152 -0
- package/template/.aioson/agents/orache.md +388 -0
- package/template/.aioson/agents/orchestrator.md +63 -2
- package/template/.aioson/agents/pair.md +5 -0
- package/template/.aioson/agents/pm.md +17 -5
- package/template/.aioson/agents/product.md +113 -29
- package/template/.aioson/agents/profiler-enricher.md +1 -1
- package/template/.aioson/agents/profiler-forge.md +9 -9
- package/template/.aioson/agents/profiler-researcher.md +1 -1
- package/template/.aioson/agents/qa.md +18 -5
- package/template/.aioson/agents/setup.md +138 -18
- package/template/.aioson/agents/sheldon.md +603 -0
- package/template/.aioson/agents/squad.md +866 -28
- package/template/.aioson/agents/tester.md +254 -0
- package/template/.aioson/agents/ux-ui.md +289 -34
- package/template/.aioson/config.md +181 -0
- package/template/.aioson/context/spec.md.template +17 -0
- package/template/.aioson/genomes/.gitkeep +0 -0
- package/template/.aioson/installed-skills/.gitkeep +0 -0
- package/template/.aioson/locales/en/agents/analyst.md +34 -4
- package/template/.aioson/locales/en/agents/architect.md +18 -0
- package/template/.aioson/locales/en/agents/dev.md +155 -11
- package/template/.aioson/locales/en/agents/deyvin.md +137 -0
- package/template/.aioson/locales/en/agents/{genoma.md → genome.md} +14 -14
- package/template/.aioson/locales/en/agents/neo.md +8 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/en/agents/pair.md +5 -0
- package/template/.aioson/locales/en/agents/pm.md +7 -0
- package/template/.aioson/locales/en/agents/product.md +35 -17
- package/template/.aioson/locales/en/agents/qa.md +56 -0
- package/template/.aioson/locales/en/agents/setup.md +53 -6
- package/template/.aioson/locales/en/agents/sheldon.md +340 -0
- package/template/.aioson/locales/en/agents/squad.md +203 -15
- package/template/.aioson/locales/en/agents/ux-ui.md +383 -35
- package/template/.aioson/locales/es/agents/analyst.md +24 -4
- package/template/.aioson/locales/es/agents/architect.md +18 -0
- package/template/.aioson/locales/es/agents/dev.md +136 -9
- package/template/.aioson/locales/es/agents/deyvin.md +97 -0
- package/template/.aioson/locales/es/agents/{genoma.md → genome.md} +13 -13
- package/template/.aioson/locales/es/agents/neo.md +48 -0
- package/template/.aioson/locales/es/agents/orache.md +103 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/es/agents/pair.md +5 -0
- package/template/.aioson/locales/es/agents/pm.md +7 -0
- package/template/.aioson/locales/es/agents/product.md +13 -3
- package/template/.aioson/locales/es/agents/qa.md +33 -0
- package/template/.aioson/locales/es/agents/setup.md +30 -6
- package/template/.aioson/locales/es/agents/sheldon.md +192 -0
- package/template/.aioson/locales/es/agents/squad.md +284 -15
- package/template/.aioson/locales/es/agents/ux-ui.md +34 -25
- package/template/.aioson/locales/fr/agents/analyst.md +24 -4
- package/template/.aioson/locales/fr/agents/architect.md +18 -0
- package/template/.aioson/locales/fr/agents/dev.md +136 -9
- package/template/.aioson/locales/fr/agents/deyvin.md +97 -0
- package/template/.aioson/locales/fr/agents/{genoma.md → genome.md} +7 -7
- package/template/.aioson/locales/fr/agents/neo.md +48 -0
- package/template/.aioson/locales/fr/agents/orache.md +104 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/fr/agents/pair.md +5 -0
- package/template/.aioson/locales/fr/agents/pm.md +7 -0
- package/template/.aioson/locales/fr/agents/product.md +13 -3
- package/template/.aioson/locales/fr/agents/qa.md +33 -0
- package/template/.aioson/locales/fr/agents/setup.md +30 -6
- package/template/.aioson/locales/fr/agents/sheldon.md +192 -0
- package/template/.aioson/locales/fr/agents/squad.md +279 -10
- package/template/.aioson/locales/fr/agents/ux-ui.md +34 -25
- package/template/.aioson/locales/pt-BR/agents/analyst.md +45 -4
- package/template/.aioson/locales/pt-BR/agents/architect.md +29 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +167 -15
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +137 -0
- package/template/.aioson/locales/pt-BR/agents/{genoma.md → genome.md} +49 -49
- package/template/.aioson/locales/pt-BR/agents/neo.md +147 -0
- package/template/.aioson/locales/pt-BR/agents/orache.md +137 -0
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/pt-BR/agents/pair.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/pm.md +7 -0
- package/template/.aioson/locales/pt-BR/agents/product.md +43 -20
- package/template/.aioson/locales/pt-BR/agents/qa.md +67 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +53 -6
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +192 -0
- package/template/.aioson/locales/pt-BR/agents/squad.md +591 -47
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +369 -22
- package/template/.aioson/my-agents/.gitkeep +0 -0
- package/template/.aioson/rules/.gitkeep +0 -0
- package/template/.aioson/rules/squad/.gitkeep +0 -0
- package/template/.aioson/rules/squad/README.md +50 -0
- package/template/.aioson/schemas/genome-meta.schema.json +1 -1
- package/template/.aioson/schemas/genome.schema.json +1 -1
- package/template/.aioson/schemas/squad-blueprint.schema.json +32 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +434 -1
- package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +205 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -0
- package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +210 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -0
- package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +203 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +407 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +272 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +524 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +277 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +289 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +437 -0
- package/template/.aioson/skills/design/interface-design/SKILL.md +47 -0
- package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -0
- package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -0
- package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +71 -0
- package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -0
- package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -0
- package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +62 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -0
- package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +209 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -0
- package/template/.aioson/skills/design-system/SKILL.md +92 -0
- package/template/.aioson/skills/design-system/cognitive-core-ui.skill +0 -0
- package/template/.aioson/skills/design-system/components/SKILL.md +274 -0
- package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md +184 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md +250 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md +197 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md +231 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/premium-visual-design/SKILL.md +83 -0
- package/template/.aioson/skills/premium-visual-design/components/agent-badge.md +92 -0
- package/template/.aioson/skills/premium-visual-design/components/dependency-node.md +102 -0
- package/template/.aioson/skills/premium-visual-design/components/mention-autocomplete.md +136 -0
- package/template/.aioson/skills/premium-visual-design/components/notification-center.md +136 -0
- package/template/.aioson/skills/premium-visual-design/components/review-action-bar.md +188 -0
- package/template/.aioson/skills/premium-visual-design/components/team-switcher.md +131 -0
- package/template/.aioson/skills/premium-visual-design/patterns/agent-message-thread.md +198 -0
- package/template/.aioson/skills/premium-visual-design/patterns/notification-panel.md +275 -0
- package/template/.aioson/skills/premium-visual-design/patterns/review-workflow-ui.md +234 -0
- package/template/.aioson/skills/premium-visual-design/patterns/task-dependency-graph.md +147 -0
- package/template/.aioson/skills/premium-visual-design/tokens/status-extended.md +142 -0
- package/template/.aioson/skills/squad/SKILL.md +58 -0
- package/template/.aioson/skills/squad/domains/.gitkeep +0 -0
- package/template/.aioson/skills/squad/formats/.gitkeep +0 -0
- package/template/.aioson/skills/squad/formats/catalog.json +15 -0
- package/template/.aioson/skills/squad/formats/content/blog-post.md +47 -0
- package/template/.aioson/skills/squad/formats/content/newsletter.md +47 -0
- package/template/.aioson/skills/squad/formats/creative/podcast-script.md +43 -0
- package/template/.aioson/skills/squad/formats/creative/video-script.md +41 -0
- package/template/.aioson/skills/squad/formats/social/instagram-feed.md +42 -0
- package/template/.aioson/skills/squad/formats/social/linkedin-post.md +42 -0
- package/template/.aioson/skills/squad/formats/social/tiktok.md +39 -0
- package/template/.aioson/skills/squad/formats/social/twitter-thread.md +39 -0
- package/template/.aioson/skills/squad/formats/social/youtube-long.md +47 -0
- package/template/.aioson/skills/squad/formats/social/youtube-shorts.md +39 -0
- package/template/.aioson/skills/squad/patterns/.gitkeep +0 -0
- package/template/.aioson/skills/squad/patterns/multi-platform-pattern.md +108 -0
- package/template/.aioson/skills/squad/patterns/persona-based-pattern.md +98 -0
- package/template/.aioson/skills/squad/patterns/pipeline-pattern.md +106 -0
- package/template/.aioson/skills/squad/patterns/review-loop-pattern.md +81 -0
- package/template/.aioson/skills/squad/references/.gitkeep +0 -0
- package/template/.aioson/skills/squad/references/checklist-templates.md +122 -0
- package/template/.aioson/skills/squad/references/executor-archetypes.md +123 -0
- package/template/.aioson/skills/squad/references/workflow-templates.md +169 -0
- package/template/.aioson/skills/static/debugging-protocol.md +42 -0
- package/template/.aioson/skills/static/git-worktrees.md +36 -0
- package/template/.aioson/tasks/implementation-plan.md +307 -0
- package/template/.aioson/tasks/squad-create.md +1 -1
- package/template/.aioson/tasks/squad-design.md +28 -0
- package/template/.aioson/tasks/squad-execution-plan.md +279 -0
- package/template/.aioson/tasks/squad-export.md +1 -1
- package/template/.aioson/tasks/squad-investigate.md +44 -0
- package/template/.aioson/tasks/squad-learning-review.md +44 -0
- package/template/.aioson/tasks/squad-output-config.md +177 -0
- package/template/.aioson/tasks/squad-profile.md +48 -0
- package/template/.aioson/tasks/squad-review.md +61 -0
- package/template/.aioson/tasks/squad-task-decompose.md +66 -0
- package/template/.aioson/tasks/squad-validate.md +1 -1
- package/template/.claude/commands/aioson/agent/deyvin.md +5 -0
- package/template/.claude/commands/aioson/agent/discovery-design-doc.md +5 -0
- package/template/.claude/commands/aioson/agent/genome.md +5 -0
- package/template/.claude/commands/aioson/agent/neo.md +5 -0
- package/template/.claude/commands/aioson/agent/product.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-enricher.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-researcher.md +5 -0
- package/template/.claude/commands/aioson/agent/squad.md +5 -0
- package/template/.claude/commands/aioson/agent/tester.md +5 -0
- package/template/.gemini/GEMINI.md +3 -0
- package/template/.gemini/commands/aios-deyvin.toml +6 -0
- package/template/.gemini/commands/aios-neo.toml +4 -0
- package/template/.gemini/commands/aios-pair.toml +6 -0
- package/template/.gemini/commands/aios-tester.toml +6 -0
- package/template/AGENTS.md +37 -6
- package/template/CLAUDE.md +34 -4
- package/template/OPENCODE.md +8 -2
- package/template/squad-searches/.gitkeep +0 -0
- package/template/.aioson/skills/static/interface-design.md +0 -372
- package/template/.aioson/skills/static/premium-command-center-ui.md +0 -190
- /package/template/.aioson/{genomas → docs}/.gitkeep +0 -0
- /package/template/.claude/commands/aioson/{analyst.md → agent/analyst.md} +0 -0
- /package/template/.claude/commands/aioson/{architect.md → agent/architect.md} +0 -0
- /package/template/.claude/commands/aioson/{dev.md → agent/dev.md} +0 -0
- /package/template/.claude/commands/aioson/{orchestrator.md → agent/orchestrator.md} +0 -0
- /package/template/.claude/commands/aioson/{pm.md → agent/pm.md} +0 -0
- /package/template/.claude/commands/aioson/{qa.md → agent/qa.md} +0 -0
- /package/template/.claude/commands/aioson/{setup.md → agent/setup.md} +0 -0
- /package/template/.claude/commands/aioson/{ux-ui.md → agent/ux-ui.md} +0 -0
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { execFile } = require('node:child_process');
|
|
6
|
+
const { exists, ensureDir } = require('../utils');
|
|
7
|
+
|
|
8
|
+
const INSTALLED_SKILLS_DIR = '.aioson/installed-skills';
|
|
9
|
+
const TOOL_TARGETS = [
|
|
10
|
+
'.claude/skills',
|
|
11
|
+
'.cursor/skills',
|
|
12
|
+
'.windsurf/skills'
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
function resolveTargetDir(args) {
|
|
16
|
+
return path.resolve(process.cwd(), args[0] || '.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse YAML frontmatter from a SKILL.md file.
|
|
21
|
+
*/
|
|
22
|
+
function parseSkillFrontmatter(content) {
|
|
23
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
24
|
+
if (!match) return {};
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const line of match[1].split('\n')) {
|
|
27
|
+
const idx = line.indexOf(':');
|
|
28
|
+
if (idx === -1) continue;
|
|
29
|
+
const key = line.slice(0, idx).trim();
|
|
30
|
+
let val = line.slice(idx + 1).trim();
|
|
31
|
+
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
|
|
32
|
+
val = val.slice(1, -1);
|
|
33
|
+
}
|
|
34
|
+
result[key] = val;
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Copy a skill to a tool-specific directory (Claude Code, Cursor, Windsurf).
|
|
41
|
+
*/
|
|
42
|
+
async function distributeToTool(targetDir, slug, skillDir) {
|
|
43
|
+
const results = [];
|
|
44
|
+
for (const toolPath of TOOL_TARGETS) {
|
|
45
|
+
const toolSkillDir = path.join(targetDir, toolPath, slug);
|
|
46
|
+
try {
|
|
47
|
+
await ensureDir(toolSkillDir);
|
|
48
|
+
// Copy all files from the installed skill dir
|
|
49
|
+
const entries = await fs.readdir(skillDir);
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
const src = path.join(skillDir, entry);
|
|
52
|
+
const dest = path.join(toolSkillDir, entry);
|
|
53
|
+
const stat = await fs.stat(src);
|
|
54
|
+
if (stat.isFile()) {
|
|
55
|
+
await fs.copyFile(src, dest);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
results.push({ tool: toolPath, ok: true });
|
|
59
|
+
} catch (err) {
|
|
60
|
+
results.push({ tool: toolPath, ok: false, error: err.message });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Remove a skill from tool-specific directories.
|
|
68
|
+
*/
|
|
69
|
+
async function removeFromTools(targetDir, slug) {
|
|
70
|
+
for (const toolPath of TOOL_TARGETS) {
|
|
71
|
+
const toolSkillDir = path.join(targetDir, toolPath, slug);
|
|
72
|
+
try {
|
|
73
|
+
await fs.rm(toolSkillDir, { recursive: true, force: true });
|
|
74
|
+
} catch {
|
|
75
|
+
// Ignore — may not exist
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Update the AGENTS.md installed-skills section.
|
|
82
|
+
*/
|
|
83
|
+
async function updateAgentsMdSkills(targetDir) {
|
|
84
|
+
const agentsPath = path.join(targetDir, 'AGENTS.md');
|
|
85
|
+
if (!(await exists(agentsPath))) return;
|
|
86
|
+
|
|
87
|
+
let content = await fs.readFile(agentsPath, 'utf8');
|
|
88
|
+
|
|
89
|
+
// List installed skills
|
|
90
|
+
const skillsDir = path.join(targetDir, INSTALLED_SKILLS_DIR);
|
|
91
|
+
let skills = [];
|
|
92
|
+
try {
|
|
93
|
+
const entries = await fs.readdir(skillsDir);
|
|
94
|
+
for (const slug of entries) {
|
|
95
|
+
const skillMdPath = path.join(skillsDir, slug, 'SKILL.md');
|
|
96
|
+
if (await exists(skillMdPath)) {
|
|
97
|
+
const raw = await fs.readFile(skillMdPath, 'utf8');
|
|
98
|
+
const fm = parseSkillFrontmatter(raw);
|
|
99
|
+
skills.push({
|
|
100
|
+
slug,
|
|
101
|
+
name: fm.name || slug,
|
|
102
|
+
description: fm.description || ''
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
// No installed skills
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Build the section
|
|
111
|
+
const marker = '## Installed skills';
|
|
112
|
+
const endMarker = '## '; // Next section starts with ##
|
|
113
|
+
const startIdx = content.indexOf(marker);
|
|
114
|
+
|
|
115
|
+
let skillsSection = '';
|
|
116
|
+
if (skills.length > 0) {
|
|
117
|
+
skillsSection = `${marker}\n\n`;
|
|
118
|
+
skillsSection += 'These skills are available in the project. Load them on-demand when the task matches their description.\n\n';
|
|
119
|
+
skillsSection += '| Skill | File | Description |\n';
|
|
120
|
+
skillsSection += '|-------|------|-------------|\n';
|
|
121
|
+
for (const s of skills) {
|
|
122
|
+
const shortDesc = s.description.length > 100 ? s.description.slice(0, 100) + '...' : s.description;
|
|
123
|
+
skillsSection += `| @${s.slug} | \`.aioson/installed-skills/${s.slug}/SKILL.md\` | ${shortDesc} |\n`;
|
|
124
|
+
}
|
|
125
|
+
skillsSection += '\n';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (startIdx !== -1) {
|
|
129
|
+
// Replace existing section
|
|
130
|
+
const afterMarker = content.slice(startIdx + marker.length);
|
|
131
|
+
const nextSectionIdx = afterMarker.indexOf('\n## ');
|
|
132
|
+
if (nextSectionIdx !== -1) {
|
|
133
|
+
const before = content.slice(0, startIdx);
|
|
134
|
+
const after = afterMarker.slice(nextSectionIdx + 1);
|
|
135
|
+
content = before + (skills.length > 0 ? skillsSection : '') + after;
|
|
136
|
+
} else {
|
|
137
|
+
// Section is at the end
|
|
138
|
+
content = content.slice(0, startIdx) + skillsSection;
|
|
139
|
+
}
|
|
140
|
+
} else if (skills.length > 0) {
|
|
141
|
+
// Insert before "## Golden rule" or at the end
|
|
142
|
+
const goldenIdx = content.indexOf('## Golden rule');
|
|
143
|
+
if (goldenIdx !== -1) {
|
|
144
|
+
content = content.slice(0, goldenIdx) + skillsSection + content.slice(goldenIdx);
|
|
145
|
+
} else {
|
|
146
|
+
content = content.trimEnd() + '\n\n' + skillsSection;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
await fs.writeFile(agentsPath, content, 'utf8');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Install from npm using @tech-leads-club/agent-skills
|
|
155
|
+
* Runs the npm CLI, then moves the resulting files to .aioson/installed-skills/
|
|
156
|
+
*/
|
|
157
|
+
async function installFromNpm(targetDir, slug, options, logger) {
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
const args = ['@tech-leads-club/agent-skills', 'install', '--skill', slug];
|
|
160
|
+
if (options.force) args.push('--force');
|
|
161
|
+
|
|
162
|
+
logger.log(` Running: npx ${args.join(' ')}`);
|
|
163
|
+
execFile('npx', args, {
|
|
164
|
+
cwd: targetDir,
|
|
165
|
+
timeout: 60000,
|
|
166
|
+
env: { ...process.env }
|
|
167
|
+
}, async (error, stdout, stderr) => {
|
|
168
|
+
if (error) {
|
|
169
|
+
logger.error(` npm install failed: ${error.message}`);
|
|
170
|
+
return resolve({ ok: false, error: error.message });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// The npm tool installs to .claude/skills/{slug}/, .cursor/skills/{slug}/, .windsurf/skills/{slug}/
|
|
174
|
+
// Find the SKILL.md in any of these and copy to .aioson/installed-skills/
|
|
175
|
+
const sources = TOOL_TARGETS.map(t => path.join(targetDir, t, slug));
|
|
176
|
+
let sourceDir = null;
|
|
177
|
+
for (const src of sources) {
|
|
178
|
+
if (await exists(path.join(src, 'SKILL.md'))) {
|
|
179
|
+
sourceDir = src;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!sourceDir) {
|
|
185
|
+
return resolve({ ok: false, error: `Skill "${slug}" installed by npm but SKILL.md not found in tool directories` });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Copy to .aioson/installed-skills/{slug}/
|
|
189
|
+
const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
|
|
190
|
+
await ensureDir(destDir);
|
|
191
|
+
|
|
192
|
+
const entries = await fs.readdir(sourceDir);
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
await fs.copyFile(path.join(sourceDir, entry), path.join(destDir, entry));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
resolve({ ok: true, sourceDir, destDir });
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Install from aioson.com cloud registry
|
|
204
|
+
*/
|
|
205
|
+
async function installFromCloud(targetDir, slug, options, logger) {
|
|
206
|
+
// Read cloud config
|
|
207
|
+
let cloudUrl, cloudToken;
|
|
208
|
+
try {
|
|
209
|
+
const raw = await fs.readFile(path.join(targetDir, '.aioson/install.json'), 'utf8');
|
|
210
|
+
const meta = JSON.parse(raw);
|
|
211
|
+
cloudUrl = options.url || meta.cloudBaseUrl;
|
|
212
|
+
cloudToken = options.token || meta.cloudApiToken;
|
|
213
|
+
} catch {
|
|
214
|
+
cloudUrl = options.url;
|
|
215
|
+
cloudToken = options.token;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!cloudUrl) {
|
|
219
|
+
return { ok: false, error: 'Cloud URL not configured. Use --url or set cloudBaseUrl.' };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const endpoint = `${cloudUrl.replace(/\/+$/, '')}/api/registry/skills/${encodeURIComponent(slug)}`;
|
|
223
|
+
logger.log(` Fetching: ${endpoint}`);
|
|
224
|
+
|
|
225
|
+
const headers = { accept: 'application/json' };
|
|
226
|
+
if (cloudToken) headers.authorization = `Bearer ${cloudToken}`;
|
|
227
|
+
|
|
228
|
+
const response = await fetch(endpoint, { headers, signal: AbortSignal.timeout(15000) });
|
|
229
|
+
if (!response.ok) {
|
|
230
|
+
return { ok: false, error: `Cloud returned ${response.status}` };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const snapshot = await response.json();
|
|
234
|
+
if (!snapshot.skill || !snapshot.contentMarkdown) {
|
|
235
|
+
return { ok: false, error: 'Invalid skill snapshot from cloud' };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Build SKILL.md with frontmatter
|
|
239
|
+
const fm = [
|
|
240
|
+
'---',
|
|
241
|
+
`name: ${snapshot.skill.slug}`,
|
|
242
|
+
`description: ${snapshot.skill.summary || snapshot.skill.title || slug}`,
|
|
243
|
+
`source: cloud`,
|
|
244
|
+
`domain: ${snapshot.skill.domain || 'general'}`,
|
|
245
|
+
'---',
|
|
246
|
+
'',
|
|
247
|
+
snapshot.contentMarkdown
|
|
248
|
+
].join('\n');
|
|
249
|
+
|
|
250
|
+
const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
|
|
251
|
+
await ensureDir(destDir);
|
|
252
|
+
await fs.writeFile(path.join(destDir, 'SKILL.md'), fm, 'utf8');
|
|
253
|
+
|
|
254
|
+
// Write meta
|
|
255
|
+
await fs.writeFile(path.join(destDir, '.skill-meta.json'), JSON.stringify({
|
|
256
|
+
source: 'cloud',
|
|
257
|
+
cloudSlug: snapshot.skill.slug,
|
|
258
|
+
installedAt: new Date().toISOString()
|
|
259
|
+
}, null, 2), 'utf8');
|
|
260
|
+
|
|
261
|
+
return { ok: true, destDir };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Install from a local file path
|
|
266
|
+
*/
|
|
267
|
+
async function installFromLocal(targetDir, slug, filePath, logger) {
|
|
268
|
+
const absPath = path.resolve(targetDir, filePath);
|
|
269
|
+
if (!(await exists(absPath))) {
|
|
270
|
+
return { ok: false, error: `File not found: ${absPath}` };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
|
|
274
|
+
await ensureDir(destDir);
|
|
275
|
+
|
|
276
|
+
const stat = await fs.stat(absPath);
|
|
277
|
+
if (stat.isDirectory()) {
|
|
278
|
+
// Copy entire directory
|
|
279
|
+
const entries = await fs.readdir(absPath);
|
|
280
|
+
for (const entry of entries) {
|
|
281
|
+
const src = path.join(absPath, entry);
|
|
282
|
+
const srcStat = await fs.stat(src);
|
|
283
|
+
if (srcStat.isFile()) {
|
|
284
|
+
await fs.copyFile(src, path.join(destDir, entry));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
// Single file — copy as SKILL.md
|
|
289
|
+
await fs.copyFile(absPath, path.join(destDir, 'SKILL.md'));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Write meta
|
|
293
|
+
await fs.writeFile(path.join(destDir, '.skill-meta.json'), JSON.stringify({
|
|
294
|
+
source: 'local',
|
|
295
|
+
sourcePath: filePath,
|
|
296
|
+
installedAt: new Date().toISOString()
|
|
297
|
+
}, null, 2), 'utf8');
|
|
298
|
+
|
|
299
|
+
return { ok: true, destDir };
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ── Main commands ──
|
|
303
|
+
|
|
304
|
+
async function runSkillInstall({ args, options = {}, logger, t }) {
|
|
305
|
+
const targetDir = resolveTargetDir(args);
|
|
306
|
+
const slug = options.slug || options.skill;
|
|
307
|
+
const from = options.from || 'npm';
|
|
308
|
+
|
|
309
|
+
if (!slug) {
|
|
310
|
+
logger.error('Usage: aioson skill:install --slug=<name> [--from=npm|cloud|./path]');
|
|
311
|
+
return { ok: false, error: 'Missing --slug' };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
logger.log(`Installing skill "${slug}" from ${from}...`);
|
|
315
|
+
|
|
316
|
+
let result;
|
|
317
|
+
if (from === 'npm') {
|
|
318
|
+
result = await installFromNpm(targetDir, slug, options, logger);
|
|
319
|
+
} else if (from === 'cloud') {
|
|
320
|
+
result = await installFromCloud(targetDir, slug, options, logger);
|
|
321
|
+
} else {
|
|
322
|
+
// Treat as local path
|
|
323
|
+
result = await installFromLocal(targetDir, slug, from, logger);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!result.ok) {
|
|
327
|
+
logger.error(` Installation failed: ${result.error}`);
|
|
328
|
+
return { ok: false, error: result.error, slug };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Distribute to tool directories
|
|
332
|
+
const skillDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
|
|
333
|
+
const distributed = await distributeToTool(targetDir, slug, skillDir);
|
|
334
|
+
|
|
335
|
+
for (const d of distributed) {
|
|
336
|
+
const status = d.ok ? 'OK' : `FAIL: ${d.error}`;
|
|
337
|
+
logger.log(` ${d.tool}: ${status}`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Update AGENTS.md
|
|
341
|
+
await updateAgentsMdSkills(targetDir);
|
|
342
|
+
logger.log(` AGENTS.md updated`);
|
|
343
|
+
|
|
344
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
345
|
+
if (await exists(skillMdPath)) {
|
|
346
|
+
const raw = await fs.readFile(skillMdPath, 'utf8');
|
|
347
|
+
const fm = parseSkillFrontmatter(raw);
|
|
348
|
+
logger.log(`\nInstalled: ${fm.name || slug}`);
|
|
349
|
+
if (fm.description) {
|
|
350
|
+
logger.log(` ${fm.description.slice(0, 120)}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
logger.log(`\nSkill available at: .aioson/installed-skills/${slug}/SKILL.md`);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
ok: true,
|
|
358
|
+
slug,
|
|
359
|
+
from,
|
|
360
|
+
installed: path.join(INSTALLED_SKILLS_DIR, slug),
|
|
361
|
+
distributed: distributed.filter(d => d.ok).map(d => d.tool)
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Scan a directory for .md files with SKILL.md or frontmatter descriptions.
|
|
367
|
+
* Returns array of { slug, name, description, type, path }.
|
|
368
|
+
*/
|
|
369
|
+
async function scanSourceSkillDir(baseDir, type) {
|
|
370
|
+
const results = [];
|
|
371
|
+
if (!(await exists(baseDir))) return results;
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
const entries = await fs.readdir(baseDir, { withFileTypes: true });
|
|
375
|
+
for (const entry of entries) {
|
|
376
|
+
if (entry.name.startsWith('.')) continue;
|
|
377
|
+
|
|
378
|
+
if (entry.isDirectory()) {
|
|
379
|
+
// Look for SKILL.md inside the directory
|
|
380
|
+
const skillMdPath = path.join(baseDir, entry.name, 'SKILL.md');
|
|
381
|
+
if (await exists(skillMdPath)) {
|
|
382
|
+
const raw = await fs.readFile(skillMdPath, 'utf8');
|
|
383
|
+
const fm = parseSkillFrontmatter(raw);
|
|
384
|
+
results.push({
|
|
385
|
+
slug: entry.name,
|
|
386
|
+
name: fm.name || entry.name,
|
|
387
|
+
description: fm.description || '',
|
|
388
|
+
type,
|
|
389
|
+
path: path.relative(process.cwd(), path.join(baseDir, entry.name))
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
} else if (entry.isFile() && entry.name.endsWith('.md') && entry.name !== 'README.md') {
|
|
393
|
+
// Read frontmatter from .md file directly
|
|
394
|
+
const filePath = path.join(baseDir, entry.name);
|
|
395
|
+
const raw = await fs.readFile(filePath, 'utf8');
|
|
396
|
+
const fm = parseSkillFrontmatter(raw);
|
|
397
|
+
const slug = entry.name.replace(/\.md$/, '');
|
|
398
|
+
results.push({
|
|
399
|
+
slug,
|
|
400
|
+
name: fm.name || slug,
|
|
401
|
+
description: fm.description || '',
|
|
402
|
+
type,
|
|
403
|
+
path: path.relative(process.cwd(), filePath)
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
} catch {
|
|
408
|
+
// Directory not readable
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return results;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
async function runSkillList({ args, options = {}, logger, t }) {
|
|
415
|
+
const targetDir = resolveTargetDir(args);
|
|
416
|
+
const skillsDir = path.join(targetDir, INSTALLED_SKILLS_DIR);
|
|
417
|
+
const showAll = options.all !== undefined;
|
|
418
|
+
|
|
419
|
+
const installed = [];
|
|
420
|
+
|
|
421
|
+
// Installed skills
|
|
422
|
+
try {
|
|
423
|
+
const entries = await fs.readdir(skillsDir);
|
|
424
|
+
for (const slug of entries) {
|
|
425
|
+
const skillMdPath = path.join(skillsDir, slug, 'SKILL.md');
|
|
426
|
+
if (!(await exists(skillMdPath))) continue;
|
|
427
|
+
|
|
428
|
+
const raw = await fs.readFile(skillMdPath, 'utf8');
|
|
429
|
+
const fm = parseSkillFrontmatter(raw);
|
|
430
|
+
|
|
431
|
+
let source = 'unknown';
|
|
432
|
+
try {
|
|
433
|
+
const metaRaw = await fs.readFile(path.join(skillsDir, slug, '.skill-meta.json'), 'utf8');
|
|
434
|
+
const meta = JSON.parse(metaRaw);
|
|
435
|
+
source = meta.source || 'unknown';
|
|
436
|
+
} catch { /* no meta */ }
|
|
437
|
+
|
|
438
|
+
installed.push({
|
|
439
|
+
slug,
|
|
440
|
+
name: fm.name || slug,
|
|
441
|
+
description: fm.description || '',
|
|
442
|
+
source,
|
|
443
|
+
path: path.relative(targetDir, path.join(skillsDir, slug))
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
} catch {
|
|
447
|
+
// Dir may not exist
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Source skills (design, static, dynamic)
|
|
451
|
+
const sourceBase = path.join(targetDir, '.aioson/skills');
|
|
452
|
+
const designSkills = await scanSourceSkillDir(path.join(sourceBase, 'design'), 'design');
|
|
453
|
+
const designSystemSkills = await scanSourceSkillDir(sourceBase, 'design-system')
|
|
454
|
+
.then(r => r.filter(s => s.slug === 'design-system'));
|
|
455
|
+
const staticSkills = await scanSourceSkillDir(path.join(sourceBase, 'static'), 'static');
|
|
456
|
+
const dynamicSkills = await scanSourceSkillDir(path.join(sourceBase, 'dynamic'), 'dynamic');
|
|
457
|
+
|
|
458
|
+
// Check active design skill
|
|
459
|
+
let activeDesignSkill = null;
|
|
460
|
+
try {
|
|
461
|
+
const contextPath = path.join(targetDir, '.aioson/context/project.context.md');
|
|
462
|
+
const contextRaw = await fs.readFile(contextPath, 'utf8');
|
|
463
|
+
const match = contextRaw.match(/design_skill:\s*(.+)/);
|
|
464
|
+
if (match) activeDesignSkill = match[1].trim();
|
|
465
|
+
} catch { /* no context */ }
|
|
466
|
+
|
|
467
|
+
// Output
|
|
468
|
+
if (installed.length > 0) {
|
|
469
|
+
logger.log(`Installed skills (${installed.length}):\n`);
|
|
470
|
+
for (const s of installed) {
|
|
471
|
+
logger.log(` ${s.slug} (${s.source})`);
|
|
472
|
+
if (s.description) {
|
|
473
|
+
logger.log(` ${s.description.slice(0, 100)}`);
|
|
474
|
+
}
|
|
475
|
+
logger.log(` ${s.path}/SKILL.md`);
|
|
476
|
+
logger.log('');
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
logger.log('No installed skills.\n');
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Always show source skills summary
|
|
483
|
+
const allSource = [...designSkills, ...staticSkills, ...dynamicSkills];
|
|
484
|
+
|
|
485
|
+
if (designSkills.length > 0) {
|
|
486
|
+
logger.log(`Design skills (${designSkills.length}) — ONE active per project:`);
|
|
487
|
+
for (const s of designSkills) {
|
|
488
|
+
const active = activeDesignSkill === s.slug ? ' [active]' : '';
|
|
489
|
+
logger.log(` ${s.slug}${active}`);
|
|
490
|
+
if (s.description) logger.log(` ${s.description.slice(0, 100)}`);
|
|
491
|
+
}
|
|
492
|
+
logger.log('');
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (staticSkills.length > 0) {
|
|
496
|
+
logger.log(`Static skills (${staticSkills.length}) — loaded by framework match:`);
|
|
497
|
+
for (const s of staticSkills) {
|
|
498
|
+
logger.log(` ${s.slug}`);
|
|
499
|
+
if (showAll && s.description) logger.log(` ${s.description.slice(0, 100)}`);
|
|
500
|
+
}
|
|
501
|
+
logger.log('');
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (dynamicSkills.length > 0) {
|
|
505
|
+
logger.log(`Dynamic skills (${dynamicSkills.length}) — loaded by task context:`);
|
|
506
|
+
for (const s of dynamicSkills) {
|
|
507
|
+
logger.log(` ${s.slug}`);
|
|
508
|
+
if (showAll && s.description) logger.log(` ${s.description.slice(0, 100)}`);
|
|
509
|
+
}
|
|
510
|
+
logger.log('');
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (installed.length === 0 && allSource.length === 0) {
|
|
514
|
+
logger.log('Use `aioson skill:install --slug=<name>` to add a skill.');
|
|
515
|
+
} else {
|
|
516
|
+
logger.log('Source skills are loaded automatically by agents — no installation needed.');
|
|
517
|
+
logger.log('Use --all for full descriptions. Use `aioson skill:install` for third-party skills.');
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return { ok: true, installed, source: { design: designSkills, static: staticSkills, dynamic: dynamicSkills } };
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
async function runSkillRemove({ args, options = {}, logger, t }) {
|
|
524
|
+
const targetDir = resolveTargetDir(args);
|
|
525
|
+
const slug = options.slug || options.skill;
|
|
526
|
+
|
|
527
|
+
if (!slug) {
|
|
528
|
+
logger.error('Usage: aioson skill:remove --slug=<name>');
|
|
529
|
+
return { ok: false, error: 'Missing --slug' };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const skillDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
|
|
533
|
+
if (!(await exists(skillDir))) {
|
|
534
|
+
logger.error(`Skill "${slug}" not found in .aioson/installed-skills/`);
|
|
535
|
+
return { ok: false, error: 'not_found', slug };
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Remove from installed-skills
|
|
539
|
+
await fs.rm(skillDir, { recursive: true, force: true });
|
|
540
|
+
logger.log(` Removed .aioson/installed-skills/${slug}/`);
|
|
541
|
+
|
|
542
|
+
// Remove from tool directories
|
|
543
|
+
await removeFromTools(targetDir, slug);
|
|
544
|
+
logger.log(` Removed from .claude/skills/, .cursor/skills/, .windsurf/skills/`);
|
|
545
|
+
|
|
546
|
+
// Update AGENTS.md
|
|
547
|
+
await updateAgentsMdSkills(targetDir);
|
|
548
|
+
logger.log(` AGENTS.md updated`);
|
|
549
|
+
|
|
550
|
+
logger.log(`\nSkill "${slug}" removed.`);
|
|
551
|
+
return { ok: true, slug };
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
module.exports = {
|
|
555
|
+
runSkillInstall,
|
|
556
|
+
runSkillList,
|
|
557
|
+
runSkillRemove
|
|
558
|
+
};
|