eai-cli 0.0.0-bootstrap.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/LICENSE +183 -0
- package/NOTICE +4 -0
- package/README.md +14 -0
- package/dist/commands/agent.d.ts +3 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +69 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/blocks.d.ts +3 -0
- package/dist/commands/blocks.d.ts.map +1 -0
- package/dist/commands/blocks.js +249 -0
- package/dist/commands/blocks.js.map +1 -0
- package/dist/commands/chat.d.ts +6 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +105 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/deploy.d.ts +36 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +712 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +15 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +133 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/docs.d.ts +6 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +118 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/env.d.ts +10 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +200 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/errors.d.ts +3 -0
- package/dist/commands/errors.d.ts.map +1 -0
- package/dist/commands/errors.js +72 -0
- package/dist/commands/errors.js.map +1 -0
- package/dist/commands/gofer.d.ts +3 -0
- package/dist/commands/gofer.d.ts.map +1 -0
- package/dist/commands/gofer.js +134 -0
- package/dist/commands/gofer.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1437 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +7 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +117 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/provision.d.ts +6 -0
- package/dist/commands/provision.d.ts.map +1 -0
- package/dist/commands/provision.js +855 -0
- package/dist/commands/provision.js.map +1 -0
- package/dist/commands/publicapi.d.ts +6 -0
- package/dist/commands/publicapi.d.ts.map +1 -0
- package/dist/commands/publicapi.js +184 -0
- package/dist/commands/publicapi.js.map +1 -0
- package/dist/commands/resources.d.ts +38 -0
- package/dist/commands/resources.d.ts.map +1 -0
- package/dist/commands/resources.js +1010 -0
- package/dist/commands/resources.js.map +1 -0
- package/dist/commands/runtime.d.ts +3 -0
- package/dist/commands/runtime.d.ts.map +1 -0
- package/dist/commands/runtime.js +78 -0
- package/dist/commands/runtime.js.map +1 -0
- package/dist/commands/template.d.ts +3 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/template.js +365 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/tenant.d.ts +45 -0
- package/dist/commands/tenant.d.ts.map +1 -0
- package/dist/commands/tenant.js +1036 -0
- package/dist/commands/tenant.js.map +1 -0
- package/dist/commands/types.d.ts +130 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +1636 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update.d.ts +13 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +163 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/user.d.ts +6 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +359 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/commands/verify.d.ts +40 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +1442 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/vertical.d.ts +24 -0
- package/dist/commands/vertical.d.ts.map +1 -0
- package/dist/commands/vertical.js +301 -0
- package/dist/commands/vertical.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +73 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/workflow.d.ts +6 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +400 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +272 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent-guide.d.ts +24 -0
- package/dist/lib/agent-guide.d.ts.map +1 -0
- package/dist/lib/agent-guide.js +155 -0
- package/dist/lib/agent-guide.js.map +1 -0
- package/dist/lib/api.d.ts +338 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +991 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/auth.d.ts +65 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +592 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/azure-cli.d.ts +6 -0
- package/dist/lib/azure-cli.d.ts.map +1 -0
- package/dist/lib/azure-cli.js +13 -0
- package/dist/lib/azure-cli.js.map +1 -0
- package/dist/lib/block-catalog-normalize.d.ts +47 -0
- package/dist/lib/block-catalog-normalize.d.ts.map +1 -0
- package/dist/lib/block-catalog-normalize.js +355 -0
- package/dist/lib/block-catalog-normalize.js.map +1 -0
- package/dist/lib/block-catalog-types.d.ts +111 -0
- package/dist/lib/block-catalog-types.d.ts.map +1 -0
- package/dist/lib/block-catalog-types.js +41 -0
- package/dist/lib/block-catalog-types.js.map +1 -0
- package/dist/lib/block-catalog-utils.d.ts +7 -0
- package/dist/lib/block-catalog-utils.d.ts.map +1 -0
- package/dist/lib/block-catalog-utils.js +47 -0
- package/dist/lib/block-catalog-utils.js.map +1 -0
- package/dist/lib/block-catalog-validation.d.ts +5 -0
- package/dist/lib/block-catalog-validation.d.ts.map +1 -0
- package/dist/lib/block-catalog-validation.js +112 -0
- package/dist/lib/block-catalog-validation.js.map +1 -0
- package/dist/lib/block-catalog.d.ts +3 -0
- package/dist/lib/block-catalog.d.ts.map +1 -0
- package/dist/lib/block-catalog.js +284 -0
- package/dist/lib/block-catalog.js.map +1 -0
- package/dist/lib/cloud-env.d.ts +25 -0
- package/dist/lib/cloud-env.d.ts.map +1 -0
- package/dist/lib/cloud-env.js +79 -0
- package/dist/lib/cloud-env.js.map +1 -0
- package/dist/lib/config.d.ts +116 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +195 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/context.d.ts +43 -0
- package/dist/lib/context.d.ts.map +1 -0
- package/dist/lib/context.js +68 -0
- package/dist/lib/context.js.map +1 -0
- package/dist/lib/error-codes.d.ts +56 -0
- package/dist/lib/error-codes.d.ts.map +1 -0
- package/dist/lib/error-codes.js +211 -0
- package/dist/lib/error-codes.js.map +1 -0
- package/dist/lib/error-guidance/catalog.d.ts +648 -0
- package/dist/lib/error-guidance/catalog.d.ts.map +1 -0
- package/dist/lib/error-guidance/catalog.js +940 -0
- package/dist/lib/error-guidance/catalog.js.map +1 -0
- package/dist/lib/error-guidance/match.d.ts +3 -0
- package/dist/lib/error-guidance/match.d.ts.map +1 -0
- package/dist/lib/error-guidance/match.js +46 -0
- package/dist/lib/error-guidance/match.js.map +1 -0
- package/dist/lib/error-guidance/render.d.ts +5 -0
- package/dist/lib/error-guidance/render.d.ts.map +1 -0
- package/dist/lib/error-guidance/render.js +92 -0
- package/dist/lib/error-guidance/render.js.map +1 -0
- package/dist/lib/error-guidance/types.d.ts +76 -0
- package/dist/lib/error-guidance/types.d.ts.map +1 -0
- package/dist/lib/error-guidance/types.js +2 -0
- package/dist/lib/error-guidance/types.js.map +1 -0
- package/dist/lib/error-guidance/validate.d.ts +3 -0
- package/dist/lib/error-guidance/validate.d.ts.map +1 -0
- package/dist/lib/error-guidance/validate.js +59 -0
- package/dist/lib/error-guidance/validate.js.map +1 -0
- package/dist/lib/gofer-installer.d.ts +32 -0
- package/dist/lib/gofer-installer.d.ts.map +1 -0
- package/dist/lib/gofer-installer.js +589 -0
- package/dist/lib/gofer-installer.js.map +1 -0
- package/dist/lib/gofer-refresh.d.ts +46 -0
- package/dist/lib/gofer-refresh.d.ts.map +1 -0
- package/dist/lib/gofer-refresh.js +536 -0
- package/dist/lib/gofer-refresh.js.map +1 -0
- package/dist/lib/next-route-exports.d.ts +6 -0
- package/dist/lib/next-route-exports.d.ts.map +1 -0
- package/dist/lib/next-route-exports.js +127 -0
- package/dist/lib/next-route-exports.js.map +1 -0
- package/dist/lib/npm.d.ts +2 -0
- package/dist/lib/npm.d.ts.map +1 -0
- package/dist/lib/npm.js +4 -0
- package/dist/lib/npm.js.map +1 -0
- package/dist/lib/object-type-defaults.d.ts +4 -0
- package/dist/lib/object-type-defaults.d.ts.map +1 -0
- package/dist/lib/object-type-defaults.js +72 -0
- package/dist/lib/object-type-defaults.js.map +1 -0
- package/dist/lib/output.d.ts +35 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +166 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/profile.d.ts +52 -0
- package/dist/lib/profile.d.ts.map +1 -0
- package/dist/lib/profile.js +116 -0
- package/dist/lib/profile.js.map +1 -0
- package/dist/lib/project-manifest.d.ts +42 -0
- package/dist/lib/project-manifest.d.ts.map +1 -0
- package/dist/lib/project-manifest.js +191 -0
- package/dist/lib/project-manifest.js.map +1 -0
- package/dist/lib/resourceapi-bundle.d.ts +33 -0
- package/dist/lib/resourceapi-bundle.d.ts.map +1 -0
- package/dist/lib/resourceapi-bundle.js +79 -0
- package/dist/lib/resourceapi-bundle.js.map +1 -0
- package/dist/lib/runtime-contract.d.ts +84 -0
- package/dist/lib/runtime-contract.d.ts.map +1 -0
- package/dist/lib/runtime-contract.js +318 -0
- package/dist/lib/runtime-contract.js.map +1 -0
- package/dist/lib/schema-builder.d.ts +28 -0
- package/dist/lib/schema-builder.d.ts.map +1 -0
- package/dist/lib/schema-builder.js +69 -0
- package/dist/lib/schema-builder.js.map +1 -0
- package/dist/lib/tenant-context.d.ts +127 -0
- package/dist/lib/tenant-context.d.ts.map +1 -0
- package/dist/lib/tenant-context.js +573 -0
- package/dist/lib/tenant-context.js.map +1 -0
- package/dist/lib/update-check.d.ts +52 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +271 -0
- package/dist/lib/update-check.js.map +1 -0
- package/dist/lib/update-maintenance.d.ts +15 -0
- package/dist/lib/update-maintenance.d.ts.map +1 -0
- package/dist/lib/update-maintenance.js +187 -0
- package/dist/lib/update-maintenance.js.map +1 -0
- package/dist/lib/utils.d.ts +23 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +48 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/workflow-provisioning.d.ts +54 -0
- package/dist/lib/workflow-provisioning.d.ts.map +1 -0
- package/dist/lib/workflow-provisioning.js +281 -0
- package/dist/lib/workflow-provisioning.js.map +1 -0
- package/package.json +51 -0
- package/resources/gofer/.gofer-version +7 -0
- package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +1287 -0
- package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +429 -0
- package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +635 -0
- package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +1159 -0
- package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +860 -0
- package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +886 -0
- package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +748 -0
- package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +924 -0
- package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +2269 -0
- package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +423 -0
- package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +508 -0
- package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +315 -0
- package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +558 -0
- package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +148 -0
- package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +119 -0
- package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +612 -0
- package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +114 -0
- package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +397 -0
- package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +561 -0
- package/resources/gofer/agents-skills/gofer_personality/SKILL.md +44 -0
- package/resources/gofer/agents-skills/gofer_plan/SKILL.md +40 -0
- package/resources/gofer/agents-skills/gofer_side/SKILL.md +45 -0
- package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +112 -0
- package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +112 -0
- package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +112 -0
- package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +112 -0
- package/resources/gofer/bash-scripts/check-context-health.sh +365 -0
- package/resources/gofer/bash-scripts/check-persona-pack.sh +81 -0
- package/resources/gofer/bash-scripts/check-prerequisites.sh +168 -0
- package/resources/gofer/bash-scripts/common.sh +192 -0
- package/resources/gofer/bash-scripts/create-new-feature.sh +260 -0
- package/resources/gofer/bash-scripts/install-optional-tools.sh +270 -0
- package/resources/gofer/bash-scripts/log-stage.sh +224 -0
- package/resources/gofer/bash-scripts/mark-task-complete.sh +74 -0
- package/resources/gofer/bash-scripts/pipeline-state.sh +306 -0
- package/resources/gofer/bash-scripts/read-failed-approaches.sh +114 -0
- package/resources/gofer/bash-scripts/read-session-memories.sh +96 -0
- package/resources/gofer/bash-scripts/save-checkpoint.sh +407 -0
- package/resources/gofer/bash-scripts/setup-plan.sh +62 -0
- package/resources/gofer/bash-scripts/sync-implementation-status.sh +47 -0
- package/resources/gofer/bash-scripts/update-agent-context.sh +772 -0
- package/resources/gofer/bash-scripts/validate-artifact.sh +335 -0
- package/resources/gofer/bash-scripts/verify-task.sh +384 -0
- package/resources/gofer/bash-scripts/write-failed-approach.sh +110 -0
- package/resources/gofer/bash-scripts/write-periodic-checkpoint.sh +128 -0
- package/resources/gofer/bash-scripts/write-session-memory.sh +118 -0
- package/resources/gofer/claude-agents/assumption-tracker.md +168 -0
- package/resources/gofer/claude-agents/business-metrics-analyzer.md +169 -0
- package/resources/gofer/claude-agents/business-problem-validator.md +168 -0
- package/resources/gofer/claude-agents/codebase-analyzer.md +124 -0
- package/resources/gofer/claude-agents/codebase-locator.md +95 -0
- package/resources/gofer/claude-agents/codebase-pattern-finder.md +180 -0
- package/resources/gofer/claude-agents/comms-writer.md +158 -0
- package/resources/gofer/claude-agents/engineer-review.md +169 -0
- package/resources/gofer/claude-agents/implement-bug-triangulator.md +94 -0
- package/resources/gofer/claude-agents/implement-code-review-council.md +89 -0
- package/resources/gofer/claude-agents/implement-doc-writer.md +89 -0
- package/resources/gofer/claude-agents/implement-error-hardener.md +84 -0
- package/resources/gofer/claude-agents/implement-performance-explorer.md +95 -0
- package/resources/gofer/claude-agents/implement-test-diversifier.md +82 -0
- package/resources/gofer/claude-agents/implement-variant-generator.md +80 -0
- package/resources/gofer/claude-agents/multi-perspective-judge.md +114 -0
- package/resources/gofer/claude-agents/plan-api-comparator.md +90 -0
- package/resources/gofer/claude-agents/plan-architecture-diverger.md +100 -0
- package/resources/gofer/claude-agents/plan-data-model-stress-tester.md +95 -0
- package/resources/gofer/claude-agents/plan-migration-path-finder.md +95 -0
- package/resources/gofer/claude-agents/plan-refactor-rewrite-advisor.md +97 -0
- package/resources/gofer/claude-agents/research-dependency-evaluator.md +106 -0
- package/resources/gofer/claude-agents/research-horizon-scanner.md +100 -0
- package/resources/gofer/claude-agents/research-market-scanner.md +137 -0
- package/resources/gofer/claude-agents/research-perspective-multiplier.md +102 -0
- package/resources/gofer/claude-agents/scope-creep-detector.md +152 -0
- package/resources/gofer/claude-agents/specify-ambiguity-detector.md +95 -0
- package/resources/gofer/claude-agents/specify-journey-stress-tester.md +92 -0
- package/resources/gofer/claude-agents/tasks-cross-cutting-scanner.md +91 -0
- package/resources/gofer/claude-agents/tasks-rollback-planner.md +89 -0
- package/resources/gofer/claude-agents/validate-security-red-team.md +102 -0
- package/resources/gofer/claude-agents/validation-correctness.md +103 -0
- package/resources/gofer/claude-agents/validation-integration.md +129 -0
- package/resources/gofer/claude-agents/validation-performance.md +120 -0
- package/resources/gofer/claude-agents/validation-security.md +115 -0
- package/resources/gofer/claude-agents/validation-standards.md +151 -0
- package/resources/gofer/claude-agents/validation-test-quality.md +146 -0
- package/resources/gofer/claude-agents/visual-bounded-context-writer.md +40 -0
- package/resources/gofer/claude-agents/visual-c4-writer.md +45 -0
- package/resources/gofer/claude-agents/visual-erd-writer.md +34 -0
- package/resources/gofer/claude-agents/visual-heatmap-writer.md +63 -0
- package/resources/gofer/claude-agents/visual-risk-writer.md +64 -0
- package/resources/gofer/claude-commands/0_gofer_start.md +1282 -0
- package/resources/gofer/claude-commands/0a_problem_validation.md +424 -0
- package/resources/gofer/claude-commands/10_gofer_cloud.md +630 -0
- package/resources/gofer/claude-commands/1_gofer_research.md +1154 -0
- package/resources/gofer/claude-commands/2_gofer_specify.md +855 -0
- package/resources/gofer/claude-commands/3_gofer_plan.md +881 -0
- package/resources/gofer/claude-commands/4_gofer_tasks.md +743 -0
- package/resources/gofer/claude-commands/5_gofer_implement.md +919 -0
- package/resources/gofer/claude-commands/6_gofer_validate.md +2264 -0
- package/resources/gofer/claude-commands/7_gofer_save.md +418 -0
- package/resources/gofer/claude-commands/7a_stakeholder_comms.md +503 -0
- package/resources/gofer/claude-commands/8_gofer_branding.md +310 -0
- package/resources/gofer/claude-commands/9_gofer_tests.md +553 -0
- package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +143 -0
- package/resources/gofer/claude-commands/gofer_check_workspace.md +114 -0
- package/resources/gofer/claude-commands/gofer_constitution.md +607 -0
- package/resources/gofer/claude-commands/gofer_diagnose.md +109 -0
- package/resources/gofer/claude-commands/gofer_eai_first_run.md +392 -0
- package/resources/gofer/claude-commands/gofer_hydrate.md +556 -0
- package/resources/gofer/claude-commands/gofer_personality.md +39 -0
- package/resources/gofer/claude-commands/gofer_plan.md +35 -0
- package/resources/gofer/claude-commands/gofer_side.md +40 -0
- package/resources/gofer/claude-commands/gofer_spec_summary.md +107 -0
- package/resources/gofer/claude-commands/gofer_tdd.md +107 -0
- package/resources/gofer/claude-commands/gofer_vocabulary.md +107 -0
- package/resources/gofer/claude-commands/gofer_zoom_out.md +107 -0
- package/resources/gofer/claude-skills/eai-gofer/SKILL.md +56 -0
- package/resources/gofer/commands/.gitkeep +0 -0
- package/resources/gofer/commands/0_gofer_start.md +1299 -0
- package/resources/gofer/commands/0a_problem_validation.md +405 -0
- package/resources/gofer/commands/10_gofer_cloud.md +611 -0
- package/resources/gofer/commands/1_gofer_research.md +1135 -0
- package/resources/gofer/commands/2_gofer_specify.md +836 -0
- package/resources/gofer/commands/3_gofer_plan.md +862 -0
- package/resources/gofer/commands/4_gofer_tasks.md +724 -0
- package/resources/gofer/commands/5_gofer_implement.md +900 -0
- package/resources/gofer/commands/6_gofer_validate.md +2245 -0
- package/resources/gofer/commands/7_gofer_save.md +399 -0
- package/resources/gofer/commands/7a_stakeholder_comms.md +484 -0
- package/resources/gofer/commands/8_gofer_branding.md +291 -0
- package/resources/gofer/commands/9_gofer_tests.md +534 -0
- package/resources/gofer/commands/gofer_bootstrap_workspace.md +159 -0
- package/resources/gofer/commands/gofer_check_workspace.md +130 -0
- package/resources/gofer/commands/gofer_constitution.md +588 -0
- package/resources/gofer/commands/gofer_diagnose.md +89 -0
- package/resources/gofer/commands/gofer_eai_first_run.md +392 -0
- package/resources/gofer/commands/gofer_hydrate.md +537 -0
- package/resources/gofer/commands/gofer_personality.md +61 -0
- package/resources/gofer/commands/gofer_plan.md +51 -0
- package/resources/gofer/commands/gofer_side.md +56 -0
- package/resources/gofer/commands/gofer_spec_summary.md +87 -0
- package/resources/gofer/commands/gofer_tdd.md +87 -0
- package/resources/gofer/commands/gofer_vocabulary.md +87 -0
- package/resources/gofer/commands/gofer_zoom_out.md +87 -0
- package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +13 -0
- package/resources/gofer/copilot-instructions/language-server.instructions.md +49 -0
- package/resources/gofer/copilot-instructions/typescript.instructions.md +47 -0
- package/resources/gofer/copilot-instructions/vscode-extension.instructions.md +46 -0
- package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +1308 -0
- package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +429 -0
- package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +644 -0
- package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +1177 -0
- package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +878 -0
- package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +904 -0
- package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +766 -0
- package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +942 -0
- package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +2277 -0
- package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +433 -0
- package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +516 -0
- package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +323 -0
- package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +566 -0
- package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +161 -0
- package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +132 -0
- package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +621 -0
- package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +127 -0
- package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +410 -0
- package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +571 -0
- package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +57 -0
- package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +53 -0
- package/resources/gofer/copilot-prompts/gofer_side.prompt.md +58 -0
- package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +125 -0
- package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +125 -0
- package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +125 -0
- package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +125 -0
- package/resources/gofer/gemini/agents/assumption-tracker.md +171 -0
- package/resources/gofer/gemini/agents/business-metrics-analyzer.md +172 -0
- package/resources/gofer/gemini/agents/business-problem-validator.md +171 -0
- package/resources/gofer/gemini/agents/codebase-analyzer.md +127 -0
- package/resources/gofer/gemini/agents/codebase-locator.md +98 -0
- package/resources/gofer/gemini/agents/codebase-pattern-finder.md +183 -0
- package/resources/gofer/gemini/agents/comms-writer.md +161 -0
- package/resources/gofer/gemini/agents/engineer-review.md +172 -0
- package/resources/gofer/gemini/agents/implement-bug-triangulator.md +97 -0
- package/resources/gofer/gemini/agents/implement-code-review-council.md +92 -0
- package/resources/gofer/gemini/agents/implement-doc-writer.md +92 -0
- package/resources/gofer/gemini/agents/implement-error-hardener.md +87 -0
- package/resources/gofer/gemini/agents/implement-performance-explorer.md +98 -0
- package/resources/gofer/gemini/agents/implement-test-diversifier.md +85 -0
- package/resources/gofer/gemini/agents/implement-variant-generator.md +83 -0
- package/resources/gofer/gemini/agents/multi-perspective-judge.md +117 -0
- package/resources/gofer/gemini/agents/plan-api-comparator.md +93 -0
- package/resources/gofer/gemini/agents/plan-architecture-diverger.md +103 -0
- package/resources/gofer/gemini/agents/plan-data-model-stress-tester.md +98 -0
- package/resources/gofer/gemini/agents/plan-migration-path-finder.md +98 -0
- package/resources/gofer/gemini/agents/plan-refactor-rewrite-advisor.md +100 -0
- package/resources/gofer/gemini/agents/research-dependency-evaluator.md +109 -0
- package/resources/gofer/gemini/agents/research-horizon-scanner.md +103 -0
- package/resources/gofer/gemini/agents/research-market-scanner.md +140 -0
- package/resources/gofer/gemini/agents/research-perspective-multiplier.md +105 -0
- package/resources/gofer/gemini/agents/scope-creep-detector.md +155 -0
- package/resources/gofer/gemini/agents/specify-ambiguity-detector.md +98 -0
- package/resources/gofer/gemini/agents/specify-journey-stress-tester.md +95 -0
- package/resources/gofer/gemini/agents/tasks-cross-cutting-scanner.md +94 -0
- package/resources/gofer/gemini/agents/tasks-rollback-planner.md +92 -0
- package/resources/gofer/gemini/agents/validate-security-red-team.md +105 -0
- package/resources/gofer/gemini/agents/validation-correctness.md +106 -0
- package/resources/gofer/gemini/agents/validation-integration.md +132 -0
- package/resources/gofer/gemini/agents/validation-performance.md +123 -0
- package/resources/gofer/gemini/agents/validation-security.md +118 -0
- package/resources/gofer/gemini/agents/validation-standards.md +154 -0
- package/resources/gofer/gemini/agents/validation-test-quality.md +149 -0
- package/resources/gofer/gemini/agents/visual-bounded-context-writer.md +40 -0
- package/resources/gofer/gemini/agents/visual-c4-writer.md +44 -0
- package/resources/gofer/gemini/agents/visual-erd-writer.md +36 -0
- package/resources/gofer/gemini/agents/visual-heatmap-writer.md +63 -0
- package/resources/gofer/gemini/agents/visual-risk-writer.md +64 -0
- package/resources/gofer/gemini/commands/gofer/.gitkeep +0 -0
- package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +1282 -0
- package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +424 -0
- package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +630 -0
- package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +1154 -0
- package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +855 -0
- package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +881 -0
- package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +743 -0
- package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +919 -0
- package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +2264 -0
- package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +418 -0
- package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +503 -0
- package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +310 -0
- package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +553 -0
- package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +143 -0
- package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +114 -0
- package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +607 -0
- package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +109 -0
- package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +392 -0
- package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +556 -0
- package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_personality.md +39 -0
- package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_plan.md +35 -0
- package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_side.md +40 -0
- package/resources/gofer/gemini/commands/gofer/gofer_side.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +107 -0
- package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +107 -0
- package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +107 -0
- package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +107 -0
- package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/manifest.json +32 -0
- package/resources/gofer/gemini/extension.json +16 -0
- package/resources/gofer/github-agents/gofer-business.agent.md +20 -0
- package/resources/gofer/github-agents/gofer-implement.agent.md +15 -0
- package/resources/gofer/github-agents/gofer-plan.agent.md +15 -0
- package/resources/gofer/github-agents/gofer-research.agent.md +15 -0
- package/resources/gofer/github-agents/gofer-validate.agent.md +10 -0
- package/resources/gofer/github-skills/eai-gofer/SKILL.md +56 -0
- package/resources/gofer/hook-scripts/agent-stop.mjs +655 -0
- package/resources/gofer/hook-scripts/log-stage-launch-time.mjs +77 -0
- package/resources/gofer/hook-scripts/post-tool-use.mjs +333 -0
- package/resources/gofer/hook-scripts/queued-input.mjs +188 -0
- package/resources/gofer/hook-scripts/session-lifecycle.mjs +93 -0
- package/resources/gofer/hook-scripts/user-prompt-submit.mjs +228 -0
- package/resources/gofer/instruction-templates/base/agents-base.md +37 -0
- package/resources/gofer/instruction-templates/base/claude-base.md +7 -0
- package/resources/gofer/instruction-templates/base/copilot-base.md +26 -0
- package/resources/gofer/instruction-templates/gofer/gofer-claude.md +5 -0
- package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +9 -0
- package/resources/gofer/instruction-templates/languages/generic.md +7 -0
- package/resources/gofer/instruction-templates/languages/go.md +8 -0
- package/resources/gofer/instruction-templates/languages/java.md +8 -0
- package/resources/gofer/instruction-templates/languages/python.md +9 -0
- package/resources/gofer/instruction-templates/languages/rust.md +9 -0
- package/resources/gofer/instruction-templates/languages/typescript.md +19 -0
- package/resources/gofer/instruction-templates/workflow/principles.md +52 -0
- package/resources/gofer/memory/constitution.md +391 -0
- package/resources/gofer/memory/context-profiles.yaml +74 -0
- package/resources/gofer/memory/decisions/000-use-adr-for-decisions.md +67 -0
- package/resources/gofer/memory/decisions/001-di-framework.md +190 -0
- package/resources/gofer/memory/decisions/002-module-extraction.md +305 -0
- package/resources/gofer/memory/decisions/003-error-handling.md +368 -0
- package/resources/gofer/memory/decisions/004-cache-eviction.md +436 -0
- package/resources/gofer/memory/decisions/005-constants-management.md +520 -0
- package/resources/gofer/memory/decisions/README.md +129 -0
- package/resources/gofer/memory/diagrams/di-container.mmd +321 -0
- package/resources/gofer/memory/diagrams/extension-activation.mmd +184 -0
- package/resources/gofer/memory/diagrams/module-dependencies.mmd +264 -0
- package/resources/gofer/memory/gofer-model-policy.yaml +97 -0
- package/resources/gofer/memory/lessons.md +46 -0
- package/resources/gofer/node-scripts/canonical-descriptions.mjs +86 -0
- package/resources/gofer/node-scripts/check-version-alignment.mjs +131 -0
- package/resources/gofer/node-scripts/codex-doctor.mjs +425 -0
- package/resources/gofer/node-scripts/generate-commands.mjs +1366 -0
- package/resources/gofer/node-scripts/generate-issues.js +563 -0
- package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +893 -0
- package/resources/gofer/node-scripts/gofer-loop-audit.mjs +541 -0
- package/resources/gofer/node-scripts/gofer-performance-report.mjs +306 -0
- package/resources/gofer/node-scripts/gofer-workspace-bootstrap.mjs +56 -0
- package/resources/gofer/node-scripts/gofer-workspace-check.mjs +56 -0
- package/resources/gofer/node-scripts/lib/ai-leverage-tagger.mjs +103 -0
- package/resources/gofer/node-scripts/lib/assemble-stakeholder-pack.mjs +114 -0
- package/resources/gofer/node-scripts/lib/marp-deck.mjs +87 -0
- package/resources/gofer/node-scripts/lib/mermaid-tabular-fallback.mjs +264 -0
- package/resources/gofer/node-scripts/lib/render-visual.mjs +54 -0
- package/resources/gofer/node-scripts/lib/validate-aliases.mjs +85 -0
- package/resources/gofer/node-scripts/lib/visual-counts.mjs +44 -0
- package/resources/gofer/node-scripts/lib/visual-pass-pipeline.mjs +134 -0
- package/resources/gofer/node-scripts/mermaid-export.mjs +72 -0
- package/resources/gofer/node-scripts/package-agent-plugin.mjs +940 -0
- package/resources/gofer/node-scripts/parse-stage-command.mjs +211 -0
- package/resources/gofer/node-scripts/schemas/.gitkeep +0 -0
- package/resources/gofer/node-scripts/schemas/stage-command.schema.json +72 -0
- package/resources/gofer/node-scripts/sync-extension-resources.mjs +110 -0
- package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +1166 -0
- package/resources/gofer/powershell-scripts/install-optional-tools.ps1 +214 -0
- package/resources/gofer/references/platform/README.md +17 -0
- package/resources/gofer/references/platform/deployment-repo.md +9 -0
- package/resources/gofer/references/platform/eai-app-template.md +45 -0
- package/resources/gofer/references/platform/eai-config-driven-ui.md +156 -0
- package/resources/gofer/references/platform/eai-error-catalog.yaml +197 -0
- package/resources/gofer/references/platform/eai-repo-contract.md +134 -0
- package/resources/gofer/references/platform/eai-service-patterns.md +56 -0
- package/resources/gofer/references/platform/eai.md +85 -0
- package/resources/gofer/references/platform/vertical-template.md +49 -0
- package/resources/gofer/specify-commands/.gitkeep +0 -0
- package/resources/gofer/specify-commands/0_gofer_start.md +1299 -0
- package/resources/gofer/specify-commands/0a_problem_validation.md +405 -0
- package/resources/gofer/specify-commands/10_gofer_cloud.md +611 -0
- package/resources/gofer/specify-commands/1_gofer_research.md +1135 -0
- package/resources/gofer/specify-commands/2_gofer_specify.md +836 -0
- package/resources/gofer/specify-commands/3_gofer_plan.md +862 -0
- package/resources/gofer/specify-commands/4_gofer_tasks.md +724 -0
- package/resources/gofer/specify-commands/5_gofer_implement.md +900 -0
- package/resources/gofer/specify-commands/6_gofer_validate.md +2245 -0
- package/resources/gofer/specify-commands/7_gofer_save.md +399 -0
- package/resources/gofer/specify-commands/7a_stakeholder_comms.md +484 -0
- package/resources/gofer/specify-commands/8_gofer_branding.md +291 -0
- package/resources/gofer/specify-commands/9_gofer_tests.md +534 -0
- package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +159 -0
- package/resources/gofer/specify-commands/gofer_check_workspace.md +130 -0
- package/resources/gofer/specify-commands/gofer_constitution.md +588 -0
- package/resources/gofer/specify-commands/gofer_diagnose.md +89 -0
- package/resources/gofer/specify-commands/gofer_eai_first_run.md +392 -0
- package/resources/gofer/specify-commands/gofer_hydrate.md +537 -0
- package/resources/gofer/specify-commands/gofer_personality.md +61 -0
- package/resources/gofer/specify-commands/gofer_plan.md +51 -0
- package/resources/gofer/specify-commands/gofer_side.md +56 -0
- package/resources/gofer/specify-commands/gofer_spec_summary.md +87 -0
- package/resources/gofer/specify-commands/gofer_tdd.md +87 -0
- package/resources/gofer/specify-commands/gofer_vocabulary.md +87 -0
- package/resources/gofer/specify-commands/gofer_zoom_out.md +87 -0
- package/resources/gofer/system-skills/0_gofer_start/SKILL.md +1287 -0
- package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +429 -0
- package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +635 -0
- package/resources/gofer/system-skills/1_gofer_research/SKILL.md +1159 -0
- package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +860 -0
- package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +886 -0
- package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +748 -0
- package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +924 -0
- package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +2269 -0
- package/resources/gofer/system-skills/7_gofer_save/SKILL.md +423 -0
- package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +508 -0
- package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +315 -0
- package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +558 -0
- package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +148 -0
- package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +119 -0
- package/resources/gofer/system-skills/gofer_constitution/SKILL.md +612 -0
- package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +114 -0
- package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +397 -0
- package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +561 -0
- package/resources/gofer/system-skills/gofer_personality/SKILL.md +44 -0
- package/resources/gofer/system-skills/gofer_plan/SKILL.md +40 -0
- package/resources/gofer/system-skills/gofer_side/SKILL.md +45 -0
- package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +112 -0
- package/resources/gofer/system-skills/gofer_tdd/SKILL.md +112 -0
- package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +112 -0
- package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +112 -0
- package/resources/gofer/templates/agent-file-template.md +28 -0
- package/resources/gofer/templates/assumptions-template.md +94 -0
- package/resources/gofer/templates/audit-history-template.md +35 -0
- package/resources/gofer/templates/brand/brand-profile-template.json +45 -0
- package/resources/gofer/templates/brand/document-style-template.md +50 -0
- package/resources/gofer/templates/brand/marp-theme-template.css +58 -0
- package/resources/gofer/templates/brownfield-analysis.md +44 -0
- package/resources/gofer/templates/business-metrics-template.md +120 -0
- package/resources/gofer/templates/business-owner-summary-template.md +83 -0
- package/resources/gofer/templates/checklist-template.md +40 -0
- package/resources/gofer/templates/ciso-security-summary-template.md +70 -0
- package/resources/gofer/templates/context-bundle-template.md +76 -0
- package/resources/gofer/templates/contract-pack-template.md +109 -0
- package/resources/gofer/templates/cto-architecture-summary-template.md +83 -0
- package/resources/gofer/templates/discovery-template.md +92 -0
- package/resources/gofer/templates/eai-preflight-template.md +144 -0
- package/resources/gofer/templates/goal-ledger-template.json +69 -0
- package/resources/gofer/templates/gofer-model-policy.yaml +97 -0
- package/resources/gofer/templates/issues-template.md +106 -0
- package/resources/gofer/templates/journey/base-journey.md +95 -0
- package/resources/gofer/templates/journey/industry-variants.yaml +277 -0
- package/resources/gofer/templates/loop-contract-template.json +68 -0
- package/resources/gofer/templates/plan-template.md +215 -0
- package/resources/gofer/templates/problem-brief-template.md +85 -0
- package/resources/gofer/templates/proposal-review-template.md +79 -0
- package/resources/gofer/templates/research-template.md +222 -0
- package/resources/gofer/templates/reuse-scan-template.md +43 -0
- package/resources/gofer/templates/sequence-diagrams/option-spectrum.yaml +178 -0
- package/resources/gofer/templates/service-fit-matrix-template.md +29 -0
- package/resources/gofer/templates/session-handoff-template.md +172 -0
- package/resources/gofer/templates/spec-summary-template.md +118 -0
- package/resources/gofer/templates/spec-template.md +196 -0
- package/resources/gofer/templates/stakeholder-comms-template.md +330 -0
- package/resources/gofer/templates/stakeholder-review-index-template.md +54 -0
- package/resources/gofer/templates/tasks-template.md +323 -0
- package/resources/gofer/templates/ui-approval-template.md +32 -0
- package/resources/gofer/templates/ui-preview-brief-template.md +65 -0
- package/resources/gofer/templates/ui-review-log-template.md +11 -0
- package/resources/gofer/templates/visuals/.gitkeep +0 -0
- package/resources/gofer/templates/visuals/bounded-context-map.md +19 -0
- package/resources/gofer/templates/visuals/bounded-context-template.md +47 -0
- package/resources/gofer/templates/visuals/c4-container-template.md +38 -0
- package/resources/gofer/templates/visuals/c4-container.md +20 -0
- package/resources/gofer/templates/visuals/c4-context-template.md +46 -0
- package/resources/gofer/templates/visuals/capability-heatmap-template.md +54 -0
- package/resources/gofer/templates/visuals/data-model-erd-template.md +41 -0
- package/resources/gofer/templates/visuals/erd.md +19 -0
- package/resources/gofer/templates/visuals/impact-canvas.md +40 -0
- package/resources/gofer/templates/visuals/risk-heatmap-template.md +51 -0
- package/resources/gofer/templates/visuals/roi-projection.md +17 -0
- package/resources/gofer/templates/visuals/value-stream-asis.md +16 -0
- package/resources/gofer/templates/visuals/value-stream-tobe.md +18 -0
- package/resources/gofer/templates/working-backwards-prfaq-template.md +165 -0
- package/resources/linked-sources.json +25 -0
|
@@ -0,0 +1,1010 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eai resources — CRUD operations on platform resources.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { resolveCommandContext, normalizeFormat, makeSpinner } from '../lib/context.js';
|
|
7
|
+
import { isRecord, toObjectTypeSlug } from '../lib/utils.js';
|
|
8
|
+
import * as out from '../lib/output.js';
|
|
9
|
+
import { ErrorCode, exitWithError } from '../lib/error-codes.js';
|
|
10
|
+
import { findGuidance } from '../lib/error-guidance/match.js';
|
|
11
|
+
import { formatGuidanceText } from '../lib/error-guidance/render.js';
|
|
12
|
+
export function buildCreateResourceOutput(type, submittedData, created) {
|
|
13
|
+
const createdResource = isRecord(created) ? created : {};
|
|
14
|
+
const id = typeof createdResource.id === 'string'
|
|
15
|
+
? createdResource.id
|
|
16
|
+
: isRecord(createdResource.data) && typeof createdResource.data.id === 'string'
|
|
17
|
+
? createdResource.data.id
|
|
18
|
+
: undefined;
|
|
19
|
+
const createdData = isRecord(createdResource.data) ? createdResource.data : submittedData;
|
|
20
|
+
return {
|
|
21
|
+
type,
|
|
22
|
+
...createdResource,
|
|
23
|
+
id,
|
|
24
|
+
data: createdData,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function extractPublishedSchemaTypes(payload) {
|
|
28
|
+
if (!isRecord(payload)) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
if (Array.isArray(payload.objectTypes)) {
|
|
32
|
+
return payload.objectTypes
|
|
33
|
+
.filter((value) => isRecord(value) && typeof value.name === 'string')
|
|
34
|
+
.map((value) => ({
|
|
35
|
+
name: value.name,
|
|
36
|
+
slug: typeof value.slug === 'string' ? value.slug : undefined,
|
|
37
|
+
properties: Array.isArray(value.properties) ? value.properties : [],
|
|
38
|
+
linkTypes: Array.isArray(value.linkTypes) ? value.linkTypes : [],
|
|
39
|
+
actions: Array.isArray(value.actions) ? value.actions : [],
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(payload.object_types)) {
|
|
43
|
+
return payload.object_types
|
|
44
|
+
.filter((value) => isRecord(value) && typeof value.name === 'string')
|
|
45
|
+
.map((value) => ({
|
|
46
|
+
name: value.name,
|
|
47
|
+
slug: typeof value.slug === 'string' ? value.slug : undefined,
|
|
48
|
+
properties: Array.isArray(value.properties) ? value.properties : [],
|
|
49
|
+
linkTypes: Array.isArray(value.linkTypes) ? value.linkTypes : [],
|
|
50
|
+
actions: Array.isArray(value.actions) ? value.actions : [],
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
if (!Array.isArray(payload.docs)) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
return payload.docs
|
|
57
|
+
.filter((value) => {
|
|
58
|
+
if (!isRecord(value) || typeof value.name !== 'string') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (value.status === 'published') {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return value.publishedAt !== null && value.publishedAt !== undefined;
|
|
65
|
+
})
|
|
66
|
+
.map((value) => ({
|
|
67
|
+
name: value.name,
|
|
68
|
+
slug: typeof value.slug === 'string' ? value.slug : undefined,
|
|
69
|
+
properties: Array.isArray(value.properties) ? value.properties : [],
|
|
70
|
+
linkTypes: Array.isArray(value.linkTypes) ? value.linkTypes : [],
|
|
71
|
+
actions: Array.isArray(value.actions) ? value.actions : [],
|
|
72
|
+
status: typeof value.status === 'string' ? value.status : undefined,
|
|
73
|
+
publishedAt: typeof value.publishedAt === 'string' ? value.publishedAt : null,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
function failCommand(spinner, message) {
|
|
77
|
+
if (spinner) {
|
|
78
|
+
spinner.fail(message);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
out.error(message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function succeedCommand(spinner, message) {
|
|
85
|
+
if (spinner) {
|
|
86
|
+
spinner.succeed(message);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
out.success(message);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function extractErrorPayload(payload) {
|
|
93
|
+
if (!isRecord(payload)) {
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
const nested = [payload.error, payload.detail, payload];
|
|
97
|
+
const result = {};
|
|
98
|
+
for (const candidate of nested) {
|
|
99
|
+
if (typeof candidate === 'string' && !result.message) {
|
|
100
|
+
result.message = candidate;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!isRecord(candidate)) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (!result.message) {
|
|
107
|
+
const message = candidate.message ?? candidate.detail ?? candidate.error;
|
|
108
|
+
if (typeof message === 'string') {
|
|
109
|
+
result.message = message;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (!result.code && typeof candidate.code === 'string') {
|
|
113
|
+
result.code = candidate.code;
|
|
114
|
+
}
|
|
115
|
+
if (!result.reasonCode) {
|
|
116
|
+
const reasonCode = candidate.reasonCode ?? candidate.reason_code ?? candidate.reason;
|
|
117
|
+
if (typeof reasonCode === 'string') {
|
|
118
|
+
result.reasonCode = reasonCode;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!result.serverCode) {
|
|
122
|
+
const serverCode = candidate.serverCode ?? candidate.server_code;
|
|
123
|
+
if (typeof serverCode === 'string') {
|
|
124
|
+
result.serverCode = serverCode;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
function withGuidance(message, lookup) {
|
|
131
|
+
const guidance = findGuidance(lookup);
|
|
132
|
+
return guidance ? `${message}\n\n${formatGuidanceText(guidance)}` : message;
|
|
133
|
+
}
|
|
134
|
+
async function formatResponseError(res, operation) {
|
|
135
|
+
const text = await res.text();
|
|
136
|
+
if (!text) {
|
|
137
|
+
return withGuidance(`${res.status} ${res.statusText}`, {
|
|
138
|
+
operation,
|
|
139
|
+
status: res.status,
|
|
140
|
+
message: res.statusText,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const payload = JSON.parse(text);
|
|
145
|
+
const errorPayload = extractErrorPayload(payload);
|
|
146
|
+
const message = errorPayload.message;
|
|
147
|
+
const base = `${res.status} ${res.statusText}${message ? ` — ${message}` : ''}`;
|
|
148
|
+
return withGuidance(base, {
|
|
149
|
+
operation,
|
|
150
|
+
status: res.status,
|
|
151
|
+
code: errorPayload.code,
|
|
152
|
+
reasonCode: errorPayload.reasonCode,
|
|
153
|
+
serverCode: errorPayload.serverCode,
|
|
154
|
+
message: message || text.slice(0, 300),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
const message = text.slice(0, 300);
|
|
159
|
+
return withGuidance(`${res.status} ${res.statusText} — ${message}`, {
|
|
160
|
+
operation,
|
|
161
|
+
status: res.status,
|
|
162
|
+
message,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function renderSearchCapabilities(capabilities) {
|
|
167
|
+
const search = capabilities?.search;
|
|
168
|
+
if (!search) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const modeState = (ready) => (ready ? chalk.green('ready') : chalk.yellow('unavailable'));
|
|
172
|
+
out.info(`Search modes: fulltext ${modeState(search.fulltext)}, hybrid ${modeState(search.hybrid)}, vector ${modeState(search.vector)}`);
|
|
173
|
+
if (search.recommendedMode) {
|
|
174
|
+
out.info(`Recommended search mode: ${chalk.cyan(search.recommendedMode)}`);
|
|
175
|
+
}
|
|
176
|
+
if (search.reasonMessage) {
|
|
177
|
+
out.warn(search.reasonMessage);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
export function matchPublishedType(requestedType, schemaTypes) {
|
|
181
|
+
const requestedSlug = toObjectTypeSlug(requestedType);
|
|
182
|
+
const matchedType = schemaTypes.find((schemaType) => (schemaType.name === requestedType
|
|
183
|
+
|| schemaType.slug === requestedSlug
|
|
184
|
+
|| toObjectTypeSlug(schemaType.name) === requestedSlug));
|
|
185
|
+
return {
|
|
186
|
+
requestedType,
|
|
187
|
+
requestedSlug,
|
|
188
|
+
matchedType,
|
|
189
|
+
publishedTypeNames: schemaTypes.map((schemaType) => schemaType.name),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
export function buildMissingPublishedTypeMessage(match) {
|
|
193
|
+
if (match.publishedTypeNames.length === 0) {
|
|
194
|
+
return `No published object types were found for the active tenant. ${match.requestedType} cannot be listed until types are published remotely.`;
|
|
195
|
+
}
|
|
196
|
+
return `Object type "${match.requestedType}" is not published for the active tenant. Published types: ${match.publishedTypeNames.join(', ')}.`;
|
|
197
|
+
}
|
|
198
|
+
async function describeMissingPublishedType(client, requestedType) {
|
|
199
|
+
const schemaResponse = await client.getPublishedObjectTypes();
|
|
200
|
+
if (!schemaResponse.ok) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
const schemaPayload = await schemaResponse.json();
|
|
204
|
+
const match = matchPublishedType(requestedType, extractPublishedSchemaTypes(schemaPayload));
|
|
205
|
+
if (match.matchedType) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
return buildMissingPublishedTypeMessage(match);
|
|
209
|
+
}
|
|
210
|
+
export async function loadJsonInput(options, fieldHint = '--data or --file') {
|
|
211
|
+
if (options.data) {
|
|
212
|
+
return JSON.parse(options.data);
|
|
213
|
+
}
|
|
214
|
+
if (options.file) {
|
|
215
|
+
const { readFile } = await import('node:fs/promises');
|
|
216
|
+
return JSON.parse(await readFile(options.file, 'utf-8'));
|
|
217
|
+
}
|
|
218
|
+
throw new Error(`Missing ${fieldHint}`);
|
|
219
|
+
}
|
|
220
|
+
export function normalizeBatchCreateItems(payload) {
|
|
221
|
+
if (Array.isArray(payload)) {
|
|
222
|
+
return payload.map((item) => ({ data: item }));
|
|
223
|
+
}
|
|
224
|
+
if (isRecord(payload) && Array.isArray(payload.items)) {
|
|
225
|
+
return payload.items.map((item) => (isRecord(item) && isRecord(item.data) ? { data: item.data } : { data: item }));
|
|
226
|
+
}
|
|
227
|
+
if (isRecord(payload)) {
|
|
228
|
+
return [{ data: payload }];
|
|
229
|
+
}
|
|
230
|
+
throw new Error('Batch create payload must be an object, array, or { items } wrapper');
|
|
231
|
+
}
|
|
232
|
+
export function normalizeBatchUpdateItems(payload) {
|
|
233
|
+
const items = Array.isArray(payload)
|
|
234
|
+
? payload
|
|
235
|
+
: isRecord(payload) && Array.isArray(payload.items)
|
|
236
|
+
? payload.items
|
|
237
|
+
: null;
|
|
238
|
+
if (!items) {
|
|
239
|
+
throw new Error('Batch update payload must be an array or { items } wrapper');
|
|
240
|
+
}
|
|
241
|
+
return items.map((item) => {
|
|
242
|
+
if (!isRecord(item) || typeof item.id !== 'string' || !isRecord(item.data) || typeof item.version !== 'number') {
|
|
243
|
+
throw new Error('Batch update items require { id, data, version }');
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
id: item.id,
|
|
247
|
+
data: item.data,
|
|
248
|
+
version: item.version,
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
export function normalizeBatchDeleteIds(payload) {
|
|
253
|
+
if (Array.isArray(payload)) {
|
|
254
|
+
return payload.map((item) => (isRecord(item) && typeof item.id === 'string' ? item.id : String(item)));
|
|
255
|
+
}
|
|
256
|
+
if (isRecord(payload) && Array.isArray(payload.ids)) {
|
|
257
|
+
return payload.ids.map(String);
|
|
258
|
+
}
|
|
259
|
+
throw new Error('Batch delete payload must be an array of ids or { ids }');
|
|
260
|
+
}
|
|
261
|
+
export const resourcesCommand = new Command('resources')
|
|
262
|
+
.description('CRUD operations on platform resources');
|
|
263
|
+
// ─── eai resources list <type> ─────────────────────────────────────────────
|
|
264
|
+
resourcesCommand
|
|
265
|
+
.command('list <type>')
|
|
266
|
+
.description('List resources of a given type')
|
|
267
|
+
.option('--tenant-id <id>', 'Run the read-only query against a specific tenant')
|
|
268
|
+
.option('--page <n>', 'Page number', '1')
|
|
269
|
+
.option('--limit <n>', 'Items per page', '20')
|
|
270
|
+
.option('--sort <field>', 'Sort field (prefix with - for descending)', '-created_at')
|
|
271
|
+
.option('--where <json>', 'Structured where filter as JSON')
|
|
272
|
+
.option('--cursor <cursor>', 'Opaque cursor from a previous response')
|
|
273
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
274
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
275
|
+
.addHelpText('after', `
|
|
276
|
+
Examples:
|
|
277
|
+
$ eai resources list User
|
|
278
|
+
$ eai resources list Project --limit 10
|
|
279
|
+
$ eai resources list User --tenant-id 00000000-0000-4000-8000-000000000000
|
|
280
|
+
$ eai resources list User --format json | jq '.resources[] | .id'
|
|
281
|
+
`)
|
|
282
|
+
.action(async (type, options) => {
|
|
283
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
284
|
+
options.format = normalizeFormat(options);
|
|
285
|
+
const spinner = makeSpinner(options.format, `Listing ${type}...`);
|
|
286
|
+
try {
|
|
287
|
+
const res = await ctx.client.listResources(type, {
|
|
288
|
+
page: parseInt(options.page),
|
|
289
|
+
limit: parseInt(options.limit),
|
|
290
|
+
sort: options.sort,
|
|
291
|
+
where: options.where ? JSON.parse(options.where) : undefined,
|
|
292
|
+
cursor: options.cursor,
|
|
293
|
+
});
|
|
294
|
+
if (!res.ok) {
|
|
295
|
+
let message = `Failed: ${res.status} ${res.statusText}`;
|
|
296
|
+
if (res.status === 404) {
|
|
297
|
+
const publishedTypeMessage = await describeMissingPublishedType(ctx.client, type);
|
|
298
|
+
if (publishedTypeMessage) {
|
|
299
|
+
message = publishedTypeMessage;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
failCommand(spinner, message);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
const data = await res.json();
|
|
306
|
+
if (options.format === 'json') {
|
|
307
|
+
out.json({
|
|
308
|
+
type,
|
|
309
|
+
resources: data.docs,
|
|
310
|
+
totalDocs: data.totalDocs,
|
|
311
|
+
page: data.page,
|
|
312
|
+
totalPages: data.totalPages,
|
|
313
|
+
nextCursor: data.nextCursor ?? null,
|
|
314
|
+
});
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
succeedCommand(spinner, `${data.totalDocs} total — page ${data.page}/${data.totalPages}`);
|
|
318
|
+
if (data.docs.length === 0) {
|
|
319
|
+
out.info('No resources found.');
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
for (const doc of data.docs) {
|
|
323
|
+
const preview = Object.entries(doc.data)
|
|
324
|
+
.slice(0, 3)
|
|
325
|
+
.map(([k, v]) => `${k}=${chalk.dim(String(v).slice(0, 30))}`)
|
|
326
|
+
.join(', ');
|
|
327
|
+
out.info(`${chalk.cyan(doc.id)} — ${preview}`);
|
|
328
|
+
}
|
|
329
|
+
if (data.nextCursor) {
|
|
330
|
+
out.dim(`nextCursor=${data.nextCursor}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
resourcesCommand
|
|
339
|
+
.command('batch-create <type>')
|
|
340
|
+
.description('Create resources in bulk')
|
|
341
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
342
|
+
.option('--data <json>', 'Batch payload as JSON array or object')
|
|
343
|
+
.option('--file <path>', 'Read batch payload from JSON file')
|
|
344
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
345
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
346
|
+
.action(async (type, options) => {
|
|
347
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
348
|
+
options.format = normalizeFormat(options);
|
|
349
|
+
try {
|
|
350
|
+
const payload = await loadJsonInput(options);
|
|
351
|
+
const items = normalizeBatchCreateItems(payload);
|
|
352
|
+
const spinner = makeSpinner(options.format, `Batch creating ${type}...`);
|
|
353
|
+
const res = await ctx.client.batchCreateResources(type, items);
|
|
354
|
+
if (!res.ok) {
|
|
355
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
const data = await res.json();
|
|
359
|
+
if (options.format === 'json') {
|
|
360
|
+
out.json(data);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
succeedCommand(spinner, `Batch create complete (${data.succeeded} succeeded, ${data.failed} failed)`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
resourcesCommand
|
|
372
|
+
.command('batch-update <type>')
|
|
373
|
+
.description('Update resources in bulk')
|
|
374
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
375
|
+
.option('--data <json>', 'Batch payload as JSON array or object')
|
|
376
|
+
.option('--file <path>', 'Read batch payload from JSON file')
|
|
377
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
378
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
379
|
+
.action(async (type, options) => {
|
|
380
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
381
|
+
options.format = normalizeFormat(options);
|
|
382
|
+
try {
|
|
383
|
+
const payload = await loadJsonInput(options);
|
|
384
|
+
const items = normalizeBatchUpdateItems(payload);
|
|
385
|
+
const spinner = makeSpinner(options.format, `Batch updating ${type}...`);
|
|
386
|
+
const res = await ctx.client.batchUpdateResources(type, items);
|
|
387
|
+
if (!res.ok) {
|
|
388
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
const data = await res.json();
|
|
392
|
+
if (options.format === 'json') {
|
|
393
|
+
out.json(data);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
succeedCommand(spinner, `Batch update complete (${data.succeeded} succeeded, ${data.failed} failed)`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch (err) {
|
|
400
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
401
|
+
process.exit(1);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
resourcesCommand
|
|
405
|
+
.command('batch-delete <type>')
|
|
406
|
+
.description('Delete resources in bulk')
|
|
407
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
408
|
+
.option('--ids <csv>', 'Comma-separated ids to delete')
|
|
409
|
+
.option('--data <json>', 'Batch payload as JSON array or object')
|
|
410
|
+
.option('--file <path>', 'Read batch payload from JSON file')
|
|
411
|
+
.option('--force', 'Accepted for parity with resources delete; batch delete is non-interactive', false)
|
|
412
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
413
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
414
|
+
.action(async (type, options) => {
|
|
415
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
416
|
+
options.format = normalizeFormat(options);
|
|
417
|
+
try {
|
|
418
|
+
const ids = options.ids
|
|
419
|
+
? String(options.ids).split(',').map((value) => value.trim()).filter(Boolean)
|
|
420
|
+
: normalizeBatchDeleteIds(await loadJsonInput(options));
|
|
421
|
+
const spinner = makeSpinner(options.format, `Batch deleting ${type}...`);
|
|
422
|
+
const res = await ctx.client.batchDeleteResources(type, ids);
|
|
423
|
+
if (!res.ok) {
|
|
424
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
const data = await res.json();
|
|
428
|
+
if (options.format === 'json') {
|
|
429
|
+
out.json(data);
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
succeedCommand(spinner, `Batch delete complete (${data.succeeded} succeeded, ${data.failed} failed)`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
resourcesCommand
|
|
441
|
+
.command('aggregate <type>')
|
|
442
|
+
.description('Run a server-side aggregate query')
|
|
443
|
+
.option('--tenant-id <id>', 'Run the read-only query against a specific tenant')
|
|
444
|
+
.requiredOption('--group-by <fields>', 'Comma-separated groupBy fields')
|
|
445
|
+
.requiredOption('--metrics <json>', 'Aggregate metrics JSON')
|
|
446
|
+
.option('--where <json>', 'Structured where filter as JSON')
|
|
447
|
+
.option('--limit <n>', 'Max summary rows', '1000')
|
|
448
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
449
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
450
|
+
.action(async (type, options) => {
|
|
451
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
452
|
+
options.format = normalizeFormat(options);
|
|
453
|
+
try {
|
|
454
|
+
const res = await ctx.client.aggregateResources(type, {
|
|
455
|
+
groupBy: String(options.groupBy).split(',').map((value) => value.trim()).filter(Boolean),
|
|
456
|
+
metrics: JSON.parse(options.metrics),
|
|
457
|
+
where: options.where ? JSON.parse(options.where) : undefined,
|
|
458
|
+
limit: parseInt(options.limit),
|
|
459
|
+
});
|
|
460
|
+
if (!res.ok) {
|
|
461
|
+
failCommand(null, await formatResponseError(res, 'resources.aggregate'));
|
|
462
|
+
process.exit(1);
|
|
463
|
+
}
|
|
464
|
+
const data = await res.json();
|
|
465
|
+
if (options.format === 'json') {
|
|
466
|
+
out.json(data);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
out.success(`${data.totalRows} aggregate rows`);
|
|
470
|
+
for (const row of data.rows.slice(0, 20)) {
|
|
471
|
+
out.info(JSON.stringify(row));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
477
|
+
process.exit(1);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
// ─── eai resources get <type> <id> ────────────────────────────────────────
|
|
481
|
+
resourcesCommand
|
|
482
|
+
.command('get <type> <id>')
|
|
483
|
+
.description('Get a single resource')
|
|
484
|
+
.option('--tenant-id <id>', 'Run the read-only query against a specific tenant')
|
|
485
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
486
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
487
|
+
.action(async (type, id, options) => {
|
|
488
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
489
|
+
options.format = normalizeFormat(options);
|
|
490
|
+
try {
|
|
491
|
+
const res = await ctx.client.getResource(type, id);
|
|
492
|
+
if (!res.ok) {
|
|
493
|
+
out.error(`${res.status} ${res.statusText}`);
|
|
494
|
+
process.exit(1);
|
|
495
|
+
}
|
|
496
|
+
const data = await res.json();
|
|
497
|
+
if (options.format === 'json') {
|
|
498
|
+
out.json(data);
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
out.heading(`${type}: ${id}`);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
catch (err) {
|
|
505
|
+
out.error(err instanceof Error ? err.message : String(err));
|
|
506
|
+
process.exit(1);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
// ─── eai resources create <type> ──────────────────────────────────────────
|
|
510
|
+
resourcesCommand
|
|
511
|
+
.command('create <type>')
|
|
512
|
+
.description('Create a new resource')
|
|
513
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
514
|
+
.option('--data <json>', 'Resource data as JSON string')
|
|
515
|
+
.option('--file <path>', 'Read data from JSON file')
|
|
516
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
517
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
518
|
+
.addHelpText('after', `
|
|
519
|
+
Examples:
|
|
520
|
+
$ eai resources create Project --data '{"name":"Demo","description":"Test project"}'
|
|
521
|
+
$ eai resources create User --file user.json
|
|
522
|
+
$ eai resources create Project --tenant-id 00000000-0000-4000-8000-000000000000 --data '{"name":"Demo"}'
|
|
523
|
+
$ eai resources create Project --data '{"name":"Demo"}' --format json
|
|
524
|
+
`)
|
|
525
|
+
.action(async (type, options) => {
|
|
526
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
527
|
+
options.format = normalizeFormat(options);
|
|
528
|
+
let data;
|
|
529
|
+
if (options.data) {
|
|
530
|
+
data = JSON.parse(options.data);
|
|
531
|
+
}
|
|
532
|
+
else if (options.file) {
|
|
533
|
+
const { readFile } = await import('node:fs/promises');
|
|
534
|
+
data = JSON.parse(await readFile(options.file, 'utf-8'));
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
exitWithError(ErrorCode.E303, { field: '--data or --file' }, options.format);
|
|
538
|
+
}
|
|
539
|
+
const spinner = makeSpinner(options.format, `Creating ${type}...`);
|
|
540
|
+
try {
|
|
541
|
+
const res = await ctx.client.createResource(type, data);
|
|
542
|
+
if (!res.ok) {
|
|
543
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
544
|
+
const body = await res.text();
|
|
545
|
+
out.error(body);
|
|
546
|
+
process.exit(1);
|
|
547
|
+
}
|
|
548
|
+
const created = await res.json();
|
|
549
|
+
const output = buildCreateResourceOutput(type, data, created);
|
|
550
|
+
if (options.format === 'json') {
|
|
551
|
+
out.json(output);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
const createdId = typeof output.id === 'string' ? output.id : undefined;
|
|
555
|
+
succeedCommand(spinner, `Created ${type} ${chalk.dim(createdId ?? '')}`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
560
|
+
process.exit(1);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
// ─── eai resources update <type> <id> ────────────────────────────────────
|
|
564
|
+
resourcesCommand
|
|
565
|
+
.command('update <type> <id>')
|
|
566
|
+
.description('Update a resource')
|
|
567
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
568
|
+
.option('--data <json>', 'Updated data as JSON string')
|
|
569
|
+
.option('--version <n>', 'Resource version (for optimistic locking)')
|
|
570
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
571
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
572
|
+
.action(async (type, id, options) => {
|
|
573
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
574
|
+
options.format = normalizeFormat(options);
|
|
575
|
+
if (!options.data) {
|
|
576
|
+
exitWithError(ErrorCode.E303, { field: '--data' }, options.format);
|
|
577
|
+
}
|
|
578
|
+
const data = JSON.parse(options.data);
|
|
579
|
+
let version = options.version ? parseInt(options.version) : undefined;
|
|
580
|
+
// Auto-fetch version if not provided
|
|
581
|
+
if (version === undefined) {
|
|
582
|
+
const getRes = await ctx.client.getResource(type, id);
|
|
583
|
+
if (getRes.ok) {
|
|
584
|
+
const existing = await getRes.json();
|
|
585
|
+
version = existing.version;
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
exitWithError(ErrorCode.E203, { details: 'Could not fetch current resource version. Use --version explicitly.' }, options.format);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
const spinner = makeSpinner(options.format, `Updating ${type} ${id}...`);
|
|
592
|
+
try {
|
|
593
|
+
const res = await ctx.client.updateResource(type, id, data, version);
|
|
594
|
+
if (!res.ok) {
|
|
595
|
+
failCommand(spinner, await formatResponseError(res, 'resources.update'));
|
|
596
|
+
process.exit(1);
|
|
597
|
+
}
|
|
598
|
+
if (options.format === 'json') {
|
|
599
|
+
out.json({ type, id, data, version });
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
succeedCommand(spinner, `Updated ${type} ${chalk.dim(id)}`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (err) {
|
|
606
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
607
|
+
process.exit(1);
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
// ─── eai resources delete <type> <id> ────────────────────────────────────
|
|
611
|
+
resourcesCommand
|
|
612
|
+
.command('delete <type> <id>')
|
|
613
|
+
.description('Delete a resource')
|
|
614
|
+
.option('--tenant-id <id>', 'Run the mutation against a specific tenant')
|
|
615
|
+
.option('--force', 'Skip confirmation', false)
|
|
616
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
617
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
618
|
+
.action(async (type, id, options) => {
|
|
619
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
620
|
+
options.format = normalizeFormat(options);
|
|
621
|
+
if (!options.force) {
|
|
622
|
+
const inquirer = await import('inquirer');
|
|
623
|
+
const { confirm } = await inquirer.default.prompt([{
|
|
624
|
+
type: 'confirm',
|
|
625
|
+
name: 'confirm',
|
|
626
|
+
message: `Delete ${type} ${id}?`,
|
|
627
|
+
default: false,
|
|
628
|
+
}]);
|
|
629
|
+
if (!confirm) {
|
|
630
|
+
if (options.format === 'json') {
|
|
631
|
+
out.json({ cancelled: true });
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
out.info('Cancelled.');
|
|
635
|
+
}
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
const spinner = makeSpinner(options.format, `Deleting ${type} ${id}...`);
|
|
640
|
+
try {
|
|
641
|
+
const res = await ctx.client.deleteResource(type, id);
|
|
642
|
+
if (!res.ok) {
|
|
643
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
644
|
+
process.exit(1);
|
|
645
|
+
}
|
|
646
|
+
if (options.format === 'json') {
|
|
647
|
+
out.json({ type, id, deleted: true });
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
succeedCommand(spinner, `Deleted ${type} ${chalk.dim(id)}`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
catch (err) {
|
|
654
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
655
|
+
process.exit(1);
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
// ─── eai resources query ──────────────────────────────────────────────────
|
|
659
|
+
resourcesCommand
|
|
660
|
+
.command('query')
|
|
661
|
+
.description('Cross-type query')
|
|
662
|
+
.option('--tenant-id <id>', 'Run the read-only query against a specific tenant')
|
|
663
|
+
.requiredOption('--types <types>', 'Comma-separated object type names')
|
|
664
|
+
.option('--where <json>', 'Filter conditions as JSON')
|
|
665
|
+
.option('--limit <n>', 'Max results', '20')
|
|
666
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
667
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
668
|
+
.action(async (options) => {
|
|
669
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
670
|
+
options.format = normalizeFormat(options);
|
|
671
|
+
const objectTypes = options.types.split(',').map((t) => t.trim());
|
|
672
|
+
const where = options.where ? JSON.parse(options.where) : undefined;
|
|
673
|
+
const spinner = makeSpinner(options.format, `Querying ${objectTypes.join(', ')}...`);
|
|
674
|
+
try {
|
|
675
|
+
const res = await ctx.client.queryResources({
|
|
676
|
+
object_types: objectTypes,
|
|
677
|
+
where,
|
|
678
|
+
limit: parseInt(options.limit),
|
|
679
|
+
});
|
|
680
|
+
if (!res.ok) {
|
|
681
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
682
|
+
process.exit(1);
|
|
683
|
+
}
|
|
684
|
+
const data = await res.json();
|
|
685
|
+
if (options.format === 'json') {
|
|
686
|
+
out.json(data);
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
succeedCommand(spinner, 'Query complete');
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
catch (err) {
|
|
693
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
694
|
+
process.exit(1);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
// ─── eai resources storage ────────────────────────────────────────────────
|
|
698
|
+
const storageCommand = resourcesCommand
|
|
699
|
+
.command('storage')
|
|
700
|
+
.description('Storage provisioning status and diagnostics');
|
|
701
|
+
storageCommand
|
|
702
|
+
.command('status')
|
|
703
|
+
.description('Show storage routing and provisioning status')
|
|
704
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
705
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
706
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
707
|
+
.action(async (options) => {
|
|
708
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
709
|
+
options.format = normalizeFormat(options);
|
|
710
|
+
const spinner = makeSpinner(options.format, 'Fetching storage status...');
|
|
711
|
+
const res = await ctx.client.getResourceStorageStatus();
|
|
712
|
+
if (!res.ok) {
|
|
713
|
+
failCommand(spinner, await formatResponseError(res, 'resources.storage.status'));
|
|
714
|
+
process.exit(1);
|
|
715
|
+
}
|
|
716
|
+
const payload = await res.json();
|
|
717
|
+
if (options.format === 'json') {
|
|
718
|
+
out.json(payload);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
succeedCommand(spinner, `Storage status for tenant ${payload.tenantId || ctx.tenantId}`);
|
|
722
|
+
for (const item of payload.objectTypes || []) {
|
|
723
|
+
const status = item.isReady ? chalk.green('ready') : chalk.yellow('not ready');
|
|
724
|
+
out.info(`${chalk.cyan(item.objectType)} ${chalk.dim(item.backend)} ${status}`);
|
|
725
|
+
for (const issue of item.issues || []) {
|
|
726
|
+
out.warn(` ${issue}`);
|
|
727
|
+
}
|
|
728
|
+
for (const warning of item.warnings || []) {
|
|
729
|
+
out.warn(` warning: ${warning}`);
|
|
730
|
+
}
|
|
731
|
+
renderSearchCapabilities(item.capabilities);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
storageCommand
|
|
735
|
+
.command('doctor')
|
|
736
|
+
.description('Run storage diagnostics')
|
|
737
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
738
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
739
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
740
|
+
.action(async (options) => {
|
|
741
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
742
|
+
options.format = normalizeFormat(options);
|
|
743
|
+
const spinner = makeSpinner(options.format, 'Running storage doctor...');
|
|
744
|
+
const res = await ctx.client.getResourceStorageDoctor();
|
|
745
|
+
if (!res.ok) {
|
|
746
|
+
failCommand(spinner, await formatResponseError(res, 'resources.storage.doctor'));
|
|
747
|
+
process.exit(1);
|
|
748
|
+
}
|
|
749
|
+
const payload = await res.json();
|
|
750
|
+
if (options.format === 'json') {
|
|
751
|
+
out.json(payload);
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
if (payload.healthy) {
|
|
755
|
+
succeedCommand(spinner, 'Storage doctor passed');
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
failCommand(spinner, 'Storage doctor found issues');
|
|
759
|
+
}
|
|
760
|
+
for (const check of payload.checks || []) {
|
|
761
|
+
const state = check.healthy ? chalk.green('healthy') : chalk.red('unhealthy');
|
|
762
|
+
out.info(`${chalk.cyan(check.objectType)} ${chalk.dim(check.backend)} ${state}`);
|
|
763
|
+
for (const issue of check.issues || []) {
|
|
764
|
+
out.warn(` ${issue}`);
|
|
765
|
+
}
|
|
766
|
+
for (const warning of check.warnings || []) {
|
|
767
|
+
out.warn(` warning: ${warning}`);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
renderSearchCapabilities(payload.capabilities);
|
|
771
|
+
if (!payload.healthy) {
|
|
772
|
+
process.exit(1);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
// ─── eai resources search <query> ─────────────────────────────────────────
|
|
776
|
+
resourcesCommand
|
|
777
|
+
.command('search <query>')
|
|
778
|
+
.description('Search tenant resource projections')
|
|
779
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
780
|
+
.option('--types <types>', 'Comma-separated object type names')
|
|
781
|
+
.option('--mode <mode>', 'Search mode: fulltext|hybrid|vector', 'hybrid')
|
|
782
|
+
.option('--hybrid', 'Use hybrid full-text + vector search', false)
|
|
783
|
+
.option('--vector', 'Use vector-only search', false)
|
|
784
|
+
.option('--fulltext', 'Use full-text-only search', false)
|
|
785
|
+
.option('--limit <n>', 'Max results', '10')
|
|
786
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
787
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
788
|
+
.action(async (query, options) => {
|
|
789
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
790
|
+
options.format = normalizeFormat(options);
|
|
791
|
+
const mode = options.vector ? 'vector' : options.fulltext ? 'fulltext' : options.hybrid ? 'hybrid' : options.mode;
|
|
792
|
+
const objectTypes = options.types
|
|
793
|
+
? String(options.types).split(',').map((item) => item.trim()).filter(Boolean)
|
|
794
|
+
: undefined;
|
|
795
|
+
const spinner = makeSpinner(options.format, 'Searching resources...');
|
|
796
|
+
const res = await ctx.client.searchResources({
|
|
797
|
+
query,
|
|
798
|
+
objectTypes,
|
|
799
|
+
mode,
|
|
800
|
+
limit: parseInt(options.limit),
|
|
801
|
+
includePayload: true,
|
|
802
|
+
});
|
|
803
|
+
if (!res.ok) {
|
|
804
|
+
failCommand(spinner, await formatResponseError(res, 'resources.search'));
|
|
805
|
+
process.exit(1);
|
|
806
|
+
}
|
|
807
|
+
const payload = await res.json();
|
|
808
|
+
if (options.format === 'json') {
|
|
809
|
+
out.json(payload);
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
succeedCommand(spinner, `${payload.results?.length || 0} result(s) from ${payload.indexName || 'search'}`);
|
|
813
|
+
for (const hit of payload.results || []) {
|
|
814
|
+
out.info(`${chalk.cyan(hit.id)} ${chalk.dim(hit.objectType)} score=${hit.score ?? 'n/a'}`);
|
|
815
|
+
if (hit.content) {
|
|
816
|
+
out.dim(` ${String(hit.content).slice(0, 160)}`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
// ─── eai resources file ───────────────────────────────────────────────────
|
|
821
|
+
const fileCommand = resourcesCommand
|
|
822
|
+
.command('file')
|
|
823
|
+
.description('Upload, download, and delete Blob-backed resource files');
|
|
824
|
+
fileCommand
|
|
825
|
+
.command('upload <type> <id> <property> <path>')
|
|
826
|
+
.description('Upload a file to a resource file property')
|
|
827
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
828
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
829
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
830
|
+
.action(async (type, id, property, filePath, options) => {
|
|
831
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
832
|
+
options.format = normalizeFormat(options);
|
|
833
|
+
const spinner = makeSpinner(options.format, `Uploading ${filePath}...`);
|
|
834
|
+
const res = await ctx.client.uploadResourceFile(type, id, property, filePath);
|
|
835
|
+
if (!res.ok) {
|
|
836
|
+
failCommand(spinner, await formatResponseError(res));
|
|
837
|
+
process.exit(1);
|
|
838
|
+
}
|
|
839
|
+
const payload = await res.json();
|
|
840
|
+
if (options.format === 'json') {
|
|
841
|
+
out.json(payload);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
succeedCommand(spinner, `Uploaded ${payload.filename || filePath} to ${type}.${property}`);
|
|
845
|
+
if (payload.blobRef) {
|
|
846
|
+
out.info(`Blob: ${chalk.dim(payload.blobRef)}`);
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
fileCommand
|
|
850
|
+
.command('get <type> <id> <property>')
|
|
851
|
+
.description('Download a resource file property')
|
|
852
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
853
|
+
.option('--output <path>', 'Write to a specific file path')
|
|
854
|
+
.action(async (type, id, property, options) => {
|
|
855
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
856
|
+
const spinner = makeSpinner('text', `Downloading ${type}.${property}...`);
|
|
857
|
+
const res = await ctx.client.downloadResourceFile(type, id, property);
|
|
858
|
+
if (!res.ok) {
|
|
859
|
+
failCommand(spinner, await formatResponseError(res));
|
|
860
|
+
process.exit(1);
|
|
861
|
+
}
|
|
862
|
+
const { writeFile } = await import('node:fs/promises');
|
|
863
|
+
const contentDisposition = res.headers.get('content-disposition') || '';
|
|
864
|
+
const filenameMatch = contentDisposition.match(/filename="?([^";]+)"?/i);
|
|
865
|
+
const outputPath = options.output || filenameMatch?.[1] || `${id}-${property}`;
|
|
866
|
+
await writeFile(outputPath, Buffer.from(await res.arrayBuffer()));
|
|
867
|
+
succeedCommand(spinner, `Downloaded to ${outputPath}`);
|
|
868
|
+
});
|
|
869
|
+
fileCommand
|
|
870
|
+
.command('delete <type> <id> <property>')
|
|
871
|
+
.description('Delete a resource file property')
|
|
872
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
873
|
+
.option('--force', 'Skip confirmation', false)
|
|
874
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
875
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
876
|
+
.action(async (type, id, property, options) => {
|
|
877
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
878
|
+
options.format = normalizeFormat(options);
|
|
879
|
+
if (!options.force) {
|
|
880
|
+
const inquirer = await import('inquirer');
|
|
881
|
+
const { confirm } = await inquirer.default.prompt([{
|
|
882
|
+
type: 'confirm',
|
|
883
|
+
name: 'confirm',
|
|
884
|
+
message: `Delete file ${type}.${property} on ${id}?`,
|
|
885
|
+
default: false,
|
|
886
|
+
}]);
|
|
887
|
+
if (!confirm) {
|
|
888
|
+
out.info('Cancelled.');
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
const spinner = makeSpinner(options.format, `Deleting ${type}.${property} file...`);
|
|
893
|
+
const res = await ctx.client.deleteResourceFile(type, id, property);
|
|
894
|
+
if (!res.ok) {
|
|
895
|
+
failCommand(spinner, await formatResponseError(res));
|
|
896
|
+
process.exit(1);
|
|
897
|
+
}
|
|
898
|
+
const payload = await res.json();
|
|
899
|
+
if (options.format === 'json') {
|
|
900
|
+
out.json(payload);
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
succeedCommand(spinner, `Deleted file on ${type}.${property}`);
|
|
904
|
+
});
|
|
905
|
+
// ─── eai resources schema ─────────────────────────────────────────────────
|
|
906
|
+
resourcesCommand
|
|
907
|
+
.command('schema')
|
|
908
|
+
.description('Show published Object Types for tenant')
|
|
909
|
+
.option('--tenant-id <id>', 'Run the read-only query against a specific tenant')
|
|
910
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
911
|
+
.option('--json', 'Output raw JSON (deprecated, use --format json)', false)
|
|
912
|
+
.action(async (options) => {
|
|
913
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
914
|
+
options.format = normalizeFormat(options);
|
|
915
|
+
const spinner = makeSpinner(options.format, 'Fetching schema...');
|
|
916
|
+
try {
|
|
917
|
+
const res = await ctx.client.getSchema();
|
|
918
|
+
if (!res.ok) {
|
|
919
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
920
|
+
process.exit(1);
|
|
921
|
+
}
|
|
922
|
+
const payload = await res.json();
|
|
923
|
+
const types = extractPublishedSchemaTypes(payload);
|
|
924
|
+
if (options.format === 'json') {
|
|
925
|
+
out.json({ objectTypes: types, count: types.length });
|
|
926
|
+
}
|
|
927
|
+
else {
|
|
928
|
+
succeedCommand(spinner, `${types.length} published types`);
|
|
929
|
+
for (const t of types) {
|
|
930
|
+
const slug = t.slug ? chalk.dim(` (${t.slug})`) : '';
|
|
931
|
+
out.info(`${chalk.cyan(t.name)}${slug} — ${t.properties.length} properties, ${t.linkTypes.length} links`);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
catch (err) {
|
|
936
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
937
|
+
process.exit(1);
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
resourcesCommand
|
|
941
|
+
.command('sync-schema')
|
|
942
|
+
.description('Provision or reconcile storage resources from published Object Type metadata')
|
|
943
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
944
|
+
.option('--backend <backend>', 'Limit to a backend (postgresql|documentdb|blob|search)')
|
|
945
|
+
.option('--dry-run', 'Show the reconcile plan without mutating storage', false)
|
|
946
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
947
|
+
.action(async (options) => {
|
|
948
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
949
|
+
options.format = normalizeFormat(options);
|
|
950
|
+
const spinner = makeSpinner(options.format, 'Syncing storage schema...');
|
|
951
|
+
try {
|
|
952
|
+
const res = await ctx.client.syncStorageSchema({
|
|
953
|
+
backend: options.backend,
|
|
954
|
+
dryRun: Boolean(options.dryRun),
|
|
955
|
+
});
|
|
956
|
+
if (!res.ok) {
|
|
957
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
958
|
+
process.exit(1);
|
|
959
|
+
}
|
|
960
|
+
const payload = await res.json();
|
|
961
|
+
if (options.format === 'json') {
|
|
962
|
+
out.json(payload);
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
succeedCommand(spinner, `${payload.results.length} storage binding${payload.results.length === 1 ? '' : 's'} processed`);
|
|
966
|
+
for (const result of payload.results) {
|
|
967
|
+
const actions = result.actions?.length ? chalk.dim(` — ${result.actions.join(', ')}`) : '';
|
|
968
|
+
out.info(`${chalk.cyan(result.objectType)} [${result.backend}] ${result.status}${actions}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
catch (err) {
|
|
973
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
974
|
+
process.exit(1);
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
resourcesCommand
|
|
978
|
+
.command('doctor')
|
|
979
|
+
.description('Inspect storage readiness for the active tenant')
|
|
980
|
+
.option('--tenant-id <id>', 'Run against a specific tenant')
|
|
981
|
+
.option('--format <format>', 'Output format (text|json)', 'text')
|
|
982
|
+
.action(async (options) => {
|
|
983
|
+
const ctx = await resolveCommandContext({ tenantId: options.tenantId, interactive: !options.tenantId });
|
|
984
|
+
options.format = normalizeFormat(options);
|
|
985
|
+
const spinner = makeSpinner(options.format, 'Checking storage readiness...');
|
|
986
|
+
try {
|
|
987
|
+
const res = await ctx.client.getStorageDoctor();
|
|
988
|
+
if (!res.ok) {
|
|
989
|
+
failCommand(spinner, `${res.status} ${res.statusText}`);
|
|
990
|
+
process.exit(1);
|
|
991
|
+
}
|
|
992
|
+
const payload = await res.json();
|
|
993
|
+
if (options.format === 'json') {
|
|
994
|
+
out.json(payload);
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
succeedCommand(spinner, payload.healthy ? 'Storage is healthy' : 'Storage requires attention');
|
|
998
|
+
for (const check of payload.checks) {
|
|
999
|
+
const status = check.healthy ? chalk.green('healthy') : chalk.yellow('needs-attention');
|
|
1000
|
+
const issues = check.issues?.length ? chalk.dim(` — ${check.issues.join('; ')}`) : '';
|
|
1001
|
+
out.info(`${chalk.cyan(check.objectType)} [${check.backend}] ${status}${issues}`);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
catch (err) {
|
|
1006
|
+
failCommand(spinner, err instanceof Error ? err.message : String(err));
|
|
1007
|
+
process.exit(1);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
//# sourceMappingURL=resources.js.map
|