@kal-elsam/kairo-runtime 0.1.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/README.md +937 -0
- package/bin/harness.js +11 -0
- package/bin/kairo-runtime.js +11 -0
- package/bin/kairo.js +11 -0
- package/global-template/components/catalog.json +25 -0
- package/global-template/components/orchestrator/orchestrator.md +55 -0
- package/global-template/components/sdd-core/handoff.md +38 -0
- package/global-template/components/sdd-core/spec-sizing.md +38 -0
- package/global-template/components/sdd-core/workflow.md +31 -0
- package/global-template/core/orchestrator.md +55 -0
- package/package.json +64 -0
- package/prompts/HARNESS_ENFORCEMENT_UPGRADE.md +11 -0
- package/prompts/HARNESS_ENTERPRISE.md +33 -0
- package/prompts/HARNESS_INSTALLER_MASTER.md +853 -0
- package/prompts/HARNESS_MINIMAL.md +30 -0
- package/prompts/HARNESS_SPEC_SIZING_UPGRADE.md +41 -0
- package/prompts/HARNESS_STANDARD.md +35 -0
- package/prompts/HARNESS_UNIVERSAL_PARITY.md +56 -0
- package/repo-template/.claude/agents/adapter-parity-reviewer.md +17 -0
- package/repo-template/.claude/agents/architect.md +17 -0
- package/repo-template/.claude/agents/eval-engineer.md +17 -0
- package/repo-template/.claude/agents/reviewer.md +17 -0
- package/repo-template/.claude/agents/sdd-reviewer.md +17 -0
- package/repo-template/.claude/agents/sdd-spec-writer.md +17 -0
- package/repo-template/.claude/skills/checkpoint/SKILL.md +13 -0
- package/repo-template/.claude/skills/eval-design/SKILL.md +3 -0
- package/repo-template/.claude/skills/evals/SKILL.md +13 -0
- package/repo-template/.claude/skills/loop-engineering/SKILL.md +16 -0
- package/repo-template/.claude/skills/maintainability-review/SKILL.md +3 -0
- package/repo-template/.claude/skills/quality-gate-review/SKILL.md +3 -0
- package/repo-template/.claude/skills/sdd/SKILL.md +13 -0
- package/repo-template/.claude/skills/spec-complexity-classifier/SKILL.md +10 -0
- package/repo-template/.claude/skills/spec-escalation-review/SKILL.md +10 -0
- package/repo-template/.claude/skills/spec-intake/SKILL.md +10 -0
- package/repo-template/.claude/skills/tdd/SKILL.md +13 -0
- package/repo-template/.claude/skills/trust-review/SKILL.md +3 -0
- package/repo-template/.codex/skills/adapter-parity/SKILL.md +29 -0
- package/repo-template/.codex/skills/checkpoint/SKILL.md +36 -0
- package/repo-template/.codex/skills/eval-design/SKILL.md +3 -0
- package/repo-template/.codex/skills/evals/SKILL.md +28 -0
- package/repo-template/.codex/skills/loop-engineering/SKILL.md +24 -0
- package/repo-template/.codex/skills/maintainability-review/SKILL.md +3 -0
- package/repo-template/.codex/skills/quality-gate-review/SKILL.md +3 -0
- package/repo-template/.codex/skills/sdd/SKILL.md +30 -0
- package/repo-template/.codex/skills/spec-complexity-classifier/SKILL.md +10 -0
- package/repo-template/.codex/skills/spec-escalation-review/SKILL.md +10 -0
- package/repo-template/.codex/skills/spec-intake/SKILL.md +10 -0
- package/repo-template/.codex/skills/tdd/SKILL.md +27 -0
- package/repo-template/.codex/skills/trust-review/SKILL.md +3 -0
- package/repo-template/.cursor/agents/adapter-parity-reviewer.md +29 -0
- package/repo-template/.cursor/agents/architect.md +27 -0
- package/repo-template/.cursor/agents/context-engineer.md +27 -0
- package/repo-template/.cursor/agents/debugger.md +27 -0
- package/repo-template/.cursor/agents/eval-engineer.md +27 -0
- package/repo-template/.cursor/agents/harness-orchestrator.md +27 -0
- package/repo-template/.cursor/agents/loop-controller.md +17 -0
- package/repo-template/.cursor/agents/loop-debugger.md +16 -0
- package/repo-template/.cursor/agents/reviewer.md +27 -0
- package/repo-template/.cursor/agents/sdd/sdd-acceptance-reviewer.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-implementation-guardian.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-intake-analyst.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-orchestrator.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-spec-reviewer.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-spec-writer.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-task-breakdown.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-technical-planner.md +31 -0
- package/repo-template/.cursor/agents/sdd/sdd-test-planner.md +31 -0
- package/repo-template/.cursor/agents/spec-intake-analyst.md +14 -0
- package/repo-template/.cursor/agents/test-engineer.md +27 -0
- package/repo-template/.cursor/commands/adapter-parity.md +34 -0
- package/repo-template/.cursor/commands/checkpoint.md +30 -0
- package/repo-template/.cursor/commands/debug.md +13 -0
- package/repo-template/.cursor/commands/init-eval.md +12 -0
- package/repo-template/.cursor/commands/init-feature.md +12 -0
- package/repo-template/.cursor/commands/init-harness.md +13 -0
- package/repo-template/.cursor/commands/loop-debug.md +3 -0
- package/repo-template/.cursor/commands/loop-review.md +3 -0
- package/repo-template/.cursor/commands/loop-run.md +5 -0
- package/repo-template/.cursor/commands/review.md +21 -0
- package/repo-template/.cursor/commands/sdd-intake.md +18 -0
- package/repo-template/.cursor/commands/sdd-plan.md +18 -0
- package/repo-template/.cursor/commands/sdd-spec.md +18 -0
- package/repo-template/.cursor/commands/sdd-tasks.md +18 -0
- package/repo-template/.cursor/commands/sdd-validate.md +18 -0
- package/repo-template/.cursor/commands/spec-escalate.md +9 -0
- package/repo-template/.cursor/commands/spec-intake.md +10 -0
- package/repo-template/.cursor/commands/spec-size.md +21 -0
- package/repo-template/.cursor/rules/adapter-parity.mdc +20 -0
- package/repo-template/.cursor/rules/api.mdc +12 -0
- package/repo-template/.cursor/rules/core.mdc +21 -0
- package/repo-template/.cursor/rules/enforcement.mdc +16 -0
- package/repo-template/.cursor/rules/evals.mdc +10 -0
- package/repo-template/.cursor/rules/git.mdc +19 -0
- package/repo-template/.cursor/rules/harness.mdc +14 -0
- package/repo-template/.cursor/rules/loops.mdc +17 -0
- package/repo-template/.cursor/rules/testing.mdc +13 -0
- package/repo-template/.cursor/rules/ui.mdc +13 -0
- package/repo-template/.cursor/skills/api-design/SKILL.md +23 -0
- package/repo-template/.cursor/skills/architecture/SKILL.md +23 -0
- package/repo-template/.cursor/skills/code-review/SKILL.md +23 -0
- package/repo-template/.cursor/skills/context-graph/SKILL.md +23 -0
- package/repo-template/.cursor/skills/debugging/SKILL.md +23 -0
- package/repo-template/.cursor/skills/evals/SKILL.md +23 -0
- package/repo-template/.cursor/skills/git-workflow/SKILL.md +23 -0
- package/repo-template/.cursor/skills/testing/SKILL.md +23 -0
- package/repo-template/.cursor/skills/ui-design/SKILL.md +23 -0
- package/repo-template/.gentle-ai/README.md +37 -0
- package/repo-template/.gentle-ai/loops/README.md +27 -0
- package/repo-template/.gentle-ai/loops/sdd-tdd-repair.loop.md +27 -0
- package/repo-template/.gentle-ai/model-routing.md +25 -0
- package/repo-template/.github/copilot-instructions.md +37 -0
- package/repo-template/.github/dependabot.yml +11 -0
- package/repo-template/.github/instructions/harness.instructions.md +11 -0
- package/repo-template/.github/workflows/harness-quality-gate.yml +67 -0
- package/repo-template/.github/workflows/harness-security-gate.yml +32 -0
- package/repo-template/.harness/spec-sizing.json +33 -0
- package/repo-template/.opencode/README.md +71 -0
- package/repo-template/.opencode/agents/adapter-parity-reviewer.md +23 -0
- package/repo-template/.opencode/agents/architect.md +38 -0
- package/repo-template/.opencode/agents/checkpoint-reviewer.md +38 -0
- package/repo-template/.opencode/agents/eval-engineer.md +38 -0
- package/repo-template/.opencode/agents/loop-controller.md +38 -0
- package/repo-template/.opencode/agents/loop-debugger.md +38 -0
- package/repo-template/.opencode/agents/model-router.md +38 -0
- package/repo-template/.opencode/agents/sdd-orchestrator.md +38 -0
- package/repo-template/.opencode/agents/sdd-spec-reviewer.md +38 -0
- package/repo-template/.opencode/agents/spec-intake-analyst.md +19 -0
- package/repo-template/.opencode/agents/tdd-engineer.md +38 -0
- package/repo-template/.opencode/commands/checkpoint.md +3 -0
- package/repo-template/.opencode/commands/eval-design.md +3 -0
- package/repo-template/.opencode/commands/maintainability-review.md +3 -0
- package/repo-template/.opencode/commands/quality-gate.md +3 -0
- package/repo-template/.opencode/commands/spec-escalate.md +9 -0
- package/repo-template/.opencode/commands/spec-intake.md +10 -0
- package/repo-template/.opencode/commands/spec-size.md +21 -0
- package/repo-template/.opencode/commands/trust-review.md +3 -0
- package/repo-template/.opencode/loops/ai-behavior-improvement.loop.md +15 -0
- package/repo-template/.opencode/loops/bug-repair.loop.md +16 -0
- package/repo-template/.opencode/loops/documentation-sync.loop.md +13 -0
- package/repo-template/.opencode/loops/feature-development.loop.md +25 -0
- package/repo-template/.opencode/skills/spec-complexity-classifier/SKILL.md +10 -0
- package/repo-template/.opencode/skills/spec-escalation-review/SKILL.md +10 -0
- package/repo-template/.opencode/skills/spec-intake/SKILL.md +10 -0
- package/repo-template/.pi/README.md +21 -0
- package/repo-template/.pi/prompts/checkpoint.md +11 -0
- package/repo-template/.pi/prompts/loop-run.md +10 -0
- package/repo-template/.pi/prompts/sdd-plan.md +11 -0
- package/repo-template/.pi/prompts/sdd-spec.md +13 -0
- package/repo-template/.pi/prompts/spec-escalate.md +9 -0
- package/repo-template/.pi/prompts/spec-intake.md +10 -0
- package/repo-template/.pi/prompts/spec-size.md +21 -0
- package/repo-template/.pi/skills/adapter-parity/SKILL.md +7 -0
- package/repo-template/.pi/skills/checkpoint/SKILL.md +7 -0
- package/repo-template/.pi/skills/eval-design/SKILL.md +3 -0
- package/repo-template/.pi/skills/evals/SKILL.md +7 -0
- package/repo-template/.pi/skills/loop-engineering/SKILL.md +7 -0
- package/repo-template/.pi/skills/maintainability-review/SKILL.md +3 -0
- package/repo-template/.pi/skills/quality-gate-review/SKILL.md +3 -0
- package/repo-template/.pi/skills/sdd/SKILL.md +7 -0
- package/repo-template/.pi/skills/spec-complexity-classifier/SKILL.md +10 -0
- package/repo-template/.pi/skills/spec-escalation-review/SKILL.md +10 -0
- package/repo-template/.pi/skills/spec-intake/SKILL.md +10 -0
- package/repo-template/.pi/skills/tdd/SKILL.md +7 -0
- package/repo-template/.pi/skills/trust-review/SKILL.md +3 -0
- package/repo-template/AGENT.md +8 -0
- package/repo-template/AGENTS.md +165 -0
- package/repo-template/CLAUDE.md +9 -0
- package/repo-template/GEMINI.md +9 -0
- package/repo-template/docs/ai/adapter-parity.md +135 -0
- package/repo-template/docs/ai/agent-workflow.md +45 -0
- package/repo-template/docs/ai/api.md +28 -0
- package/repo-template/docs/ai/architecture.md +53 -0
- package/repo-template/docs/ai/context-budget.md +54 -0
- package/repo-template/docs/ai/context-graph.md +39 -0
- package/repo-template/docs/ai/conventions.md +34 -0
- package/repo-template/docs/ai/decision-log.md +5 -0
- package/repo-template/docs/ai/enforcement.md +63 -0
- package/repo-template/docs/ai/eval-strategy.md +42 -0
- package/repo-template/docs/ai/evals.md +44 -0
- package/repo-template/docs/ai/git-workflow.md +35 -0
- package/repo-template/docs/ai/governance.md +61 -0
- package/repo-template/docs/ai/harness.md +49 -0
- package/repo-template/docs/ai/installer-cli.md +34 -0
- package/repo-template/docs/ai/loop-log.md +5 -0
- package/repo-template/docs/ai/loop-observability.md +57 -0
- package/repo-template/docs/ai/loop-policy.md +86 -0
- package/repo-template/docs/ai/loops.md +95 -0
- package/repo-template/docs/ai/maintainability-gates.md +26 -0
- package/repo-template/docs/ai/memory.md +71 -0
- package/repo-template/docs/ai/model-policy.md +105 -0
- package/repo-template/docs/ai/observability-runtime.md +48 -0
- package/repo-template/docs/ai/provider-routing.md +138 -0
- package/repo-template/docs/ai/quality-gates.md +48 -0
- package/repo-template/docs/ai/rollback-runtime.md +25 -0
- package/repo-template/docs/ai/security.md +12 -0
- package/repo-template/docs/ai/spec-driven-development.md +124 -0
- package/repo-template/docs/ai/spec-escalation.md +44 -0
- package/repo-template/docs/ai/spec-intake.md +46 -0
- package/repo-template/docs/ai/spec-sizing.md +207 -0
- package/repo-template/docs/ai/test-driven-development.md +35 -0
- package/repo-template/docs/ai/testing.md +28 -0
- package/repo-template/docs/ai/tool-adapters.md +186 -0
- package/repo-template/docs/ai/trust-allowlist.md +5 -0
- package/repo-template/docs/ai/trust-policy.md +41 -0
- package/repo-template/docs/ai/ui.md +17 -0
- package/repo-template/docs/skills/adapter-parity-review.md +46 -0
- package/repo-template/docs/skills/api-design.md +37 -0
- package/repo-template/docs/skills/architecture.md +37 -0
- package/repo-template/docs/skills/code-review.md +37 -0
- package/repo-template/docs/skills/context-graph.md +38 -0
- package/repo-template/docs/skills/debugging.md +37 -0
- package/repo-template/docs/skills/eval-design.md +12 -0
- package/repo-template/docs/skills/evals.md +37 -0
- package/repo-template/docs/skills/git-workflow.md +37 -0
- package/repo-template/docs/skills/look-trust-review.md +12 -0
- package/repo-template/docs/skills/loop-debugging.md +16 -0
- package/repo-template/docs/skills/loop-design.md +39 -0
- package/repo-template/docs/skills/loop-retrospective.md +15 -0
- package/repo-template/docs/skills/loop-review.md +16 -0
- package/repo-template/docs/skills/maintainability-review.md +12 -0
- package/repo-template/docs/skills/model-selection.md +36 -0
- package/repo-template/docs/skills/quality-gate-review.md +12 -0
- package/repo-template/docs/skills/spec-complexity-classifier.md +41 -0
- package/repo-template/docs/skills/spec-escalation-review.md +34 -0
- package/repo-template/docs/skills/spec-intake.md +25 -0
- package/repo-template/docs/skills/testing.md +37 -0
- package/repo-template/docs/skills/tool-adapter-sync.md +36 -0
- package/repo-template/docs/skills/ui-design.md +37 -0
- package/repo-template/docs/specs/README.md +9 -0
- package/repo-template/docs/specs/templates/basic-spec.md +41 -0
- package/repo-template/docs/specs/templates/complex-spec.md +145 -0
- package/repo-template/docs/specs/templates/standard-spec.md +58 -0
- package/repo-template/evals/README.md +11 -0
- package/repo-template/evals/golden/sample-golden.json +12 -0
- package/repo-template/evals/loop-regression/README.md +11 -0
- package/repo-template/evals/regression/sample-regression.json +12 -0
- package/repo-template/evals/schema/sample-schema.json +12 -0
- package/repo-template/evals/tool-calls/sample-tool-calls.json +12 -0
- package/repo-template/opencode.json.sample +29 -0
- package/repo-template/scripts/harness/backup.mjs +7 -0
- package/repo-template/scripts/harness/doctor.mjs +20 -0
- package/repo-template/scripts/harness/run-evals.mjs +27 -0
- package/repo-template/setup-agent-links.sh +54 -0
- package/scripts/check-published-release.mjs +127 -0
- package/scripts/check-release-commit.mjs +32 -0
- package/scripts/install.sh +225 -0
- package/scripts/installer-smoke-test.sh +155 -0
- package/scripts/lib/attribution-guard.mjs +59 -0
- package/scripts/registry-smoke-test.sh +149 -0
- package/scripts/smoke-test.sh +197 -0
- package/scripts/ux-smoke-test.sh +140 -0
- package/src/cli.js +625 -0
- package/src/doctor.js +68 -0
- package/src/global/adapter-context.js +27 -0
- package/src/global/adapter-matrix.js +38 -0
- package/src/global/adapters/claude.js +8 -0
- package/src/global/adapters/codex.js +8 -0
- package/src/global/adapters/cursor.js +8 -0
- package/src/global/adapters/opencode.js +8 -0
- package/src/global/agents.js +7 -0
- package/src/global/apply-confirmation.js +62 -0
- package/src/global/backups.js +54 -0
- package/src/global/brand/cli.js +52 -0
- package/src/global/brand/index.js +85 -0
- package/src/global/clack/setup-preview.js +48 -0
- package/src/global/clack/setup-wizard-constants.js +6 -0
- package/src/global/clack/setup-wizard.js +207 -0
- package/src/global/clack/theme.js +145 -0
- package/src/global/component-authoring.js +121 -0
- package/src/global/component-builders.js +43 -0
- package/src/global/component-distribution.js +270 -0
- package/src/global/component-installer.js +106 -0
- package/src/global/component-paths.js +22 -0
- package/src/global/component-registry.js +89 -0
- package/src/global/components/orchestrator.js +14 -0
- package/src/global/components/sdd-core.js +17 -0
- package/src/global/diff.js +233 -0
- package/src/global/drift.js +264 -0
- package/src/global/explain.js +144 -0
- package/src/global/global-cli.js +1145 -0
- package/src/global/global-doctor.js +67 -0
- package/src/global/global-installer.js +284 -0
- package/src/global/history.js +313 -0
- package/src/global/ink/run-setup-ink.js +77 -0
- package/src/global/ink/setup-app.js +278 -0
- package/src/global/ink/setup-routing.js +51 -0
- package/src/global/ink/setup-state.js +180 -0
- package/src/global/ink/terminal.js +13 -0
- package/src/global/json-output.js +22 -0
- package/src/global/load-component-catalog.js +41 -0
- package/src/global/load-workspace-component-catalog.js +123 -0
- package/src/global/managed-body.js +28 -0
- package/src/global/managed-config-adapter.js +134 -0
- package/src/global/managed-section.js +73 -0
- package/src/global/npm-registry.js +25 -0
- package/src/global/paths.js +22 -0
- package/src/global/policy.js +344 -0
- package/src/global/preflight.js +65 -0
- package/src/global/registry.js +79 -0
- package/src/global/report.js +110 -0
- package/src/global/rollback.js +126 -0
- package/src/global/setup.js +284 -0
- package/src/global/state-migration.js +65 -0
- package/src/global/state.js +50 -0
- package/src/global/status.js +94 -0
- package/src/global/sync.js +129 -0
- package/src/global/upgrade.js +145 -0
- package/src/harness-files.js +145 -0
- package/src/harness-updater.js +120 -0
- package/src/hash.js +5 -0
- package/src/manifest.js +36 -0
- package/src/project-detection.js +105 -0
- package/src/template-installer.js +72 -0
- package/src/text-template.js +24 -0
- package/src/workspace-cli.js +115 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
import { WIZARD_COPY } from "../brand/index.js";
|
|
4
|
+
import { loadConsentAudit } from "../policy.js";
|
|
5
|
+
import { formatResultNote } from "../clack/theme.js";
|
|
6
|
+
import { SetupWizardCancelledError } from "../clack/setup-wizard-constants.js";
|
|
7
|
+
import { SetupApp } from "./setup-app.js";
|
|
8
|
+
|
|
9
|
+
export { SetupWizardCancelledError };
|
|
10
|
+
|
|
11
|
+
export async function runSetupInk({
|
|
12
|
+
homeDir,
|
|
13
|
+
workspaceRoot,
|
|
14
|
+
packageRoot,
|
|
15
|
+
packageName,
|
|
16
|
+
cliVersion,
|
|
17
|
+
dryRun = false,
|
|
18
|
+
preflight = true,
|
|
19
|
+
yes = false,
|
|
20
|
+
confirm = false,
|
|
21
|
+
preflightExplicit = false,
|
|
22
|
+
yesExplicit = false,
|
|
23
|
+
confirmExplicit = false,
|
|
24
|
+
interactive = true,
|
|
25
|
+
renderImpl = render
|
|
26
|
+
}) {
|
|
27
|
+
const outcome = await new Promise((resolve) => {
|
|
28
|
+
const { waitUntilExit } = renderImpl(
|
|
29
|
+
React.createElement(SetupApp, {
|
|
30
|
+
homeDir,
|
|
31
|
+
workspaceRoot,
|
|
32
|
+
packageRoot,
|
|
33
|
+
packageName,
|
|
34
|
+
cliVersion,
|
|
35
|
+
dryRun,
|
|
36
|
+
onComplete: resolve
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
waitUntilExit().catch((error) => {
|
|
41
|
+
resolve({ cancelled: true, usedWizard: true, error });
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (outcome.error) {
|
|
46
|
+
throw outcome.error;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (outcome.cancelled) {
|
|
50
|
+
return outcome;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const consent = preflight
|
|
54
|
+
? await loadConsentAudit(homeDir, {
|
|
55
|
+
yes,
|
|
56
|
+
confirm,
|
|
57
|
+
yesExplicit,
|
|
58
|
+
confirmExplicit,
|
|
59
|
+
preflight,
|
|
60
|
+
preflightExplicit,
|
|
61
|
+
interactive,
|
|
62
|
+
applying: !dryRun,
|
|
63
|
+
dryRun,
|
|
64
|
+
json: false
|
|
65
|
+
})
|
|
66
|
+
: null;
|
|
67
|
+
|
|
68
|
+
return { ...outcome, consent };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function renderSetupInkResult(result, { dryRun = false } = {}) {
|
|
72
|
+
const title = dryRun ? WIZARD_COPY.resultDryRunTitle : WIZARD_COPY.resultSuccessTitle;
|
|
73
|
+
const outro = dryRun ? WIZARD_COPY.outroDryRun : WIZARD_COPY.outroSuccess;
|
|
74
|
+
console.log(`\n${title}\n`);
|
|
75
|
+
console.log(formatResultNote(result, { dryRun }));
|
|
76
|
+
console.log(`\n${outro}\n`);
|
|
77
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
3
|
+
import { stdout as output } from "node:process";
|
|
4
|
+
import { BRAND, WIZARD_COPY } from "../brand/index.js";
|
|
5
|
+
import { DEFAULT_COMPONENT_IDS, describeComponentCatalog } from "../component-registry.js";
|
|
6
|
+
import { GLOBAL_AGENT_IDS, detectInstalledAdapters, listAdapters } from "../registry.js";
|
|
7
|
+
import { buildSetupPreview, resolveComponentSelection } from "../clack/setup-preview.js";
|
|
8
|
+
import {
|
|
9
|
+
SETUP_STEPS,
|
|
10
|
+
buildAgentOptions,
|
|
11
|
+
buildComponentOptions,
|
|
12
|
+
formatInkDetectPanel,
|
|
13
|
+
formatInkHeaderLines,
|
|
14
|
+
formatInkPreviewLines,
|
|
15
|
+
formatInkSelectList,
|
|
16
|
+
formatInkSplashLines,
|
|
17
|
+
INITIAL_SETUP_STEP,
|
|
18
|
+
shouldStartPreviewLoad,
|
|
19
|
+
shouldUseCompactSplashLogo,
|
|
20
|
+
toggleComponentSelection,
|
|
21
|
+
toggleSelection,
|
|
22
|
+
transitionFromSplash
|
|
23
|
+
} from "./setup-state.js";
|
|
24
|
+
|
|
25
|
+
const INK_COLORS = {
|
|
26
|
+
accent: "cyan",
|
|
27
|
+
success: "green",
|
|
28
|
+
warning: "yellow",
|
|
29
|
+
danger: "red",
|
|
30
|
+
muted: "gray"
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function Header() {
|
|
34
|
+
const lines = formatInkHeaderLines();
|
|
35
|
+
return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
36
|
+
React.createElement(Text, { bold: true, color: INK_COLORS.accent }, lines[0]),
|
|
37
|
+
React.createElement(Text, { color: INK_COLORS.muted }, lines[1]),
|
|
38
|
+
React.createElement(Text, { dimColor: true }, lines[2])
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function Panel({ title, children }) {
|
|
43
|
+
return React.createElement(Box, {
|
|
44
|
+
flexDirection: "column",
|
|
45
|
+
borderStyle: "round",
|
|
46
|
+
borderColor: INK_COLORS.accent,
|
|
47
|
+
paddingX: 1,
|
|
48
|
+
marginBottom: 1
|
|
49
|
+
},
|
|
50
|
+
React.createElement(Text, { bold: true, color: INK_COLORS.accent }, title),
|
|
51
|
+
children
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Footer({ children }) {
|
|
56
|
+
return React.createElement(Text, { dimColor: true }, children);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function Splash({ compact }) {
|
|
60
|
+
const lines = formatInkSplashLines({ compact });
|
|
61
|
+
const logoLineCount = compact ? BRAND.compactLogo.length : BRAND.asciiLogo.length;
|
|
62
|
+
|
|
63
|
+
return React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
64
|
+
lines.map((line, index) => {
|
|
65
|
+
if (index < logoLineCount) {
|
|
66
|
+
return React.createElement(Text, { key: `logo-${index}`, bold: true, color: INK_COLORS.accent }, line);
|
|
67
|
+
}
|
|
68
|
+
if (line === BRAND.name) {
|
|
69
|
+
return React.createElement(Text, { key: `line-${index}`, bold: true, color: INK_COLORS.accent }, line);
|
|
70
|
+
}
|
|
71
|
+
if (line === BRAND.tagline) {
|
|
72
|
+
return React.createElement(Text, { key: `line-${index}`, color: INK_COLORS.muted }, line);
|
|
73
|
+
}
|
|
74
|
+
if (line === BRAND.splashHint) {
|
|
75
|
+
return React.createElement(Text, { key: `line-${index}`, dimColor: true }, line);
|
|
76
|
+
}
|
|
77
|
+
if (line === "") {
|
|
78
|
+
return React.createElement(Text, { key: `line-${index}` }, "");
|
|
79
|
+
}
|
|
80
|
+
return React.createElement(Text, { key: `line-${index}` }, line);
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function SetupApp({
|
|
86
|
+
homeDir,
|
|
87
|
+
workspaceRoot,
|
|
88
|
+
packageRoot,
|
|
89
|
+
packageName,
|
|
90
|
+
cliVersion,
|
|
91
|
+
dryRun = false,
|
|
92
|
+
onComplete
|
|
93
|
+
}) {
|
|
94
|
+
const { exit } = useApp();
|
|
95
|
+
const adapters = listAdapters();
|
|
96
|
+
const detected = detectInstalledAdapters({ homeDir });
|
|
97
|
+
const componentCatalog = describeComponentCatalog({ workspaceRoot });
|
|
98
|
+
const agentOptions = buildAgentOptions(adapters, detected);
|
|
99
|
+
const componentOptions = buildComponentOptions(componentCatalog);
|
|
100
|
+
const defaultAgents = detected.length > 0 ? detected : [...GLOBAL_AGENT_IDS];
|
|
101
|
+
|
|
102
|
+
const [step, setStep] = useState(INITIAL_SETUP_STEP);
|
|
103
|
+
const useCompactSplash = shouldUseCompactSplashLogo(output.columns);
|
|
104
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
105
|
+
const [selectedAgents, setSelectedAgents] = useState(defaultAgents);
|
|
106
|
+
const [selectedComponents, setSelectedComponents] = useState([...DEFAULT_COMPONENT_IDS]);
|
|
107
|
+
const [preview, setPreview] = useState(null);
|
|
108
|
+
const [previewError, setPreviewError] = useState(null);
|
|
109
|
+
const [previewLoading, setPreviewLoading] = useState(false);
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (!shouldStartPreviewLoad({ step, preview, previewError })) return;
|
|
113
|
+
|
|
114
|
+
let cancelled = false;
|
|
115
|
+
setPreviewLoading(true);
|
|
116
|
+
|
|
117
|
+
const { noDefaults, selected } = resolveComponentSelection(selectedComponents, { workspaceRoot });
|
|
118
|
+
|
|
119
|
+
buildSetupPreview({
|
|
120
|
+
homeDir,
|
|
121
|
+
workspaceRoot,
|
|
122
|
+
packageRoot,
|
|
123
|
+
packageName,
|
|
124
|
+
cliVersion,
|
|
125
|
+
agents: selectedAgents,
|
|
126
|
+
components: selected,
|
|
127
|
+
noDefaultComponents: noDefaults
|
|
128
|
+
}).then((built) => {
|
|
129
|
+
if (cancelled) return;
|
|
130
|
+
setPreview(built);
|
|
131
|
+
setPreviewLoading(false);
|
|
132
|
+
}).catch((error) => {
|
|
133
|
+
if (cancelled) return;
|
|
134
|
+
setPreviewError(error instanceof Error ? error.message : String(error));
|
|
135
|
+
setPreviewLoading(false);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return () => {
|
|
139
|
+
cancelled = true;
|
|
140
|
+
setPreviewLoading(false);
|
|
141
|
+
};
|
|
142
|
+
}, [step, preview, previewError, homeDir, workspaceRoot, packageRoot, packageName, cliVersion, selectedAgents, selectedComponents]);
|
|
143
|
+
|
|
144
|
+
const finish = (outcome) => {
|
|
145
|
+
onComplete(outcome);
|
|
146
|
+
exit();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
useInput((inputKey, key) => {
|
|
150
|
+
if (key.escape) {
|
|
151
|
+
finish({ cancelled: true, usedWizard: true });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (step === SETUP_STEPS.SPLASH) {
|
|
156
|
+
const splashTransition = transitionFromSplash({
|
|
157
|
+
escape: key.escape,
|
|
158
|
+
enter: key.return
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if (splashTransition.kind === "cancel") {
|
|
162
|
+
finish({ cancelled: true, usedWizard: true });
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (splashTransition.kind === "advance") {
|
|
166
|
+
setStep(splashTransition.step);
|
|
167
|
+
}
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (step === SETUP_STEPS.DETECT && key.return) {
|
|
172
|
+
setStep(SETUP_STEPS.AGENTS);
|
|
173
|
+
setActiveIndex(0);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (step === SETUP_STEPS.AGENTS) {
|
|
178
|
+
if (key.upArrow) {
|
|
179
|
+
setActiveIndex((index) => Math.max(0, index - 1));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (key.downArrow) {
|
|
183
|
+
setActiveIndex((index) => Math.min(agentOptions.length - 1, index + 1));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (inputKey === " ") {
|
|
187
|
+
const id = agentOptions[activeIndex].id;
|
|
188
|
+
setSelectedAgents((current) => toggleSelection(current, id));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (key.return && selectedAgents.length > 0) {
|
|
192
|
+
setStep(SETUP_STEPS.COMPONENTS);
|
|
193
|
+
setActiveIndex(0);
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (step === SETUP_STEPS.COMPONENTS) {
|
|
199
|
+
if (key.upArrow) {
|
|
200
|
+
setActiveIndex((index) => Math.max(0, index - 1));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (key.downArrow) {
|
|
204
|
+
setActiveIndex((index) => Math.min(componentOptions.length - 1, index + 1));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (inputKey === " ") {
|
|
208
|
+
const id = componentOptions[activeIndex].id;
|
|
209
|
+
setSelectedComponents((current) => toggleComponentSelection(current, id));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (key.return) {
|
|
213
|
+
setStep(SETUP_STEPS.PREVIEW);
|
|
214
|
+
setPreview(null);
|
|
215
|
+
setPreviewError(null);
|
|
216
|
+
}
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (step === SETUP_STEPS.PREVIEW && key.return && preview && !previewLoading) {
|
|
221
|
+
setStep(SETUP_STEPS.CONFIRM);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (step === SETUP_STEPS.CONFIRM) {
|
|
226
|
+
if (inputKey.toLowerCase() === "y") {
|
|
227
|
+
const { noDefaults, selected } = resolveComponentSelection(selectedComponents, { workspaceRoot });
|
|
228
|
+
finish({
|
|
229
|
+
cancelled: false,
|
|
230
|
+
usedWizard: true,
|
|
231
|
+
agents: selectedAgents,
|
|
232
|
+
components: selected,
|
|
233
|
+
noDefaultComponents: noDefaults,
|
|
234
|
+
preview
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (inputKey.toLowerCase() === "n") {
|
|
238
|
+
finish({ cancelled: true, usedWizard: true });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const detectPanel = formatInkDetectPanel({ adapters, detected });
|
|
244
|
+
|
|
245
|
+
return React.createElement(Box, { flexDirection: "column" },
|
|
246
|
+
step === SETUP_STEPS.SPLASH && React.createElement(Splash, { compact: useCompactSplash }),
|
|
247
|
+
step !== SETUP_STEPS.SPLASH && React.createElement(Header),
|
|
248
|
+
step === SETUP_STEPS.DETECT && React.createElement(Panel, { title: WIZARD_COPY.detectTitle },
|
|
249
|
+
detectPanel.split("\n")
|
|
250
|
+
.map((line) => React.createElement(Text, { key: line }, line))
|
|
251
|
+
),
|
|
252
|
+
step === SETUP_STEPS.AGENTS && React.createElement(Panel, { title: WIZARD_COPY.agentsPrompt },
|
|
253
|
+
formatInkSelectList({ options: agentOptions, selected: selectedAgents, activeIndex })
|
|
254
|
+
.map((line) => React.createElement(Text, { key: line }, line))
|
|
255
|
+
),
|
|
256
|
+
step === SETUP_STEPS.COMPONENTS && React.createElement(Panel, { title: WIZARD_COPY.componentsPrompt },
|
|
257
|
+
formatInkSelectList({ options: componentOptions, selected: selectedComponents, activeIndex })
|
|
258
|
+
.map((line) => React.createElement(Text, { key: line }, line))
|
|
259
|
+
),
|
|
260
|
+
step === SETUP_STEPS.PREVIEW && React.createElement(Panel, { title: WIZARD_COPY.previewTitle },
|
|
261
|
+
previewLoading && React.createElement(Text, { color: INK_COLORS.warning }, "Building preview…"),
|
|
262
|
+
previewError && React.createElement(Text, { color: INK_COLORS.danger }, previewError),
|
|
263
|
+
preview && formatInkPreviewLines({ preview, componentCatalog })
|
|
264
|
+
.map((line) => React.createElement(Text, { key: line }, line))
|
|
265
|
+
),
|
|
266
|
+
step === SETUP_STEPS.CONFIRM && React.createElement(Panel, { title: "Confirm" },
|
|
267
|
+
React.createElement(Text, null, dryRun ? WIZARD_COPY.confirmDryRun : WIZARD_COPY.confirmApply)
|
|
268
|
+
),
|
|
269
|
+
React.createElement(Footer, null,
|
|
270
|
+
step === SETUP_STEPS.SPLASH && `${BRAND.splashHint} · Esc cancel`,
|
|
271
|
+
step === SETUP_STEPS.DETECT && "Enter continue · Esc cancel",
|
|
272
|
+
step === SETUP_STEPS.AGENTS && "↑↓ move · Space toggle · Enter continue · Esc cancel",
|
|
273
|
+
step === SETUP_STEPS.COMPONENTS && "↑↓ move · Space toggle · Enter continue · Esc cancel",
|
|
274
|
+
step === SETUP_STEPS.PREVIEW && preview && !previewLoading && "Enter continue · Esc cancel",
|
|
275
|
+
step === SETUP_STEPS.CONFIRM && "Y apply · N cancel · Esc cancel"
|
|
276
|
+
)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { canUseSetupInk } from "./terminal.js";
|
|
2
|
+
|
|
3
|
+
const BARE_SETUP_FLAGS = [
|
|
4
|
+
"interactive",
|
|
5
|
+
"dryRun",
|
|
6
|
+
"yes",
|
|
7
|
+
"confirm",
|
|
8
|
+
"json",
|
|
9
|
+
"agents",
|
|
10
|
+
"components",
|
|
11
|
+
"noDefaultComponents"
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function isBareInteractiveSetup({
|
|
15
|
+
interactive,
|
|
16
|
+
yes = false,
|
|
17
|
+
confirm = false,
|
|
18
|
+
json = false,
|
|
19
|
+
agents = null,
|
|
20
|
+
components = null,
|
|
21
|
+
noDefaultComponents = false
|
|
22
|
+
} = {}) {
|
|
23
|
+
if (!interactive || json) return false;
|
|
24
|
+
if (yes || confirm) return false;
|
|
25
|
+
if (agents != null || components != null || noDefaultComponents) return false;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function shouldUseSetupInk({
|
|
30
|
+
interactive,
|
|
31
|
+
simple = false,
|
|
32
|
+
inkCapable = canUseSetupInk({ interactive }),
|
|
33
|
+
...flags
|
|
34
|
+
} = {}) {
|
|
35
|
+
if (simple) return false;
|
|
36
|
+
if (!isBareInteractiveSetup({ interactive, ...flags })) return false;
|
|
37
|
+
return inkCapable;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function shouldUseClackWizard({
|
|
41
|
+
interactive,
|
|
42
|
+
simple = false,
|
|
43
|
+
inkCapable = canUseSetupInk({ interactive }),
|
|
44
|
+
...flags
|
|
45
|
+
} = {}) {
|
|
46
|
+
if (!isBareInteractiveSetup({ interactive, ...flags })) return false;
|
|
47
|
+
if (!simple && inkCapable) return false;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { BARE_SETUP_FLAGS, isBareInteractiveSetup };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { AGENT_HINTS, BRAND, PREFERRED_CLI, formatCliCommand, getAgentLabel, WIZARD_COPY } from "../brand/index.js";
|
|
2
|
+
import { formatAgentMultiselectHint } from "../clack/theme.js";
|
|
3
|
+
|
|
4
|
+
export const SETUP_STEPS = {
|
|
5
|
+
SPLASH: "splash",
|
|
6
|
+
DETECT: "detect",
|
|
7
|
+
AGENTS: "agents",
|
|
8
|
+
COMPONENTS: "components",
|
|
9
|
+
PREVIEW: "preview",
|
|
10
|
+
CONFIRM: "confirm"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function shouldUseCompactSplashLogo(columns) {
|
|
14
|
+
if (!columns || columns <= 0) return false;
|
|
15
|
+
const fullWidth = Math.max(...BRAND.asciiLogo.map((line) => line.length));
|
|
16
|
+
return columns < fullWidth + 4;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function formatInkSplashLines({ compact = false } = {}) {
|
|
20
|
+
const logo = compact ? BRAND.compactLogo : BRAND.asciiLogo;
|
|
21
|
+
return [
|
|
22
|
+
...logo,
|
|
23
|
+
"",
|
|
24
|
+
BRAND.name,
|
|
25
|
+
BRAND.tagline,
|
|
26
|
+
"",
|
|
27
|
+
BRAND.splashHint
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const INITIAL_SETUP_STEP = SETUP_STEPS.SPLASH;
|
|
32
|
+
|
|
33
|
+
export function shouldStartPreviewLoad({ step, preview, previewError }) {
|
|
34
|
+
if (step !== SETUP_STEPS.PREVIEW) return false;
|
|
35
|
+
if (preview || previewError) return false;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function transitionFromSplash({ escape = false, enter = false } = {}) {
|
|
40
|
+
if (escape) {
|
|
41
|
+
return { kind: "cancel" };
|
|
42
|
+
}
|
|
43
|
+
if (enter) {
|
|
44
|
+
return { kind: "advance", step: SETUP_STEPS.DETECT };
|
|
45
|
+
}
|
|
46
|
+
return { kind: "noop" };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function toggleSelection(selected, id) {
|
|
50
|
+
if (selected.includes(id)) {
|
|
51
|
+
return selected.filter((entry) => entry !== id);
|
|
52
|
+
}
|
|
53
|
+
return [...selected, id];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function toggleComponentSelection(selected, id) {
|
|
57
|
+
if (id === "__none__") {
|
|
58
|
+
return selected.includes("__none__") ? [] : ["__none__"];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const withoutNone = selected.filter((entry) => entry !== "__none__");
|
|
62
|
+
return toggleSelection(withoutNone, id);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function buildAgentOptions(adapters, detected) {
|
|
66
|
+
return adapters.map((adapter) => ({
|
|
67
|
+
id: adapter.id,
|
|
68
|
+
label: getAgentLabel(adapter.id),
|
|
69
|
+
hint: formatAgentMultiselectHint(adapter.id, detected)
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function buildComponentOptions(components) {
|
|
74
|
+
return [
|
|
75
|
+
...components.map((component) => ({
|
|
76
|
+
id: component.id,
|
|
77
|
+
label: component.label,
|
|
78
|
+
hint: component.defaultEnabled ? "recommended" : undefined
|
|
79
|
+
})),
|
|
80
|
+
{
|
|
81
|
+
id: "__none__",
|
|
82
|
+
label: WIZARD_COPY.coreOnlyLabel,
|
|
83
|
+
hint: undefined
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function formatInkHeaderLines() {
|
|
89
|
+
return [
|
|
90
|
+
BRAND.name,
|
|
91
|
+
BRAND.tagline,
|
|
92
|
+
BRAND.splashLine
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function formatInkDetectPanel({ adapters, detected }) {
|
|
97
|
+
const readyCount = detected.length;
|
|
98
|
+
const lines = [
|
|
99
|
+
`Your agents · ${readyCount}/${adapters.length} roots found`,
|
|
100
|
+
""
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
for (const adapter of adapters) {
|
|
104
|
+
const isReady = detected.includes(adapter.id);
|
|
105
|
+
const status = isReady ? AGENT_HINTS.ready : AGENT_HINTS.notDetected;
|
|
106
|
+
lines.push(`${getAgentLabel(adapter.id)} · ${status}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return lines.join("\n");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function formatInkSelectList({ options, selected, activeIndex }) {
|
|
113
|
+
return options.map((option, index) => {
|
|
114
|
+
const checked = selected.includes(option.id) ? "[x]" : "[ ]";
|
|
115
|
+
const pointer = index === activeIndex ? "›" : " ";
|
|
116
|
+
const hint = option.hint ? ` (${option.hint})` : "";
|
|
117
|
+
return `${pointer} ${checked} ${option.label}${hint}`;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function formatInkPreviewLines({ preview, componentCatalog }) {
|
|
122
|
+
const labelById = new Map(componentCatalog.map((entry) => [entry.id, entry.label]));
|
|
123
|
+
const agentLine = preview.agents.map((id) => getAgentLabel(id)).join(", ") || "none";
|
|
124
|
+
const componentLine = preview.components.length > 0
|
|
125
|
+
? preview.components.map((id) => labelById.get(id) ?? id).join(", ")
|
|
126
|
+
: WIZARD_COPY.coreOnlyLabel;
|
|
127
|
+
|
|
128
|
+
const lines = [
|
|
129
|
+
"Agents",
|
|
130
|
+
` ${agentLine}`,
|
|
131
|
+
"",
|
|
132
|
+
"Components",
|
|
133
|
+
` ${componentLine}`,
|
|
134
|
+
"",
|
|
135
|
+
"Managed writes"
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
if (preview.preflight.changes.length === 0) {
|
|
139
|
+
lines.push(" none — already in sync");
|
|
140
|
+
} else {
|
|
141
|
+
for (const change of preview.preflight.changes) {
|
|
142
|
+
const verb = change.action === "create" ? "+" : change.action === "repair" ? "~" : "↻";
|
|
143
|
+
lines.push(` ${verb} ${change.target}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
lines.push("", "Preserved content");
|
|
148
|
+
if (preview.preflight.preserved.length === 0) {
|
|
149
|
+
lines.push(" none");
|
|
150
|
+
} else {
|
|
151
|
+
for (const entry of preview.preflight.preserved) {
|
|
152
|
+
lines.push(` ${entry.path}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return lines;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function formatInkSuccessLines(result, { dryRun = false, cliName = PREFERRED_CLI } = {}) {
|
|
160
|
+
const agentLine = result.agents.map((id) => getAgentLabel(id)).join(", ");
|
|
161
|
+
const componentLine = result.components.length > 0
|
|
162
|
+
? result.components.join(", ")
|
|
163
|
+
: WIZARD_COPY.coreOnlyLabel;
|
|
164
|
+
|
|
165
|
+
return [
|
|
166
|
+
dryRun ? WIZARD_COPY.resultDryRunTitle : WIZARD_COPY.resultSuccessTitle,
|
|
167
|
+
"",
|
|
168
|
+
`State ${result.stateRoot}`,
|
|
169
|
+
`Agents ${agentLine}`,
|
|
170
|
+
`Comps ${componentLine}`,
|
|
171
|
+
"",
|
|
172
|
+
"Next steps",
|
|
173
|
+
dryRun
|
|
174
|
+
? ` ${formatCliCommand("setup --confirm", cliName)}`
|
|
175
|
+
: ` ${formatCliCommand("status", cliName)}`,
|
|
176
|
+
dryRun
|
|
177
|
+
? ` ${formatCliCommand("setup --dry-run", cliName)}`
|
|
178
|
+
: ` ${formatCliCommand("doctor", cliName)}`
|
|
179
|
+
];
|
|
180
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
2
|
+
|
|
3
|
+
export function canUseSetupInk({
|
|
4
|
+
interactive = Boolean(input.isTTY && output.isTTY),
|
|
5
|
+
term = process.env.TERM ?? "",
|
|
6
|
+
columns = output.columns ?? 80,
|
|
7
|
+
forceInk = process.env.HARNESS_INK !== "0"
|
|
8
|
+
} = {}) {
|
|
9
|
+
if (!interactive || !forceInk) return false;
|
|
10
|
+
if (term === "dumb") return false;
|
|
11
|
+
if (columns > 0 && columns < 60) return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable control-plane JSON envelope for CI, tooling, and debugging.
|
|
3
|
+
* Field order and names are part of the public contract.
|
|
4
|
+
*/
|
|
5
|
+
export function buildControlPlaneJson(report, { cliVersion, extras = {} } = {}) {
|
|
6
|
+
return {
|
|
7
|
+
ok: report.ok,
|
|
8
|
+
overall: report.overall,
|
|
9
|
+
agents: report.agents,
|
|
10
|
+
components: report.components,
|
|
11
|
+
checks: report.checks,
|
|
12
|
+
backups: report.backups,
|
|
13
|
+
nextAction: report.nextAction,
|
|
14
|
+
policy: report.policy,
|
|
15
|
+
cliVersion,
|
|
16
|
+
...extras
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function printJson(payload) {
|
|
21
|
+
console.log(JSON.stringify(payload));
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createManagedSectionBuilder } from "./component-builders.js";
|
|
3
|
+
|
|
4
|
+
const defaultCatalogUrl = new URL("../../global-template/components/catalog.json", import.meta.url);
|
|
5
|
+
|
|
6
|
+
function validateCatalogEntry(entry) {
|
|
7
|
+
const required = ["id", "label", "version", "defaultEnabled", "assetFiles"];
|
|
8
|
+
|
|
9
|
+
for (const field of required) {
|
|
10
|
+
if (entry[field] === undefined) {
|
|
11
|
+
throw new Error(`Component catalog entry is missing "${field}".`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!Array.isArray(entry.assetFiles) || entry.assetFiles.length === 0) {
|
|
16
|
+
throw new Error(`Component "${entry.id}" must declare at least one asset file.`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function readComponentCatalogDocument(catalogUrl = defaultCatalogUrl) {
|
|
21
|
+
return JSON.parse(readFileSync(catalogUrl, "utf8"));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function loadComponentCatalog(catalogUrl = defaultCatalogUrl) {
|
|
25
|
+
const catalog = readComponentCatalogDocument(catalogUrl);
|
|
26
|
+
|
|
27
|
+
return catalog.components.map((entry) => {
|
|
28
|
+
validateCatalogEntry(entry);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
id: entry.id,
|
|
32
|
+
label: entry.label,
|
|
33
|
+
version: entry.version,
|
|
34
|
+
source: "bundled",
|
|
35
|
+
defaultEnabled: entry.defaultEnabled,
|
|
36
|
+
assetFiles: [...entry.assetFiles],
|
|
37
|
+
adapterHints: { ...(entry.adapterHints ?? {}) },
|
|
38
|
+
buildManagedSection: createManagedSectionBuilder(entry.id, entry)
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|