@jaimevalasek/aioson 1.5.1 → 1.7.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 +49 -0
- package/README.md +729 -226
- package/docs/design-previews/aurora-command-ui-website.html +884 -0
- package/docs/design-previews/aurora-command-ui.html +682 -0
- package/docs/design-previews/bold-editorial-ui-website.html +658 -0
- package/docs/design-previews/bold-editorial-ui.html +717 -0
- package/docs/design-previews/clean-saas-ui-website.html +1202 -0
- package/docs/design-previews/clean-saas-ui.html +549 -0
- package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
- package/docs/design-previews/cognitive-core-ui.html +463 -0
- package/docs/design-previews/glassmorphism-ui-website.html +572 -0
- package/docs/design-previews/glassmorphism-ui.html +886 -0
- package/docs/design-previews/index.html +699 -0
- package/docs/design-previews/interface-design-website.html +1187 -0
- package/docs/design-previews/interface-design.html +513 -0
- package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
- package/docs/design-previews/neo-brutalist-ui.html +797 -0
- package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
- package/docs/design-previews/premium-command-center-ui.html +552 -0
- package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
- package/docs/design-previews/warm-craft-ui-website.html +684 -0
- package/docs/design-previews/warm-craft-ui.html +739 -0
- package/docs/en/cli-reference.md +20 -9
- package/docs/integrations/sdlc-genius-boundary.md +76 -0
- package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
- package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
- package/docs/integrations/sdlc-genius-review-samples.md +86 -0
- package/docs/pt/README.md +10 -0
- package/docs/pt/agent-sharding.md +132 -0
- package/docs/pt/agentes.md +9 -2
- package/docs/pt/busca-de-contexto.md +129 -0
- package/docs/pt/cache-de-contexto.md +156 -0
- package/docs/pt/comandos-cli.md +915 -1
- package/docs/pt/design-hybrid-forge.md +356 -0
- package/docs/pt/devlog-pipeline.md +270 -0
- package/docs/pt/fluxo-artefatos.md +178 -0
- package/docs/pt/hooks-session-guard.md +454 -0
- package/docs/pt/inicio-rapido.md +54 -3
- package/docs/pt/inteligencia-adaptativa.md +324 -0
- package/docs/pt/monitor-de-contexto.md +158 -0
- package/docs/pt/recuperacao-de-sessao.md +125 -0
- package/docs/pt/sandbox.md +125 -0
- package/docs/pt/sdd-automation-scripts.md +557 -0
- package/docs/pt/site-forge.md +309 -0
- package/docs/pt/skills.md +98 -6
- package/docs/pt/spec-learnings-pipeline.md +265 -0
- package/package.json +1 -1
- package/src/a2a/client.js +165 -0
- package/src/a2a/server.js +223 -0
- package/src/agent-loader.js +280 -0
- package/src/cli.js +329 -1
- package/src/commands/agent-audit.js +397 -0
- package/src/commands/agent-export-skill.js +229 -0
- package/src/commands/agent-loader.js +85 -0
- package/src/commands/artifact-validate.js +189 -0
- package/src/commands/brief-gen.js +405 -0
- package/src/commands/brief-validate.js +65 -0
- package/src/commands/classify.js +256 -0
- package/src/commands/context-cache.js +90 -0
- package/src/commands/context-compact.js +49 -0
- package/src/commands/context-health.js +175 -0
- package/src/commands/context-monitor.js +163 -0
- package/src/commands/context-search.js +66 -0
- package/src/commands/context-trim.js +177 -0
- package/src/commands/design-hybrid-options.js +385 -0
- package/src/commands/detect-test-runner.js +55 -0
- package/src/commands/devlog-export-brains.js +27 -0
- package/src/commands/devlog-process.js +292 -0
- package/src/commands/devlog-watch.js +131 -0
- package/src/commands/feature-close.js +165 -0
- package/src/commands/gate-check.js +228 -0
- package/src/commands/health.js +214 -0
- package/src/commands/hooks-emit.js +253 -0
- package/src/commands/hooks-install.js +347 -0
- package/src/commands/init.js +54 -13
- package/src/commands/install.js +52 -13
- package/src/commands/learning-auto-promote.js +195 -0
- package/src/commands/learning-evolve.js +364 -0
- package/src/commands/learning-export.js +103 -0
- package/src/commands/learning-rollback.js +164 -0
- package/src/commands/live.js +59 -1
- package/src/commands/pattern-detect.js +33 -0
- package/src/commands/preflight-context.js +30 -0
- package/src/commands/preflight.js +208 -0
- package/src/commands/pulse-update.js +130 -0
- package/src/commands/recovery.js +43 -0
- package/src/commands/runner-daemon.js +274 -0
- package/src/commands/runner-plan.js +70 -0
- package/src/commands/runner-queue-from-plan.js +166 -0
- package/src/commands/runner-queue.js +189 -0
- package/src/commands/runner-run.js +129 -0
- package/src/commands/runtime.js +47 -1
- package/src/commands/sandbox.js +37 -0
- package/src/commands/self-implement-loop.js +256 -0
- package/src/commands/session-guard.js +218 -0
- package/src/commands/setup-context.js +22 -2
- package/src/commands/setup.js +178 -0
- package/src/commands/sizing.js +165 -0
- package/src/commands/skill.js +144 -32
- package/src/commands/spec-checkpoint.js +177 -0
- package/src/commands/spec-status.js +79 -0
- package/src/commands/spec-sync.js +190 -0
- package/src/commands/spec-tasks.js +288 -0
- package/src/commands/squad-autorun.js +1220 -0
- package/src/commands/squad-bus.js +217 -0
- package/src/commands/squad-card.js +149 -0
- package/src/commands/squad-daemon.js +134 -0
- package/src/commands/squad-dependency-graph.js +164 -0
- package/src/commands/squad-review.js +106 -0
- package/src/commands/squad-scaffold.js +55 -0
- package/src/commands/squad-tool-register.js +157 -0
- package/src/commands/state-save.js +122 -0
- package/src/commands/tool-registry-cmd.js +232 -0
- package/src/commands/update.js +9 -0
- package/src/commands/verify-gate.js +572 -0
- package/src/commands/workflow-execute.js +241 -0
- package/src/constants.js +18 -0
- package/src/context-cache.js +159 -0
- package/src/context-search.js +326 -0
- package/src/design-variation-catalog.js +503 -0
- package/src/i18n/messages/en.js +32 -2
- package/src/i18n/messages/es.js +30 -2
- package/src/i18n/messages/fr.js +30 -2
- package/src/i18n/messages/pt-BR.js +32 -2
- package/src/install-animation.js +260 -0
- package/src/install-profile.js +143 -0
- package/src/install-wizard.js +475 -0
- package/src/installer.js +44 -10
- package/src/lib/health-check.js +158 -0
- package/src/lib/hook-protocol.js +76 -0
- package/src/mcp/apps/squad-dashboard/app.js +163 -0
- package/src/mcp/apps/squad-dashboard/index.html +261 -0
- package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
- package/src/mcp/resources/squad-state.js +130 -0
- package/src/parser.js +7 -1
- package/src/preflight-engine.js +443 -0
- package/src/recovery-context-session.js +154 -0
- package/src/runner/cascade.js +97 -0
- package/src/runner/cli-launcher.js +109 -0
- package/src/runner/plan-importer.js +63 -0
- package/src/runner/queue-store.js +159 -0
- package/src/runtime-store.js +158 -4
- package/src/sandbox.js +177 -0
- package/src/squad/agent-teams-adapter.js +264 -0
- package/src/squad/brief-validator.js +350 -0
- package/src/squad/bus-bridge.js +140 -0
- package/src/squad/context-compactor.js +265 -0
- package/src/squad/cross-ai-synthesizer.js +250 -0
- package/src/squad/hooks-generator.js +196 -0
- package/src/squad/inter-squad-events.js +175 -0
- package/src/squad/intra-bus.js +345 -0
- package/src/squad/learning-extractor.js +213 -0
- package/src/squad/pattern-detector.js +365 -0
- package/src/squad/preflight-context.js +296 -0
- package/src/squad/recovery-context.js +242 -71
- package/src/squad/reflection.js +365 -0
- package/src/squad/squad-scaffold.js +177 -0
- package/src/squad/state-manager.js +310 -0
- package/src/squad/task-decomposer.js +652 -0
- package/src/squad/verify-gate.js +303 -0
- package/src/tool-executor.js +94 -0
- package/src/updater.js +10 -3
- package/src/worker-runner.js +186 -1
- package/template/.aioson/agents/analyst.md +119 -3
- package/template/.aioson/agents/architect.md +98 -0
- package/template/.aioson/agents/design-hybrid-forge.md +141 -0
- package/template/.aioson/agents/dev.md +335 -14
- package/template/.aioson/agents/deyvin.md +117 -2
- package/template/.aioson/agents/discovery-design-doc.md +44 -0
- package/template/.aioson/agents/genome.md +14 -0
- package/template/.aioson/agents/neo.md +78 -1
- package/template/.aioson/agents/orache.md +50 -4
- package/template/.aioson/agents/orchestrator.md +197 -1
- package/template/.aioson/agents/pm.md +93 -0
- package/template/.aioson/agents/product.md +77 -4
- package/template/.aioson/agents/profiler-enricher.md +14 -0
- package/template/.aioson/agents/profiler-forge.md +14 -0
- package/template/.aioson/agents/profiler-researcher.md +14 -0
- package/template/.aioson/agents/qa.md +249 -19
- package/template/.aioson/agents/setup.md +144 -12
- package/template/.aioson/agents/sheldon.md +237 -11
- package/template/.aioson/agents/site-forge.md +1753 -0
- package/template/.aioson/agents/squad.md +162 -0
- package/template/.aioson/agents/tester.md +209 -0
- package/template/.aioson/agents/ux-ui.md +34 -1
- package/template/.aioson/brains/README.md +128 -0
- package/template/.aioson/brains/_index.json +16 -0
- package/template/.aioson/brains/scripts/query.js +103 -0
- package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
- package/template/.aioson/config.md +158 -13
- package/template/.aioson/constitution.md +33 -0
- package/template/.aioson/context/forensics/.gitkeep +0 -0
- package/template/.aioson/context/project-pulse.md +34 -0
- package/template/.aioson/context/seeds/seed-example.md +27 -0
- package/template/.aioson/context/user-profile.md +42 -0
- package/template/.aioson/docs/LAYERS.md +79 -0
- package/template/.aioson/docs/README.md +76 -0
- package/template/.aioson/docs/example-external-api-context.md +72 -0
- package/template/.aioson/locales/en/agents/architect.md +17 -0
- package/template/.aioson/locales/en/agents/dev.md +79 -13
- package/template/.aioson/locales/en/agents/orache.md +6 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
- package/template/.aioson/locales/en/agents/product.md +50 -0
- package/template/.aioson/locales/en/agents/setup.md +33 -1
- package/template/.aioson/locales/en/agents/sheldon.md +115 -0
- package/template/.aioson/locales/en/agents/squad.md +14 -0
- package/template/.aioson/locales/en/agents/tester.md +6 -0
- package/template/.aioson/locales/es/agents/analyst.md +2 -0
- package/template/.aioson/locales/es/agents/architect.md +19 -0
- package/template/.aioson/locales/es/agents/dev.md +64 -4
- package/template/.aioson/locales/es/agents/deyvin.md +2 -0
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/es/agents/genome.md +2 -0
- package/template/.aioson/locales/es/agents/neo.md +2 -0
- package/template/.aioson/locales/es/agents/orache.md +2 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/es/agents/pair.md +2 -0
- package/template/.aioson/locales/es/agents/pm.md +2 -0
- package/template/.aioson/locales/es/agents/product.md +52 -0
- package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/es/agents/qa.md +2 -0
- package/template/.aioson/locales/es/agents/setup.md +35 -1
- package/template/.aioson/locales/es/agents/sheldon.md +117 -0
- package/template/.aioson/locales/es/agents/squad.md +16 -0
- package/template/.aioson/locales/es/agents/tester.md +9 -0
- package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/fr/agents/analyst.md +2 -0
- package/template/.aioson/locales/fr/agents/architect.md +19 -0
- package/template/.aioson/locales/fr/agents/dev.md +64 -4
- package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/fr/agents/genome.md +2 -0
- package/template/.aioson/locales/fr/agents/neo.md +2 -0
- package/template/.aioson/locales/fr/agents/orache.md +2 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/fr/agents/pair.md +2 -0
- package/template/.aioson/locales/fr/agents/pm.md +2 -0
- package/template/.aioson/locales/fr/agents/product.md +52 -0
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/fr/agents/qa.md +2 -0
- package/template/.aioson/locales/fr/agents/setup.md +35 -1
- package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
- package/template/.aioson/locales/fr/agents/squad.md +16 -0
- package/template/.aioson/locales/fr/agents/tester.md +9 -0
- package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
- package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
- package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
- package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
- package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
- package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +134 -19
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
- package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
- package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
- package/template/.aioson/rules/README.md +69 -0
- package/template/.aioson/rules/data-format-convention.md +136 -0
- package/template/.aioson/rules/example-monetary-values.md +30 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
- package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
- package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
- package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
- package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
- package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +46 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
- package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
- package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
- package/template/.aioson/skills/static/context-budget-guide.md +46 -0
- package/template/.aioson/skills/static/harness-sensors.md +74 -0
- package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
- package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
- package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
- package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
- package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
- package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
- package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
- package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
- package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
- package/template/.aioson/skills/static/threejs-patterns.md +929 -0
- package/template/.aioson/skills/static/web-research-cache.md +112 -0
- package/template/.aioson/tasks/implementation-plan.md +21 -1
- package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/orache.md +5 -0
- package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
- package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
- package/template/AGENTS.md +75 -1
- package/template/CLAUDE.md +31 -0
- package/template/OPENCODE.md +4 -0
- package/template/researchs/.gitkeep +0 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson hooks:install [projectDir] --agent=<name> --tool=<claude|antigravity|codex|all>
|
|
5
|
+
*
|
|
6
|
+
* Installs AIOSON event hooks into the AI tool's settings file.
|
|
7
|
+
* After installation, every Write/Edit/Bash tool call and session stop
|
|
8
|
+
* automatically emits a runtime event to SQLite — no manual aioson calls needed.
|
|
9
|
+
*
|
|
10
|
+
* Supported tools:
|
|
11
|
+
* --tool=claude → ~/.claude/settings.json
|
|
12
|
+
* --tool=antigravity → ~/.gemini/antigravity/hooks.json (+ .agents/hooks.json in project)
|
|
13
|
+
* --tool=codex → ~/.codex/config.yaml (limited: no hook system, documents workaround)
|
|
14
|
+
* --tool=all → installs for all detected tools
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const path = require('node:path');
|
|
18
|
+
const fs = require('node:fs/promises');
|
|
19
|
+
const os = require('node:os');
|
|
20
|
+
|
|
21
|
+
const HOME = os.homedir();
|
|
22
|
+
|
|
23
|
+
// ─── Config file paths ────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const CONFIG_PATHS = {
|
|
26
|
+
claude: path.join(HOME, '.claude', 'settings.json'),
|
|
27
|
+
antigravity: path.join(HOME, '.gemini', 'antigravity', 'hooks.json'),
|
|
28
|
+
antigravity_workspace: '.agents/hooks.json' // relative to project
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ─── Hook command templates ───────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
function makeEmitCommand(agentName, source) {
|
|
34
|
+
// $PWD is the project directory at hook execution time
|
|
35
|
+
return `aioson hooks:emit "$PWD" --agent=${agentName} --source=${source} 2>/dev/null || true`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function makeDoneCommand(agentName) {
|
|
39
|
+
return `aioson agent:done "$PWD" --agent=${agentName} --summary="Session ended via ${agentName} hook" 2>/dev/null || true`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Claude Code ─────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
function buildClaudeHooks(agentName) {
|
|
45
|
+
const emitCmd = makeEmitCommand(agentName, 'claude');
|
|
46
|
+
const doneCmd = makeDoneCommand(agentName);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
PostToolUse: [
|
|
50
|
+
{
|
|
51
|
+
matcher: 'Write|Edit|MultiEdit',
|
|
52
|
+
hooks: [{ type: 'command', command: emitCmd }]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
matcher: 'Bash',
|
|
56
|
+
hooks: [{ type: 'command', command: emitCmd }]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
matcher: 'Task|TodoWrite',
|
|
60
|
+
hooks: [{ type: 'command', command: emitCmd }]
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
Stop: [
|
|
64
|
+
{
|
|
65
|
+
hooks: [{ type: 'command', command: doneCmd }]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function installClaudeHooks(agentName, dryRun, logger) {
|
|
72
|
+
const configPath = CONFIG_PATHS.claude;
|
|
73
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
74
|
+
|
|
75
|
+
let existing = {};
|
|
76
|
+
try {
|
|
77
|
+
existing = JSON.parse(await fs.readFile(configPath, 'utf8'));
|
|
78
|
+
} catch { /* file doesn't exist yet */ }
|
|
79
|
+
|
|
80
|
+
const newHooks = buildClaudeHooks(agentName);
|
|
81
|
+
|
|
82
|
+
// Merge: add AIOSON hooks without removing existing ones
|
|
83
|
+
const merged = { ...existing };
|
|
84
|
+
if (!merged.hooks) merged.hooks = {};
|
|
85
|
+
|
|
86
|
+
for (const [event, hookList] of Object.entries(newHooks)) {
|
|
87
|
+
if (!merged.hooks[event]) {
|
|
88
|
+
merged.hooks[event] = hookList;
|
|
89
|
+
} else {
|
|
90
|
+
// Remove any existing AIOSON hooks (to avoid duplicates on reinstall)
|
|
91
|
+
const filtered = merged.hooks[event].filter((entry) => {
|
|
92
|
+
const cmd = entry.hooks?.[0]?.command || '';
|
|
93
|
+
return !cmd.includes('aioson hooks:emit') && !cmd.includes('aioson agent:done');
|
|
94
|
+
});
|
|
95
|
+
merged.hooks[event] = [...filtered, ...hookList];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!dryRun) {
|
|
100
|
+
await fs.writeFile(configPath, JSON.stringify(merged, null, 2), 'utf8');
|
|
101
|
+
logger.log(` ✓ Claude Code — ${configPath}`);
|
|
102
|
+
} else {
|
|
103
|
+
logger.log(` [dry-run] Would write: ${configPath}`);
|
|
104
|
+
logger.log(` Hooks to add:`);
|
|
105
|
+
logger.log(` PostToolUse (Write|Edit|MultiEdit|Bash|Task|TodoWrite) → hooks:emit`);
|
|
106
|
+
logger.log(` Stop → agent:done`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { tool: 'claude', configPath, hooks: newHooks };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ─── Antigravity ─────────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
function buildAntigravityHooks(agentName) {
|
|
115
|
+
const emitCmd = makeEmitCommand(agentName, 'antigravity');
|
|
116
|
+
const doneCmd = makeDoneCommand(agentName);
|
|
117
|
+
const startCmd = `aioson live:start "$PWD" --agent=${agentName} --tool=antigravity --no-launch 2>/dev/null || true`;
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
SessionStart: [{ type: 'command', command: startCmd }],
|
|
121
|
+
PostToolUse: [
|
|
122
|
+
{ matcher: 'Write|Edit|MultiEdit', hooks: [{ type: 'command', command: emitCmd }] },
|
|
123
|
+
{ matcher: 'Bash', hooks: [{ type: 'command', command: emitCmd }] },
|
|
124
|
+
{ matcher: 'Task|TodoWrite', hooks: [{ type: 'command', command: emitCmd }] }
|
|
125
|
+
],
|
|
126
|
+
SessionEnd: [{ type: 'command', command: doneCmd }],
|
|
127
|
+
Stop: [{ type: 'command', command: doneCmd }]
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function installAntigravityHooks(agentName, projectDir, dryRun, logger) {
|
|
132
|
+
const globalPath = CONFIG_PATHS.antigravity;
|
|
133
|
+
const workspacePath = path.join(projectDir, CONFIG_PATHS.antigravity_workspace);
|
|
134
|
+
|
|
135
|
+
const hooks = buildAntigravityHooks(agentName);
|
|
136
|
+
|
|
137
|
+
if (!dryRun) {
|
|
138
|
+
await fs.mkdir(path.dirname(globalPath), { recursive: true });
|
|
139
|
+
await fs.mkdir(path.dirname(workspacePath), { recursive: true });
|
|
140
|
+
|
|
141
|
+
// Global hooks
|
|
142
|
+
let globalExisting = {};
|
|
143
|
+
try { globalExisting = JSON.parse(await fs.readFile(globalPath, 'utf8')); } catch { /* new file */ }
|
|
144
|
+
const mergedGlobal = mergeAntigravityHooks(globalExisting, hooks);
|
|
145
|
+
await fs.writeFile(globalPath, JSON.stringify(mergedGlobal, null, 2), 'utf8');
|
|
146
|
+
logger.log(` ✓ Antigravity global — ${globalPath}`);
|
|
147
|
+
|
|
148
|
+
// Workspace hooks (project-scoped, takes priority)
|
|
149
|
+
let wsExisting = {};
|
|
150
|
+
try { wsExisting = JSON.parse(await fs.readFile(workspacePath, 'utf8')); } catch { /* new file */ }
|
|
151
|
+
const mergedWs = mergeAntigravityHooks(wsExisting, hooks);
|
|
152
|
+
await fs.writeFile(workspacePath, JSON.stringify(mergedWs, null, 2), 'utf8');
|
|
153
|
+
logger.log(` ✓ Antigravity workspace — ${workspacePath}`);
|
|
154
|
+
} else {
|
|
155
|
+
logger.log(` [dry-run] Would write: ${globalPath}`);
|
|
156
|
+
logger.log(` [dry-run] Would write: ${workspacePath}`);
|
|
157
|
+
logger.log(` Hooks to add: SessionStart → live:start, PostToolUse → hooks:emit, SessionEnd/Stop → agent:done`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { tool: 'antigravity', globalPath, workspacePath, hooks };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function mergeAntigravityHooks(existing, newHooks) {
|
|
164
|
+
const merged = { ...existing };
|
|
165
|
+
if (!merged.hooks) merged.hooks = {};
|
|
166
|
+
|
|
167
|
+
for (const [event, entries] of Object.entries(newHooks)) {
|
|
168
|
+
const existingEntries = Array.isArray(merged.hooks[event]) ? merged.hooks[event] : [];
|
|
169
|
+
// Remove previous AIOSON entries
|
|
170
|
+
const filtered = existingEntries.filter((e) => {
|
|
171
|
+
const cmd = (e.command || e.hooks?.[0]?.command || '');
|
|
172
|
+
return !cmd.includes('aioson');
|
|
173
|
+
});
|
|
174
|
+
const newEntries = Array.isArray(entries) ? entries : [entries];
|
|
175
|
+
merged.hooks[event] = [...filtered, ...newEntries];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return merged;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ─── Codex (OpenAI) ───────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
async function installCodexHooks(agentName, dryRun, logger) {
|
|
184
|
+
// Codex CLI does not have a native hook system as of 2026.
|
|
185
|
+
// The workaround: add a shell alias that wraps `codex` and calls live:start before / agent:done after.
|
|
186
|
+
const configPath = path.join(HOME, '.codex', 'config.yaml');
|
|
187
|
+
const wrapperPath = path.join(HOME, '.codex', 'aioson-wrapper.sh');
|
|
188
|
+
|
|
189
|
+
const wrapperScript = `#!/bin/bash
|
|
190
|
+
# AIOSON session wrapper for Codex CLI
|
|
191
|
+
# Generated by: aioson hooks:install --tool=codex --agent=${agentName}
|
|
192
|
+
# Usage: replace \`codex\` calls with \`codex-aioson\` OR add to .bashrc:
|
|
193
|
+
# alias codex='${wrapperPath}'
|
|
194
|
+
|
|
195
|
+
PROJECT_DIR="\${1:-$PWD}"
|
|
196
|
+
AGENT="${agentName}"
|
|
197
|
+
|
|
198
|
+
# Start live session before Codex runs
|
|
199
|
+
aioson live:start "$PROJECT_DIR" --agent="$AGENT" --tool=codex --no-launch 2>/dev/null || true
|
|
200
|
+
|
|
201
|
+
# Run Codex with all original arguments
|
|
202
|
+
codex-bin "$@"
|
|
203
|
+
EXIT_CODE=$?
|
|
204
|
+
|
|
205
|
+
# Register session end
|
|
206
|
+
aioson agent:done "$PROJECT_DIR" --agent="$AGENT" --summary="Codex session ended" 2>/dev/null || true
|
|
207
|
+
|
|
208
|
+
exit $EXIT_CODE
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
if (!dryRun) {
|
|
212
|
+
await fs.mkdir(path.dirname(wrapperPath), { recursive: true });
|
|
213
|
+
await fs.writeFile(wrapperPath, wrapperScript, 'utf8');
|
|
214
|
+
await fs.chmod(wrapperPath, 0o755);
|
|
215
|
+
logger.log(` ✓ Codex wrapper — ${wrapperPath}`);
|
|
216
|
+
logger.log(` ⚠ Codex has no native hooks. Add this to ~/.bashrc:`);
|
|
217
|
+
logger.log(` alias codex='${wrapperPath}'`);
|
|
218
|
+
logger.log(` Or rename: mv $(which codex) $(which codex)-bin`);
|
|
219
|
+
} else {
|
|
220
|
+
logger.log(` [dry-run] Would write: ${wrapperPath}`);
|
|
221
|
+
logger.log(` ⚠ Codex has no native hook system. Wrapper script approach only.`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return { tool: 'codex', wrapperPath, limited: true };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ─── Detection ───────────────────────────────────────────────────────────────
|
|
228
|
+
|
|
229
|
+
async function detectInstalledTools() {
|
|
230
|
+
const detected = [];
|
|
231
|
+
const checks = [
|
|
232
|
+
{ tool: 'claude', path: path.join(HOME, '.claude') },
|
|
233
|
+
{ tool: 'antigravity', path: path.join(HOME, '.gemini', 'antigravity') },
|
|
234
|
+
{ tool: 'codex', path: path.join(HOME, '.codex') }
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
for (const { tool, path: p } of checks) {
|
|
238
|
+
try {
|
|
239
|
+
await fs.access(p);
|
|
240
|
+
detected.push(tool);
|
|
241
|
+
} catch { /* not installed */ }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return detected;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
async function runHooksInstall({ args, options = {}, logger }) {
|
|
250
|
+
const projectDir = path.resolve(process.cwd(), args[0] || '.');
|
|
251
|
+
const agentName = options.agent ? String(options.agent).replace(/^@/, '') : 'dev';
|
|
252
|
+
const dryRun = options['dry-run'] || options.dryRun || false;
|
|
253
|
+
let tool = options.tool ? String(options.tool).trim().toLowerCase() : 'all';
|
|
254
|
+
|
|
255
|
+
if (tool === 'all') {
|
|
256
|
+
const detected = await detectInstalledTools();
|
|
257
|
+
if (detected.length === 0) {
|
|
258
|
+
logger.log('No supported AI tools detected. Install Claude Code, Antigravity, or Codex first.');
|
|
259
|
+
return { ok: false, reason: 'no_tools_detected' };
|
|
260
|
+
}
|
|
261
|
+
logger.log(`Detected tools: ${detected.join(', ')}`);
|
|
262
|
+
tool = detected.join(',');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const tools = tool.split(',').map((t) => t.trim()).filter(Boolean);
|
|
266
|
+
const results = [];
|
|
267
|
+
|
|
268
|
+
logger.log(`Hooks Install — agent: @${agentName}${dryRun ? ' [dry-run]' : ''}`);
|
|
269
|
+
logger.log('─'.repeat(50));
|
|
270
|
+
|
|
271
|
+
for (const t of tools) {
|
|
272
|
+
try {
|
|
273
|
+
if (t === 'claude') {
|
|
274
|
+
results.push(await installClaudeHooks(agentName, dryRun, logger));
|
|
275
|
+
} else if (t === 'antigravity') {
|
|
276
|
+
results.push(await installAntigravityHooks(agentName, projectDir, dryRun, logger));
|
|
277
|
+
} else if (t === 'codex') {
|
|
278
|
+
results.push(await installCodexHooks(agentName, dryRun, logger));
|
|
279
|
+
} else {
|
|
280
|
+
logger.log(` ⚠ Unknown tool: ${t} — supported: claude, antigravity, codex`);
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
logger.log(` ✗ ${t}: ${err.message}`);
|
|
284
|
+
results.push({ tool: t, error: err.message });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
logger.log('─'.repeat(50));
|
|
289
|
+
|
|
290
|
+
if (!dryRun) {
|
|
291
|
+
logger.log('');
|
|
292
|
+
logger.log('Hooks installed. From now on:');
|
|
293
|
+
logger.log(' • Every file write/edit → logged as artifact event');
|
|
294
|
+
logger.log(' • Every bash command → logged as step_done event');
|
|
295
|
+
logger.log(' • Session end → logged as agent:done');
|
|
296
|
+
logger.log('');
|
|
297
|
+
logger.log('To verify: aioson live:status . --agent=' + agentName);
|
|
298
|
+
logger.log('To uninstall: aioson hooks:uninstall --tool=' + tools.join(','));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (options.json) {
|
|
302
|
+
return { ok: true, results, agentName, dryRun };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return { ok: true, results, agentName, dryRun };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function runHooksUninstall({ args, options = {}, logger }) {
|
|
309
|
+
const agentName = options.agent ? String(options.agent).replace(/^@/, '') : 'dev';
|
|
310
|
+
const dryRun = options['dry-run'] || options.dryRun || false;
|
|
311
|
+
const tool = options.tool ? String(options.tool).trim().toLowerCase() : 'claude';
|
|
312
|
+
const tools = tool.split(',').map((t) => t.trim()).filter(Boolean);
|
|
313
|
+
|
|
314
|
+
logger.log(`Hooks Uninstall — agent: @${agentName}${dryRun ? ' [dry-run]' : ''}`);
|
|
315
|
+
logger.log('─'.repeat(50));
|
|
316
|
+
|
|
317
|
+
for (const t of tools) {
|
|
318
|
+
if (t === 'claude') {
|
|
319
|
+
try {
|
|
320
|
+
const configPath = CONFIG_PATHS.claude;
|
|
321
|
+
const existing = JSON.parse(await fs.readFile(configPath, 'utf8'));
|
|
322
|
+
if (existing.hooks) {
|
|
323
|
+
for (const event of Object.keys(existing.hooks)) {
|
|
324
|
+
existing.hooks[event] = (existing.hooks[event] || []).filter((entry) => {
|
|
325
|
+
const cmd = entry.hooks?.[0]?.command || entry.command || '';
|
|
326
|
+
return !cmd.includes('aioson hooks:emit') && !cmd.includes('aioson agent:done') && !cmd.includes('aioson live:start');
|
|
327
|
+
});
|
|
328
|
+
if (existing.hooks[event].length === 0) delete existing.hooks[event];
|
|
329
|
+
}
|
|
330
|
+
if (Object.keys(existing.hooks).length === 0) delete existing.hooks;
|
|
331
|
+
}
|
|
332
|
+
if (!dryRun) {
|
|
333
|
+
await fs.writeFile(configPath, JSON.stringify(existing, null, 2), 'utf8');
|
|
334
|
+
logger.log(` ✓ Claude Code hooks removed — ${configPath}`);
|
|
335
|
+
} else {
|
|
336
|
+
logger.log(` [dry-run] Would remove AIOSON hooks from: ${configPath}`);
|
|
337
|
+
}
|
|
338
|
+
} catch {
|
|
339
|
+
logger.log(` Claude Code settings not found — nothing to remove`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return { ok: true };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = { runHooksInstall, runHooksUninstall };
|
package/src/commands/init.js
CHANGED
|
@@ -5,6 +5,17 @@ const path = require('node:path');
|
|
|
5
5
|
const { installTemplate } = require('../installer');
|
|
6
6
|
const { applyAgentLocale } = require('../locales');
|
|
7
7
|
const { resolvePromptTool } = require('../prompt-tool');
|
|
8
|
+
const { runInstallWizard } = require('../install-wizard');
|
|
9
|
+
const { renderRevealAnimation, renderInstallSummary, renderProgress } = require('../install-animation');
|
|
10
|
+
const { getCliVersion } = require('../version');
|
|
11
|
+
|
|
12
|
+
// Complete profile used when --all is passed (skip wizard, install everything)
|
|
13
|
+
const ALL_PROFILE = {
|
|
14
|
+
tools: ['claude', 'codex', 'gemini', 'opencode'],
|
|
15
|
+
uses: ['development', 'squads'],
|
|
16
|
+
design: 'all',
|
|
17
|
+
locale: 'en'
|
|
18
|
+
};
|
|
8
19
|
|
|
9
20
|
async function directoryIsEmpty(dirPath) {
|
|
10
21
|
try {
|
|
@@ -25,6 +36,8 @@ async function runInit({ args, options, logger, t }) {
|
|
|
25
36
|
const targetDir = path.resolve(process.cwd(), projectName);
|
|
26
37
|
const force = Boolean(options.force);
|
|
27
38
|
const dryRun = Boolean(options['dry-run']);
|
|
39
|
+
const noInteractive = Boolean(options['no-interactive']);
|
|
40
|
+
const installAll = Boolean(options.all);
|
|
28
41
|
const requestedLanguage = options.lang || options.language;
|
|
29
42
|
const promptTool = resolvePromptTool(options.tool);
|
|
30
43
|
|
|
@@ -34,15 +47,33 @@ async function runInit({ args, options, logger, t }) {
|
|
|
34
47
|
throw new Error(t('init.non_empty_dir', { targetDir }));
|
|
35
48
|
}
|
|
36
49
|
|
|
50
|
+
// Run wizard for new projects (TTY only) — unless --all skips it
|
|
51
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
52
|
+
let installProfile = null;
|
|
53
|
+
|
|
54
|
+
if (installAll) {
|
|
55
|
+
// --all: skip wizard, install complete
|
|
56
|
+
installProfile = ALL_PROFILE;
|
|
57
|
+
if (isTTY && !dryRun) {
|
|
58
|
+
logger.log(t('init_all.installing_full', { projectName }));
|
|
59
|
+
}
|
|
60
|
+
} else if (!noInteractive && !dryRun && isTTY) {
|
|
61
|
+
installProfile = await runInstallWizard({ noInteractive, t });
|
|
62
|
+
// null = user cancelled → fall back to full install
|
|
63
|
+
}
|
|
64
|
+
|
|
37
65
|
const result = await installTemplate(targetDir, {
|
|
38
66
|
overwrite: true,
|
|
39
67
|
dryRun,
|
|
40
|
-
mode: 'init'
|
|
68
|
+
mode: 'init',
|
|
69
|
+
installProfile,
|
|
70
|
+
onProgress: isTTY && !dryRun ? renderProgress : null
|
|
41
71
|
});
|
|
42
72
|
|
|
73
|
+
const effectiveLocale = requestedLanguage || (installProfile && installProfile.locale) || null;
|
|
43
74
|
let localeApply = null;
|
|
44
|
-
if (
|
|
45
|
-
localeApply = await applyAgentLocale(targetDir,
|
|
75
|
+
if (effectiveLocale) {
|
|
76
|
+
localeApply = await applyAgentLocale(targetDir, effectiveLocale, { dryRun });
|
|
46
77
|
if (dryRun) {
|
|
47
78
|
logger.log(t('locale_apply.dry_run_applied', { locale: localeApply.locale }));
|
|
48
79
|
} else {
|
|
@@ -50,22 +81,32 @@ async function runInit({ args, options, logger, t }) {
|
|
|
50
81
|
}
|
|
51
82
|
}
|
|
52
83
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
84
|
+
// Reveal animation + summary (TTY only, not dry-run)
|
|
85
|
+
if (isTTY && !dryRun) {
|
|
86
|
+
const version = await getCliVersion();
|
|
87
|
+
await renderRevealAnimation(version);
|
|
88
|
+
renderInstallSummary({ result, installProfile });
|
|
89
|
+
logger.log('');
|
|
90
|
+
logger.log(t('init.step_cd', { projectName }));
|
|
91
|
+
} else {
|
|
92
|
+
logger.log(t('init.created_at', { targetDir }));
|
|
93
|
+
logger.log(t('init.files_copied', { count: result.copied.length }));
|
|
94
|
+
if (result.skipped.length > 0) {
|
|
95
|
+
logger.log(t('init.files_skipped', { count: result.skipped.length }));
|
|
96
|
+
}
|
|
97
|
+
logger.log(t('init.next_steps'));
|
|
98
|
+
logger.log(t('init.step_cd', { projectName }));
|
|
99
|
+
logger.log(t('init.step_setup'));
|
|
100
|
+
logger.log(t('init.step_agents'));
|
|
101
|
+
logger.log(t('init.step_agent_prompt', { tool: promptTool }));
|
|
57
102
|
}
|
|
58
|
-
logger.log(t('init.next_steps'));
|
|
59
|
-
logger.log(t('init.step_cd', { projectName }));
|
|
60
|
-
logger.log(t('init.step_setup'));
|
|
61
|
-
logger.log(t('init.step_agents'));
|
|
62
|
-
logger.log(t('init.step_agent_prompt', { tool: promptTool }));
|
|
63
103
|
|
|
64
104
|
return {
|
|
65
105
|
ok: true,
|
|
66
106
|
targetDir,
|
|
67
107
|
...result,
|
|
68
|
-
localeApply
|
|
108
|
+
localeApply,
|
|
109
|
+
installProfile
|
|
69
110
|
};
|
|
70
111
|
}
|
|
71
112
|
|
package/src/commands/install.js
CHANGED
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const { detectFramework } = require('../detector');
|
|
5
|
-
const { installTemplate } = require('../installer');
|
|
5
|
+
const { installTemplate, readInstallProfile } = require('../installer');
|
|
6
6
|
const { applyAgentLocale } = require('../locales');
|
|
7
7
|
const { resolvePromptTool } = require('../prompt-tool');
|
|
8
|
+
const { runInstallWizard } = require('../install-wizard');
|
|
9
|
+
const { renderRevealAnimation, renderInstallSummary, renderProgress } = require('../install-animation');
|
|
10
|
+
const { getCliVersion } = require('../version');
|
|
8
11
|
|
|
9
12
|
async function runInstall({ args, options, logger, t }) {
|
|
10
13
|
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
11
14
|
const force = Boolean(options.force);
|
|
12
15
|
const dryRun = Boolean(options['dry-run']);
|
|
16
|
+
const noInteractive = Boolean(options['no-interactive']);
|
|
17
|
+
const reconfigure = Boolean(options.reconfigure);
|
|
13
18
|
const requestedLanguage = options.lang || options.language;
|
|
14
19
|
const promptTool = resolvePromptTool(options.tool);
|
|
15
20
|
|
|
@@ -23,16 +28,42 @@ async function runInstall({ args, options, logger, t }) {
|
|
|
23
28
|
logger.log(t('install.framework_not_detected'));
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
// Decide install profile
|
|
32
|
+
let installProfile = null;
|
|
33
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
34
|
+
|
|
35
|
+
if (!noInteractive && isTTY && !dryRun) {
|
|
36
|
+
const existingProfile = await readInstallProfile(targetDir);
|
|
37
|
+
if (!existingProfile || reconfigure) {
|
|
38
|
+
installProfile = await runInstallWizard({
|
|
39
|
+
noInteractive,
|
|
40
|
+
existingProfile: reconfigure ? existingProfile : null,
|
|
41
|
+
t
|
|
42
|
+
});
|
|
43
|
+
// null = user cancelled → fall back to full install
|
|
44
|
+
} else {
|
|
45
|
+
installProfile = existingProfile;
|
|
46
|
+
logger.log(t('install.using_saved_profile'));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// When reconfigure, we need overwrite=true so changed profile is reflected
|
|
51
|
+
const overwrite = force || reconfigure;
|
|
52
|
+
|
|
26
53
|
const result = await installTemplate(targetDir, {
|
|
27
|
-
overwrite
|
|
54
|
+
overwrite,
|
|
28
55
|
dryRun,
|
|
29
56
|
mode: 'install',
|
|
30
|
-
frameworkDetection: detection.framework
|
|
57
|
+
frameworkDetection: detection.framework,
|
|
58
|
+
installProfile,
|
|
59
|
+
onProgress: isTTY && !dryRun ? renderProgress : null
|
|
31
60
|
});
|
|
32
61
|
|
|
62
|
+
// Locale: explicit --lang flag wins over profile, profile wins over nothing
|
|
63
|
+
const effectiveLocale = requestedLanguage || (installProfile && installProfile.locale) || null;
|
|
33
64
|
let localeApply = null;
|
|
34
|
-
if (
|
|
35
|
-
localeApply = await applyAgentLocale(targetDir,
|
|
65
|
+
if (effectiveLocale) {
|
|
66
|
+
localeApply = await applyAgentLocale(targetDir, effectiveLocale, { dryRun });
|
|
36
67
|
if (dryRun) {
|
|
37
68
|
logger.log(t('locale_apply.dry_run_applied', { locale: localeApply.locale }));
|
|
38
69
|
} else {
|
|
@@ -40,13 +71,20 @@ async function runInstall({ args, options, logger, t }) {
|
|
|
40
71
|
}
|
|
41
72
|
}
|
|
42
73
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
74
|
+
// Reveal animation + summary (TTY only, not dry-run)
|
|
75
|
+
if (isTTY && !dryRun) {
|
|
76
|
+
const version = await getCliVersion();
|
|
77
|
+
await renderRevealAnimation(version);
|
|
78
|
+
renderInstallSummary({ result, installProfile });
|
|
79
|
+
} else {
|
|
80
|
+
logger.log(t('install.done_at', { targetDir }));
|
|
81
|
+
logger.log(t('install.files_copied', { count: result.copied.length }));
|
|
82
|
+
logger.log(t('install.files_skipped', { count: result.skipped.length }));
|
|
83
|
+
logger.log(t('install.next_steps'));
|
|
84
|
+
logger.log(t('install.step_setup_context'));
|
|
85
|
+
logger.log(t('install.step_agents'));
|
|
86
|
+
logger.log(t('install.step_agent_prompt', { tool: promptTool }));
|
|
87
|
+
}
|
|
50
88
|
|
|
51
89
|
if (result.isExistingProject) {
|
|
52
90
|
logger.log('');
|
|
@@ -59,7 +97,8 @@ async function runInstall({ args, options, logger, t }) {
|
|
|
59
97
|
targetDir,
|
|
60
98
|
detection,
|
|
61
99
|
...result,
|
|
62
|
-
localeApply
|
|
100
|
+
localeApply,
|
|
101
|
+
installProfile
|
|
63
102
|
};
|
|
64
103
|
}
|
|
65
104
|
|