@specforge/canary-cli 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 +781 -0
- package/bin/specforge +21 -0
- package/dist/channel.d.ts +27 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +22 -0
- package/dist/channel.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +16 -0
- package/dist/cli/commands/configure.d.ts.map +1 -0
- package/dist/cli/commands/configure.js +186 -0
- package/dist/cli/commands/configure.js.map +1 -0
- package/dist/cli/commands/configure.types.d.ts +110 -0
- package/dist/cli/commands/configure.types.d.ts.map +1 -0
- package/dist/cli/commands/configure.types.js +82 -0
- package/dist/cli/commands/configure.types.js.map +1 -0
- package/dist/cli/commands/debug/call.d.ts +14 -0
- package/dist/cli/commands/debug/call.d.ts.map +1 -0
- package/dist/cli/commands/debug/call.js +96 -0
- package/dist/cli/commands/debug/call.js.map +1 -0
- package/dist/cli/commands/debug/index.d.ts +12 -0
- package/dist/cli/commands/debug/index.d.ts.map +1 -0
- package/dist/cli/commands/debug/index.js +14 -0
- package/dist/cli/commands/debug/index.js.map +1 -0
- package/dist/cli/commands/debug/register.d.ts +11 -0
- package/dist/cli/commands/debug/register.d.ts.map +1 -0
- package/dist/cli/commands/debug/register.js +78 -0
- package/dist/cli/commands/debug/register.js.map +1 -0
- package/dist/cli/commands/debug/test.d.ts +13 -0
- package/dist/cli/commands/debug/test.d.ts.map +1 -0
- package/dist/cli/commands/debug/test.js +91 -0
- package/dist/cli/commands/debug/test.js.map +1 -0
- package/dist/cli/commands/debug/tools.d.ts +13 -0
- package/dist/cli/commands/debug/tools.d.ts.map +1 -0
- package/dist/cli/commands/debug/tools.js +86 -0
- package/dist/cli/commands/debug/tools.js.map +1 -0
- package/dist/cli/commands/debug/types.d.ts +119 -0
- package/dist/cli/commands/debug/types.d.ts.map +1 -0
- package/dist/cli/commands/debug/types.js +36 -0
- package/dist/cli/commands/debug/types.js.map +1 -0
- package/dist/cli/commands/debug/whoami.d.ts +13 -0
- package/dist/cli/commands/debug/whoami.d.ts.map +1 -0
- package/dist/cli/commands/debug/whoami.js +131 -0
- package/dist/cli/commands/debug/whoami.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +16 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +413 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/doctor.types.d.ts +180 -0
- package/dist/cli/commands/doctor.types.d.ts.map +1 -0
- package/dist/cli/commands/doctor.types.js +140 -0
- package/dist/cli/commands/doctor.types.js.map +1 -0
- package/dist/cli/commands/feedback.d.ts +27 -0
- package/dist/cli/commands/feedback.d.ts.map +1 -0
- package/dist/cli/commands/feedback.js +262 -0
- package/dist/cli/commands/feedback.js.map +1 -0
- package/dist/cli/commands/feedback.types.d.ts +116 -0
- package/dist/cli/commands/feedback.types.d.ts.map +1 -0
- package/dist/cli/commands/feedback.types.js +65 -0
- package/dist/cli/commands/feedback.types.js.map +1 -0
- package/dist/cli/commands/index.d.ts +15 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +21 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +17 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +773 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/init.types.d.ts +193 -0
- package/dist/cli/commands/init.types.d.ts.map +1 -0
- package/dist/cli/commands/init.types.js +29 -0
- package/dist/cli/commands/init.types.js.map +1 -0
- package/dist/cli/commands/invitations.d.ts +31 -0
- package/dist/cli/commands/invitations.d.ts.map +1 -0
- package/dist/cli/commands/invitations.js +250 -0
- package/dist/cli/commands/invitations.js.map +1 -0
- package/dist/cli/commands/login.d.ts +40 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +139 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/members.d.ts +55 -0
- package/dist/cli/commands/members.d.ts.map +1 -0
- package/dist/cli/commands/members.js +296 -0
- package/dist/cli/commands/members.js.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts +54 -0
- package/dist/cli/commands/scaffold/agent-types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/agent-types.js +22 -0
- package/dist/cli/commands/scaffold/agent-types.js.map +1 -0
- package/dist/cli/commands/scaffold/display.d.ts +56 -0
- package/dist/cli/commands/scaffold/display.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/display.js +217 -0
- package/dist/cli/commands/scaffold/display.js.map +1 -0
- package/dist/cli/commands/scaffold/files.d.ts +99 -0
- package/dist/cli/commands/scaffold/files.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/files.js +122 -0
- package/dist/cli/commands/scaffold/files.js.map +1 -0
- package/dist/cli/commands/scaffold/index.d.ts +13 -0
- package/dist/cli/commands/scaffold/index.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/index.js +12 -0
- package/dist/cli/commands/scaffold/index.js.map +1 -0
- package/dist/cli/commands/scaffold/register.d.ts +11 -0
- package/dist/cli/commands/scaffold/register.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/register.js +11 -0
- package/dist/cli/commands/scaffold/register.js.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts +11 -0
- package/dist/cli/commands/scaffold/scaffold.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/scaffold.js +728 -0
- package/dist/cli/commands/scaffold/scaffold.js.map +1 -0
- package/dist/cli/commands/scaffold/targets.d.ts +60 -0
- package/dist/cli/commands/scaffold/targets.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/targets.js +251 -0
- package/dist/cli/commands/scaffold/targets.js.map +1 -0
- package/dist/cli/commands/scaffold/types.d.ts +170 -0
- package/dist/cli/commands/scaffold/types.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/types.js +12 -0
- package/dist/cli/commands/scaffold/types.js.map +1 -0
- package/dist/cli/commands/scaffold/utils.d.ts +89 -0
- package/dist/cli/commands/scaffold/utils.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/utils.js +401 -0
- package/dist/cli/commands/scaffold/utils.js.map +1 -0
- package/dist/cli/commands/status.d.ts +19 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +124 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/status.types.d.ts +37 -0
- package/dist/cli/commands/status.types.d.ts.map +1 -0
- package/dist/cli/commands/status.types.js +7 -0
- package/dist/cli/commands/status.types.js.map +1 -0
- package/dist/cli/commands/switch.d.ts +18 -0
- package/dist/cli/commands/switch.d.ts.map +1 -0
- package/dist/cli/commands/switch.js +134 -0
- package/dist/cli/commands/switch.js.map +1 -0
- package/dist/cli/commands/switch.types.d.ts +123 -0
- package/dist/cli/commands/switch.types.d.ts.map +1 -0
- package/dist/cli/commands/switch.types.js +46 -0
- package/dist/cli/commands/switch.types.js.map +1 -0
- package/dist/cli/config/agent-teams.types.d.ts +120 -0
- package/dist/cli/config/agent-teams.types.d.ts.map +1 -0
- package/dist/cli/config/agent-teams.types.js +23 -0
- package/dist/cli/config/agent-teams.types.js.map +1 -0
- package/dist/cli/config/index.d.ts +13 -0
- package/dist/cli/config/index.d.ts.map +1 -0
- package/dist/cli/config/index.js +7 -0
- package/dist/cli/config/index.js.map +1 -0
- package/dist/cli/config/loader.d.ts +114 -0
- package/dist/cli/config/loader.d.ts.map +1 -0
- package/dist/cli/config/loader.js +198 -0
- package/dist/cli/config/loader.js.map +1 -0
- package/dist/cli/config/paths.d.ts +107 -0
- package/dist/cli/config/paths.d.ts.map +1 -0
- package/dist/cli/config/paths.js +79 -0
- package/dist/cli/config/paths.js.map +1 -0
- package/dist/cli/config/planning-sessions-registry.d.ts +52 -0
- package/dist/cli/config/planning-sessions-registry.d.ts.map +1 -0
- package/dist/cli/config/planning-sessions-registry.js +46 -0
- package/dist/cli/config/planning-sessions-registry.js.map +1 -0
- package/dist/cli/config/types.d.ts +186 -0
- package/dist/cli/config/types.d.ts.map +1 -0
- package/dist/cli/config/types.js +27 -0
- package/dist/cli/config/types.js.map +1 -0
- package/dist/cli/config/validation.d.ts +62 -0
- package/dist/cli/config/validation.d.ts.map +1 -0
- package/dist/cli/config/validation.js +133 -0
- package/dist/cli/config/validation.js.map +1 -0
- package/dist/cli/config/writer.d.ts +153 -0
- package/dist/cli/config/writer.d.ts.map +1 -0
- package/dist/cli/config/writer.js +168 -0
- package/dist/cli/config/writer.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +142 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/middleware/auth-guard.d.ts +107 -0
- package/dist/cli/middleware/auth-guard.d.ts.map +1 -0
- package/dist/cli/middleware/auth-guard.js +97 -0
- package/dist/cli/middleware/auth-guard.js.map +1 -0
- package/dist/cli/middleware/error-handler.d.ts +133 -0
- package/dist/cli/middleware/error-handler.d.ts.map +1 -0
- package/dist/cli/middleware/error-handler.js +139 -0
- package/dist/cli/middleware/error-handler.js.map +1 -0
- package/dist/cli/middleware/index.d.ts +6 -0
- package/dist/cli/middleware/index.d.ts.map +1 -0
- package/dist/cli/middleware/index.js +3 -0
- package/dist/cli/middleware/index.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js +160 -0
- package/dist/cli/templates/agents/content/core/sfag-orchestrator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +343 -0
- package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts +9 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js +254 -0
- package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts +8 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.d.ts.map +1 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js +128 -0
- package/dist/cli/templates/agents/content/research/sfag-package-researcher.js.map +1 -0
- package/dist/cli/templates/agents/index.d.ts +23 -0
- package/dist/cli/templates/agents/index.d.ts.map +1 -0
- package/dist/cli/templates/agents/index.js +29 -0
- package/dist/cli/templates/agents/index.js.map +1 -0
- package/dist/cli/templates/commands.d.ts +17 -0
- package/dist/cli/templates/commands.d.ts.map +1 -0
- package/dist/cli/templates/commands.js +78 -0
- package/dist/cli/templates/commands.js.map +1 -0
- package/dist/cli/templates/content/sf-blockers.d.ts +7 -0
- package/dist/cli/templates/content/sf-blockers.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-blockers.js +69 -0
- package/dist/cli/templates/content/sf-blockers.js.map +1 -0
- package/dist/cli/templates/content/sf-commit.d.ts +7 -0
- package/dist/cli/templates/content/sf-commit.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-commit.js +79 -0
- package/dist/cli/templates/content/sf-commit.js.map +1 -0
- package/dist/cli/templates/content/sf-context.d.ts +7 -0
- package/dist/cli/templates/content/sf-context.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-context.js +63 -0
- package/dist/cli/templates/content/sf-context.js.map +1 -0
- package/dist/cli/templates/content/sf-help.d.ts +7 -0
- package/dist/cli/templates/content/sf-help.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-help.js +42 -0
- package/dist/cli/templates/content/sf-help.js.map +1 -0
- package/dist/cli/templates/content/sf-init.d.ts +7 -0
- package/dist/cli/templates/content/sf-init.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-init.js +62 -0
- package/dist/cli/templates/content/sf-init.js.map +1 -0
- package/dist/cli/templates/content/sf-reset.d.ts +7 -0
- package/dist/cli/templates/content/sf-reset.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-reset.js +67 -0
- package/dist/cli/templates/content/sf-reset.js.map +1 -0
- package/dist/cli/templates/content/sf-search.d.ts +7 -0
- package/dist/cli/templates/content/sf-search.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-search.js +63 -0
- package/dist/cli/templates/content/sf-search.js.map +1 -0
- package/dist/cli/templates/content/sf-status.d.ts +7 -0
- package/dist/cli/templates/content/sf-status.d.ts.map +1 -0
- package/dist/cli/templates/content/sf-status.js +62 -0
- package/dist/cli/templates/content/sf-status.js.map +1 -0
- package/dist/cli/templates/index.d.ts +8 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +17 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/ui/banner.d.ts +38 -0
- package/dist/cli/ui/banner.d.ts.map +1 -0
- package/dist/cli/ui/banner.js +89 -0
- package/dist/cli/ui/banner.js.map +1 -0
- package/dist/cli/ui/colors.d.ts +76 -0
- package/dist/cli/ui/colors.d.ts.map +1 -0
- package/dist/cli/ui/colors.js +67 -0
- package/dist/cli/ui/colors.js.map +1 -0
- package/dist/cli/ui/index.d.ts +7 -0
- package/dist/cli/ui/index.d.ts.map +1 -0
- package/dist/cli/ui/index.js +4 -0
- package/dist/cli/ui/index.js.map +1 -0
- package/dist/cli/ui/output.d.ts +117 -0
- package/dist/cli/ui/output.d.ts.map +1 -0
- package/dist/cli/ui/output.js +83 -0
- package/dist/cli/ui/output.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +120 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +158 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/ui/time.d.ts +54 -0
- package/dist/cli/ui/time.d.ts.map +1 -0
- package/dist/cli/ui/time.js +119 -0
- package/dist/cli/ui/time.js.map +1 -0
- package/dist/client/api-client.d.ts +123 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +105 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/cli-client.d.ts +26 -0
- package/dist/client/cli-client.d.ts.map +1 -0
- package/dist/client/cli-client.js +20 -0
- package/dist/client/cli-client.js.map +1 -0
- package/dist/config/index.d.ts +78 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +79 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/format.d.ts +126 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +71 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +45 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/monorepo-detector.d.ts +31 -0
- package/dist/lib/monorepo-detector.d.ts.map +1 -0
- package/dist/lib/monorepo-detector.js +188 -0
- package/dist/lib/monorepo-detector.js.map +1 -0
- package/dist/lib/prompt-generator.d.ts +65 -0
- package/dist/lib/prompt-generator.d.ts.map +1 -0
- package/dist/lib/prompt-generator.js +162 -0
- package/dist/lib/prompt-generator.js.map +1 -0
- package/dist/lib/strategy-analyzer.d.ts +59 -0
- package/dist/lib/strategy-analyzer.d.ts.map +1 -0
- package/dist/lib/strategy-analyzer.js +91 -0
- package/dist/lib/strategy-analyzer.js.map +1 -0
- package/dist/lib/workflow-definitions.d.ts +41 -0
- package/dist/lib/workflow-definitions.d.ts.map +1 -0
- package/dist/lib/workflow-definitions.js +497 -0
- package/dist/lib/workflow-definitions.js.map +1 -0
- package/dist/patterns/index.d.ts +9 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +21 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/inheritance.d.ts +193 -0
- package/dist/patterns/inheritance.d.ts.map +1 -0
- package/dist/patterns/inheritance.js +125 -0
- package/dist/patterns/inheritance.js.map +1 -0
- package/dist/server.d.ts +44 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/core/context-helper.d.ts +50 -0
- package/dist/tools/core/context-helper.d.ts.map +1 -0
- package/dist/tools/core/context-helper.js +49 -0
- package/dist/tools/core/context-helper.js.map +1 -0
- package/dist/tools/core/index.d.ts +2 -0
- package/dist/tools/core/index.d.ts.map +1 -0
- package/dist/tools/core/index.js +2 -0
- package/dist/tools/core/index.js.map +1 -0
- package/dist/tools/index.d.ts +58 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1499 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts +6 -0
- package/dist/transport/__tests__/resolve-endpoint.test.d.ts.map +1 -0
- package/dist/transport/index.d.ts +6 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/interface.d.ts +25 -0
- package/dist/transport/interface.d.ts.map +1 -0
- package/dist/transport/interface.js +1 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/remote.d.ts +38 -0
- package/dist/transport/remote.d.ts.map +1 -0
- package/dist/transport/remote.js +107 -0
- package/dist/transport/remote.js.map +1 -0
- package/dist/transport/resolve-endpoint.d.ts +58 -0
- package/dist/transport/resolve-endpoint.d.ts.map +1 -0
- package/dist/transport/resolve-endpoint.js +146 -0
- package/dist/transport/resolve-endpoint.js.map +1 -0
- package/dist/types/index.d.ts +212 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validation/index.d.ts +86 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +392 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/ticket-validation.d.ts +162 -0
- package/dist/validation/ticket-validation.d.ts.map +1 -0
- package/dist/validation/ticket-validation.js +188 -0
- package/dist/validation/ticket-validation.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/bulk.d.ts +133 -0
- package/node_modules/@specforge/types/dist/api/bulk.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/bulk.js +7 -0
- package/node_modules/@specforge/types/dist/api/bulk.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/feedback.d.ts +22 -0
- package/node_modules/@specforge/types/dist/api/feedback.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/feedback.js +5 -0
- package/node_modules/@specforge/types/dist/api/feedback.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/index.d.ts +6 -0
- package/node_modules/@specforge/types/dist/api/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/index.js +6 -0
- package/node_modules/@specforge/types/dist/api/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/lists.d.ts +55 -0
- package/node_modules/@specforge/types/dist/api/lists.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/lists.js +8 -0
- package/node_modules/@specforge/types/dist/api/lists.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/lookups.d.ts +92 -0
- package/node_modules/@specforge/types/dist/api/lookups.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/lookups.js +2 -0
- package/node_modules/@specforge/types/dist/api/lookups.js.map +1 -0
- package/node_modules/@specforge/types/dist/api/responses.d.ts +92 -0
- package/node_modules/@specforge/types/dist/api/responses.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/api/responses.js +9 -0
- package/node_modules/@specforge/types/dist/api/responses.js.map +1 -0
- package/node_modules/@specforge/types/dist/index.d.ts +4 -0
- package/node_modules/@specforge/types/dist/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/index.js +4 -0
- package/node_modules/@specforge/types/dist/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/index.d.ts +2 -0
- package/node_modules/@specforge/types/dist/mcp/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/index.js +2 -0
- package/node_modules/@specforge/types/dist/mcp/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-planning-session.d.ts +44 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-planning-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-planning-session.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-planning-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-review-session.d.ts +68 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-review-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-review-session.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-review-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-work-session.d.ts +133 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-work-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-work-session.js +8 -0
- package/node_modules/@specforge/types/dist/mcp/tools/action-work-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-planning-session.d.ts +21 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-planning-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-planning-session.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-planning-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-review-session.d.ts +21 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-review-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-review-session.js +8 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-review-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-work-session.d.ts +42 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-work-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-work-session.js +8 -0
- package/node_modules/@specforge/types/dist/mcp/tools/complete-work-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/create-specification.d.ts +21 -0
- package/node_modules/@specforge/types/dist/mcp/tools/create-specification.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/create-specification.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/create-specification.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/feedback.d.ts +59 -0
- package/node_modules/@specforge/types/dist/mcp/tools/feedback.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/feedback.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/feedback.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-blocked-tickets.d.ts +33 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-blocked-tickets.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-blocked-tickets.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-blocked-tickets.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-critical-path.d.ts +15 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-critical-path.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-critical-path.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-critical-path.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-dependency-tree.d.ts +15 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-dependency-tree.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-dependency-tree.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-dependency-tree.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-next-actionable-tickets.d.ts +28 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-next-actionable-tickets.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-next-actionable-tickets.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-next-actionable-tickets.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-report.d.ts +44 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-report.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-report.js +8 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get-report.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get.d.ts +23 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/get.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/index.d.ts +23 -0
- package/node_modules/@specforge/types/dist/mcp/tools/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/index.js +23 -0
- package/node_modules/@specforge/types/dist/mcp/tools/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/link-pull-request.d.ts +27 -0
- package/node_modules/@specforge/types/dist/mcp/tools/link-pull-request.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/link-pull-request.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/link-pull-request.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/list.d.ts +23 -0
- package/node_modules/@specforge/types/dist/mcp/tools/list.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/list.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/list.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reopen-specification.d.ts +14 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reopen-specification.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reopen-specification.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reopen-specification.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reset-work-session.d.ts +35 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reset-work-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reset-work-session.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/reset-work-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/search.d.ts +47 -0
- package/node_modules/@specforge/types/dist/mcp/tools/search.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/search.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/search.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-planning-session.d.ts +20 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-planning-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-planning-session.js +5 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-planning-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-review-session.d.ts +17 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-review-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-review-session.js +8 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-review-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-work-session.d.ts +16 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-work-session.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-work-session.js +7 -0
- package/node_modules/@specforge/types/dist/mcp/tools/start-work-session.js.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/epic.d.ts +105 -0
- package/node_modules/@specforge/types/dist/runtime/epic.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/epic.js +10 -0
- package/node_modules/@specforge/types/dist/runtime/epic.js.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/index.d.ts +11 -0
- package/node_modules/@specforge/types/dist/runtime/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/index.js +11 -0
- package/node_modules/@specforge/types/dist/runtime/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/project.d.ts +22 -0
- package/node_modules/@specforge/types/dist/runtime/project.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/project.js +9 -0
- package/node_modules/@specforge/types/dist/runtime/project.js.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/specification.d.ts +111 -0
- package/node_modules/@specforge/types/dist/runtime/specification.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/specification.js +10 -0
- package/node_modules/@specforge/types/dist/runtime/specification.js.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/ticket.d.ts +80 -0
- package/node_modules/@specforge/types/dist/runtime/ticket.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/runtime/ticket.js +12 -0
- package/node_modules/@specforge/types/dist/runtime/ticket.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/blueprint.d.ts +18 -0
- package/node_modules/@specforge/types/dist/schema/blueprint.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/blueprint.js +3 -0
- package/node_modules/@specforge/types/dist/schema/blueprint.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/epic.d.ts +28 -0
- package/node_modules/@specforge/types/dist/schema/epic.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/epic.js +3 -0
- package/node_modules/@specforge/types/dist/schema/epic.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/epic.extensions.d.ts +2 -0
- package/node_modules/@specforge/types/dist/schema/extensions/epic.extensions.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/epic.extensions.js +4 -0
- package/node_modules/@specforge/types/dist/schema/extensions/epic.extensions.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/specification.extensions.d.ts +6 -0
- package/node_modules/@specforge/types/dist/schema/extensions/specification.extensions.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/specification.extensions.js +3 -0
- package/node_modules/@specforge/types/dist/schema/extensions/specification.extensions.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/ticket.extensions.d.ts +6 -0
- package/node_modules/@specforge/types/dist/schema/extensions/ticket.extensions.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/extensions/ticket.extensions.js +3 -0
- package/node_modules/@specforge/types/dist/schema/extensions/ticket.extensions.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/index.d.ts +7 -0
- package/node_modules/@specforge/types/dist/schema/index.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/index.js +7 -0
- package/node_modules/@specforge/types/dist/schema/index.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/patterns.d.ts +6 -0
- package/node_modules/@specforge/types/dist/schema/patterns.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/patterns.js +3 -0
- package/node_modules/@specforge/types/dist/schema/patterns.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/project.d.ts +7 -0
- package/node_modules/@specforge/types/dist/schema/project.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/project.js +3 -0
- package/node_modules/@specforge/types/dist/schema/project.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/specification.d.ts +35 -0
- package/node_modules/@specforge/types/dist/schema/specification.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/specification.js +3 -0
- package/node_modules/@specforge/types/dist/schema/specification.js.map +1 -0
- package/node_modules/@specforge/types/dist/schema/ticket.d.ts +69 -0
- package/node_modules/@specforge/types/dist/schema/ticket.d.ts.map +1 -0
- package/node_modules/@specforge/types/dist/schema/ticket.js +3 -0
- package/node_modules/@specforge/types/dist/schema/ticket.js.map +1 -0
- package/node_modules/@specforge/types/package.json +69 -0
- package/package.json +76 -0
- package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +165 -0
- package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +348 -0
- package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +259 -0
- package/src/cli/templates/agents/content/research/sfag-package-researcher.ts +132 -0
- package/src/cli/templates/agents/index.ts +47 -0
- package/src/cli/templates/commands.ts +90 -0
- package/src/cli/templates/content/sf-blockers.ts +71 -0
- package/src/cli/templates/content/sf-commit.ts +81 -0
- package/src/cli/templates/content/sf-context.ts +65 -0
- package/src/cli/templates/content/sf-help.ts +44 -0
- package/src/cli/templates/content/sf-init.ts +64 -0
- package/src/cli/templates/content/sf-reset.ts +69 -0
- package/src/cli/templates/content/sf-search.ts +65 -0
- package/src/cli/templates/content/sf-status.ts +64 -0
- package/src/cli/templates/index.ts +16 -0
- package/src/cli/templates/skills/specforge-conventions.md +114 -0
- package/src/cli/templates/skills/specforge-orchestrator.md +409 -0
- package/src/cli/templates/skills/specforge-validator.md +128 -0
- package/src/cli/templates/skills/specforge-worker.md +412 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { resolveConfig, getConfigPaths } from "../../config/index.js";
|
|
4
|
+
import { createCliClient } from "../../../client/cli-client.js";
|
|
5
|
+
import { CHANNEL } from "../../../channel.js";
|
|
6
|
+
function maskApiKey(apiKey) {
|
|
7
|
+
if (apiKey.length < 12) {
|
|
8
|
+
return "****";
|
|
9
|
+
}
|
|
10
|
+
return `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`;
|
|
11
|
+
}
|
|
12
|
+
function getConfigSource(config) {
|
|
13
|
+
if (process.env.SPECFORGE_API_KEY) {
|
|
14
|
+
return "environment";
|
|
15
|
+
}
|
|
16
|
+
if (config.projectId) {
|
|
17
|
+
return ".specforge.json (project)";
|
|
18
|
+
}
|
|
19
|
+
if (config.apiKey) {
|
|
20
|
+
return "~/.specforge/config.json (global)";
|
|
21
|
+
}
|
|
22
|
+
return "defaults";
|
|
23
|
+
}
|
|
24
|
+
function displayUserInfo(info) {
|
|
25
|
+
console.log(chalk.bold("\nUser"));
|
|
26
|
+
console.log("\u2500\u2500\u2500\u2500");
|
|
27
|
+
if (info.user.name) {
|
|
28
|
+
console.log(`Name: ${info.user.name}`);
|
|
29
|
+
}
|
|
30
|
+
console.log(`Email: ${info.user.email}`);
|
|
31
|
+
console.log(`API Key: ${info.user.apiKey}`);
|
|
32
|
+
}
|
|
33
|
+
function displayConfiguration(info) {
|
|
34
|
+
console.log(chalk.bold("\nConfiguration"));
|
|
35
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
36
|
+
console.log(`Source: ${info.configuration.source}`);
|
|
37
|
+
if (info.configuration.projectName) {
|
|
38
|
+
console.log(`Project: ${info.configuration.projectName} (${info.configuration.projectId})`);
|
|
39
|
+
} else if (info.configuration.projectId) {
|
|
40
|
+
console.log(`Project: ${info.configuration.projectId}`);
|
|
41
|
+
} else {
|
|
42
|
+
console.log(`Project: ${chalk.dim("(not set)")}`);
|
|
43
|
+
}
|
|
44
|
+
if (info.configuration.specificationTitle) {
|
|
45
|
+
console.log(`Spec: ${info.configuration.specificationTitle} (${info.configuration.specificationId})`);
|
|
46
|
+
} else if (info.configuration.specificationId) {
|
|
47
|
+
console.log(`Spec: ${info.configuration.specificationId}`);
|
|
48
|
+
} else {
|
|
49
|
+
console.log(`Spec: ${chalk.dim("(not set)")}`);
|
|
50
|
+
}
|
|
51
|
+
console.log(`MCP format: ${info.configuration.mcpOutputFormat}`);
|
|
52
|
+
}
|
|
53
|
+
function displayPaths(info) {
|
|
54
|
+
console.log(chalk.bold("\nPaths"));
|
|
55
|
+
console.log("\u2500\u2500\u2500\u2500\u2500");
|
|
56
|
+
console.log(`Project config: ${info.paths.projectConfig}`);
|
|
57
|
+
console.log(`MCP config: ${info.paths.mcpConfig}`);
|
|
58
|
+
console.log(`Global config: ${info.paths.globalConfig}`);
|
|
59
|
+
console.log();
|
|
60
|
+
}
|
|
61
|
+
async function whoamiCommand(options) {
|
|
62
|
+
const config = resolveConfig();
|
|
63
|
+
const paths = getConfigPaths();
|
|
64
|
+
const spinner = ora("Fetching user info...").start();
|
|
65
|
+
try {
|
|
66
|
+
const client = createCliClient({
|
|
67
|
+
apiKey: config.apiKey,
|
|
68
|
+
apiUrl: process.env.SPECFORGE_API_URL || CHANNEL.endpoint.primary,
|
|
69
|
+
debug: config.debug
|
|
70
|
+
});
|
|
71
|
+
const userResponse = await client.call("get_current_user", {});
|
|
72
|
+
const userEmail = userResponse.email || "Unknown";
|
|
73
|
+
const userName = userResponse.name;
|
|
74
|
+
let projectName;
|
|
75
|
+
if (config.projectId) {
|
|
76
|
+
try {
|
|
77
|
+
const proj = await client.call("get_project", { projectId: config.projectId });
|
|
78
|
+
projectName = proj.name;
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
let specTitle;
|
|
83
|
+
if (config.specificationId) {
|
|
84
|
+
try {
|
|
85
|
+
const spec = await client.call("get_specification", {
|
|
86
|
+
specificationId: config.specificationId
|
|
87
|
+
});
|
|
88
|
+
specTitle = spec.title;
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
spinner.stop();
|
|
93
|
+
const info = {
|
|
94
|
+
user: {
|
|
95
|
+
name: userName,
|
|
96
|
+
email: userEmail,
|
|
97
|
+
apiKey: maskApiKey(config.apiKey)
|
|
98
|
+
},
|
|
99
|
+
configuration: {
|
|
100
|
+
source: getConfigSource(config),
|
|
101
|
+
projectId: config.projectId || void 0,
|
|
102
|
+
projectName,
|
|
103
|
+
specificationId: config.specificationId || void 0,
|
|
104
|
+
specificationTitle: specTitle,
|
|
105
|
+
mcpOutputFormat: config.mcpOutputFormat || "json"
|
|
106
|
+
},
|
|
107
|
+
paths: {
|
|
108
|
+
projectConfig: paths.projectConfig,
|
|
109
|
+
mcpConfig: paths.mcpConfig,
|
|
110
|
+
globalConfig: paths.globalConfig
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
if (options.json) {
|
|
114
|
+
console.log(JSON.stringify(info, null, 2));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
displayUserInfo(info);
|
|
118
|
+
displayConfiguration(info);
|
|
119
|
+
displayPaths(info);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
spinner.fail("Failed to fetch user info");
|
|
122
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
123
|
+
console.error(chalk.red(`
|
|
124
|
+
Error: ${message}`));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export {
|
|
129
|
+
whoamiCommand
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/cli/commands/debug/whoami.ts"],"sourcesContent":["/**\n * Whoami Command Implementation\n *\n * Displays current user information, configuration settings, and config file paths.\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { resolveConfig, getConfigPaths } from '../../config/index.js';\nimport { createCliClient } from '../../../client/cli-client.js';\nimport { CHANNEL } from '../../../channel.js';\nimport type { WhoamiOptions, WhoamiInfo } from './types.js';\n\n/**\n * Mask API key for display\n */\nfunction maskApiKey(apiKey: string): string {\n if (apiKey.length < 12) {\n return '****';\n }\n return `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`;\n}\n\n/**\n * Determine configuration source\n */\nfunction getConfigSource(config: { apiKey?: string | null; projectId?: string | null }): string {\n if (process.env.SPECFORGE_API_KEY) {\n return 'environment';\n }\n if (config.projectId) {\n return '.specforge.json (project)';\n }\n if (config.apiKey) {\n return '~/.specforge/config.json (global)';\n }\n return 'defaults';\n}\n\n/**\n * Display user information\n */\nfunction displayUserInfo(info: WhoamiInfo): void {\n console.log(chalk.bold('\\nUser'));\n console.log('────');\n if (info.user.name) {\n console.log(`Name: ${info.user.name}`);\n }\n console.log(`Email: ${info.user.email}`);\n console.log(`API Key: ${info.user.apiKey}`);\n}\n\n/**\n * Display configuration information\n */\nfunction displayConfiguration(info: WhoamiInfo): void {\n console.log(chalk.bold('\\nConfiguration'));\n console.log('─────────────');\n console.log(`Source: ${info.configuration.source}`);\n\n if (info.configuration.projectName) {\n console.log(`Project: ${info.configuration.projectName} (${info.configuration.projectId})`);\n } else if (info.configuration.projectId) {\n console.log(`Project: ${info.configuration.projectId}`);\n } else {\n console.log(`Project: ${chalk.dim('(not set)')}`);\n }\n\n if (info.configuration.specificationTitle) {\n console.log(`Spec: ${info.configuration.specificationTitle} (${info.configuration.specificationId})`);\n } else if (info.configuration.specificationId) {\n console.log(`Spec: ${info.configuration.specificationId}`);\n } else {\n console.log(`Spec: ${chalk.dim('(not set)')}`);\n }\n\n console.log(`MCP format: ${info.configuration.mcpOutputFormat}`);\n}\n\n/**\n * Display configuration file paths\n */\nfunction displayPaths(info: WhoamiInfo): void {\n console.log(chalk.bold('\\nPaths'));\n console.log('─────');\n console.log(`Project config: ${info.paths.projectConfig}`);\n console.log(`MCP config: ${info.paths.mcpConfig}`);\n console.log(`Global config: ${info.paths.globalConfig}`);\n console.log();\n}\n\n/**\n * Whoami command implementation\n *\n * Displays current user and configuration information.\n */\nexport async function whoamiCommand(options: WhoamiOptions): Promise<void> {\n const config = resolveConfig();\n const paths = getConfigPaths();\n\n const spinner = ora('Fetching user info...').start();\n\n try {\n const client = createCliClient({\n apiKey: config.apiKey!,\n apiUrl: process.env.SPECFORGE_API_URL || CHANNEL.endpoint.primary,\n debug: config.debug,\n });\n\n // Get user info\n const userResponse = await client.call('get_current_user', {}) as { email?: string; name?: string };\n const userEmail = userResponse.email || 'Unknown';\n const userName = userResponse.name;\n\n // Get project name if configured\n let projectName: string | undefined;\n if (config.projectId) {\n try {\n const proj = await client.call('get_project', { projectId: config.projectId });\n projectName = (proj as { name?: string }).name;\n } catch {\n // Ignore - project might not exist\n }\n }\n\n // Get specification title if configured\n let specTitle: string | undefined;\n if (config.specificationId) {\n try {\n const spec = await client.call('get_specification', {\n specificationId: config.specificationId\n });\n specTitle = (spec as { title?: string }).title;\n } catch {\n // Ignore - spec might not exist\n }\n }\n\n spinner.stop();\n\n // Build whoami info\n const info: WhoamiInfo = {\n user: {\n name: userName,\n email: userEmail,\n apiKey: maskApiKey(config.apiKey!),\n },\n configuration: {\n source: getConfigSource(config),\n projectId: config.projectId || undefined,\n projectName,\n specificationId: config.specificationId || undefined,\n specificationTitle: specTitle,\n mcpOutputFormat: config.mcpOutputFormat || 'json',\n },\n paths: {\n projectConfig: paths.projectConfig,\n mcpConfig: paths.mcpConfig,\n globalConfig: paths.globalConfig,\n },\n };\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(info, null, 2));\n return;\n }\n\n // Display formatted output\n displayUserInfo(info);\n displayConfiguration(info);\n displayPaths(info);\n\n } catch (error) {\n spinner.fail('Failed to fetch user info');\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error(chalk.red(`\\nError: ${message}`));\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Command
|
|
3
|
+
*
|
|
4
|
+
* Diagnoses configuration and connection issues for SpecForge MCP.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { DoctorOptions } from './doctor.types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Doctor command action handler
|
|
10
|
+
*/
|
|
11
|
+
export declare function doctorAction(options: DoctorOptions): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Register doctor command with Commander
|
|
14
|
+
*/
|
|
15
|
+
export declare function registerDoctorCommand(program: Command): void;
|
|
16
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,OAAO,EACL,aAAa,EAkBd,MAAM,mBAAmB,CAAC;AAoZ3B;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsB5D"}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import {
|
|
3
|
+
resolveConfig,
|
|
4
|
+
loadGlobalConfig,
|
|
5
|
+
tryLoadProjectConfig,
|
|
6
|
+
getConfigPaths
|
|
7
|
+
} from "../config/index.js";
|
|
8
|
+
import { withErrorHandler } from "../middleware/error-handler.js";
|
|
9
|
+
import { printBlank, printHeader } from "../ui/output.js";
|
|
10
|
+
import { colors } from "../ui/colors.js";
|
|
11
|
+
import { forgeProgress } from "../ui/spinner.js";
|
|
12
|
+
import { createCliClient } from "../../client/cli-client.js";
|
|
13
|
+
import { CHANNEL } from "../../channel.js";
|
|
14
|
+
import {
|
|
15
|
+
createPassResult,
|
|
16
|
+
createFailResult,
|
|
17
|
+
createWarnResult,
|
|
18
|
+
calculateSummary,
|
|
19
|
+
hasFailures,
|
|
20
|
+
getStatusIcon,
|
|
21
|
+
CHECK_CATEGORIES,
|
|
22
|
+
CONFIG_CHECK_NAMES,
|
|
23
|
+
AUTH_CHECK_NAMES,
|
|
24
|
+
CONNECTION_CHECK_NAMES,
|
|
25
|
+
PROJECT_CHECK_NAMES,
|
|
26
|
+
PERFORMANCE_THRESHOLDS,
|
|
27
|
+
API_KEY_VALIDATION,
|
|
28
|
+
FIX_SUGGESTIONS
|
|
29
|
+
} from "./doctor.types.js";
|
|
30
|
+
function maskApiKey(apiKey, visibleChars = 8) {
|
|
31
|
+
if (apiKey.length <= visibleChars) {
|
|
32
|
+
return "***";
|
|
33
|
+
}
|
|
34
|
+
return `${API_KEY_VALIDATION.PREFIX}...${apiKey.slice(-visibleChars)}`;
|
|
35
|
+
}
|
|
36
|
+
function runConfigurationChecks() {
|
|
37
|
+
const results = [];
|
|
38
|
+
const paths = getConfigPaths();
|
|
39
|
+
const globalConfig = loadGlobalConfig();
|
|
40
|
+
const projectConfig = tryLoadProjectConfig();
|
|
41
|
+
results.push(createPassResult(
|
|
42
|
+
CONFIG_CHECK_NAMES.CHANNEL,
|
|
43
|
+
`${CHANNEL.name} \xB7 ${CHANNEL.packageName} \xB7 ${CHANNEL.endpoint.primary}`,
|
|
44
|
+
{ name: CHANNEL.name, packageName: CHANNEL.packageName, endpoint: CHANNEL.endpoint.primary }
|
|
45
|
+
));
|
|
46
|
+
if (fs.existsSync(paths.mcpConfig)) {
|
|
47
|
+
results.push(createPassResult(
|
|
48
|
+
CONFIG_CHECK_NAMES.MCP_CONFIG_FOUND,
|
|
49
|
+
paths.mcpConfig
|
|
50
|
+
));
|
|
51
|
+
} else {
|
|
52
|
+
results.push(createFailResult(
|
|
53
|
+
CONFIG_CHECK_NAMES.MCP_CONFIG_FOUND,
|
|
54
|
+
"File not found",
|
|
55
|
+
FIX_SUGGESTIONS.MISSING_MCP_CONFIG
|
|
56
|
+
));
|
|
57
|
+
}
|
|
58
|
+
if (projectConfig) {
|
|
59
|
+
results.push(createPassResult(
|
|
60
|
+
CONFIG_CHECK_NAMES.PROJECT_CONFIG_FOUND,
|
|
61
|
+
paths.projectConfig
|
|
62
|
+
));
|
|
63
|
+
} else {
|
|
64
|
+
results.push(createWarnResult(
|
|
65
|
+
CONFIG_CHECK_NAMES.PROJECT_CONFIG_FOUND,
|
|
66
|
+
"File not found (optional)",
|
|
67
|
+
FIX_SUGGESTIONS.MISSING_PROJECT_CONFIG
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
results.push(createPassResult(
|
|
71
|
+
CONFIG_CHECK_NAMES.GLOBAL_CONFIG_DIR,
|
|
72
|
+
paths.globalConfig
|
|
73
|
+
));
|
|
74
|
+
if (projectConfig?.planningSessionId) {
|
|
75
|
+
results.push(createPassResult(
|
|
76
|
+
CONFIG_CHECK_NAMES.PLANNING_SESSION,
|
|
77
|
+
projectConfig.planningSessionId
|
|
78
|
+
));
|
|
79
|
+
} else {
|
|
80
|
+
results.push(createWarnResult(
|
|
81
|
+
CONFIG_CHECK_NAMES.PLANNING_SESSION,
|
|
82
|
+
"None (no planning session persisted for this spec)"
|
|
83
|
+
));
|
|
84
|
+
}
|
|
85
|
+
const apiKeySource = process.env.SPECFORGE_API_KEY ? "From environment variable" : globalConfig.apiKey ? "From ~/.specforge/config.json" : void 0;
|
|
86
|
+
if (apiKeySource) {
|
|
87
|
+
results.push(createPassResult(
|
|
88
|
+
CONFIG_CHECK_NAMES.API_KEY_CONFIGURED,
|
|
89
|
+
apiKeySource
|
|
90
|
+
));
|
|
91
|
+
} else {
|
|
92
|
+
results.push(createFailResult(
|
|
93
|
+
CONFIG_CHECK_NAMES.API_KEY_CONFIGURED,
|
|
94
|
+
"No API key found",
|
|
95
|
+
FIX_SUGGESTIONS.MISSING_API_KEY
|
|
96
|
+
));
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
100
|
+
async function runAuthenticationChecks(apiKey) {
|
|
101
|
+
const results = [];
|
|
102
|
+
if (!apiKey) {
|
|
103
|
+
results.push(createFailResult(
|
|
104
|
+
AUTH_CHECK_NAMES.API_KEY_FORMAT,
|
|
105
|
+
"No API key to validate"
|
|
106
|
+
));
|
|
107
|
+
return results;
|
|
108
|
+
}
|
|
109
|
+
const hasValidPrefix = apiKey.startsWith(API_KEY_VALIDATION.PREFIX);
|
|
110
|
+
const hasValidLength = apiKey.length >= API_KEY_VALIDATION.MIN_LENGTH;
|
|
111
|
+
if (hasValidPrefix && hasValidLength) {
|
|
112
|
+
results.push(createPassResult(
|
|
113
|
+
AUTH_CHECK_NAMES.API_KEY_FORMAT,
|
|
114
|
+
maskApiKey(apiKey)
|
|
115
|
+
));
|
|
116
|
+
} else {
|
|
117
|
+
const issues = [];
|
|
118
|
+
if (!hasValidPrefix) issues.push(`should start with ${API_KEY_VALIDATION.PREFIX}`);
|
|
119
|
+
if (!hasValidLength) issues.push(`minimum ${API_KEY_VALIDATION.MIN_LENGTH} characters`);
|
|
120
|
+
results.push(createFailResult(
|
|
121
|
+
AUTH_CHECK_NAMES.API_KEY_FORMAT,
|
|
122
|
+
`Invalid format (${issues.join(", ")})`,
|
|
123
|
+
FIX_SUGGESTIONS.INVALID_API_KEY_FORMAT
|
|
124
|
+
));
|
|
125
|
+
return results;
|
|
126
|
+
}
|
|
127
|
+
const config = resolveConfig();
|
|
128
|
+
const client = createCliClient({
|
|
129
|
+
apiKey,
|
|
130
|
+
apiUrl: config.apiUrl,
|
|
131
|
+
debug: config.debug
|
|
132
|
+
});
|
|
133
|
+
try {
|
|
134
|
+
await client.call("list_projects", {});
|
|
135
|
+
results.push(createPassResult(
|
|
136
|
+
AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,
|
|
137
|
+
"Successfully authenticated"
|
|
138
|
+
));
|
|
139
|
+
try {
|
|
140
|
+
const userResponse = await client.call(
|
|
141
|
+
"get_current_user",
|
|
142
|
+
{}
|
|
143
|
+
);
|
|
144
|
+
const userInfo = userResponse.name ? `${userResponse.name} (${userResponse.email})` : userResponse.email || "Unknown";
|
|
145
|
+
results.push(createPassResult(
|
|
146
|
+
AUTH_CHECK_NAMES.USER_INFO,
|
|
147
|
+
userInfo
|
|
148
|
+
));
|
|
149
|
+
} catch {
|
|
150
|
+
results.push(createPassResult(
|
|
151
|
+
AUTH_CHECK_NAMES.USER_INFO,
|
|
152
|
+
"Authenticated (email not available)"
|
|
153
|
+
));
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
157
|
+
if (message.includes("401") || message.includes("Unauthorized")) {
|
|
158
|
+
results.push(createFailResult(
|
|
159
|
+
AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,
|
|
160
|
+
"Invalid or expired API key",
|
|
161
|
+
FIX_SUGGESTIONS.EXPIRED_API_KEY
|
|
162
|
+
));
|
|
163
|
+
} else {
|
|
164
|
+
results.push(createFailResult(
|
|
165
|
+
AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,
|
|
166
|
+
`Authentication failed: ${message}`
|
|
167
|
+
));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return results;
|
|
171
|
+
}
|
|
172
|
+
async function runConnectionChecks(apiKey) {
|
|
173
|
+
const results = [];
|
|
174
|
+
const config = resolveConfig();
|
|
175
|
+
const apiUrl = config.apiUrl;
|
|
176
|
+
if (!apiKey) {
|
|
177
|
+
results.push(createFailResult(
|
|
178
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
179
|
+
"No API key to test connection",
|
|
180
|
+
FIX_SUGGESTIONS.MISSING_API_KEY
|
|
181
|
+
));
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
184
|
+
const client = createCliClient({
|
|
185
|
+
apiKey,
|
|
186
|
+
apiUrl: config.apiUrl,
|
|
187
|
+
debug: config.debug
|
|
188
|
+
});
|
|
189
|
+
try {
|
|
190
|
+
const start = Date.now();
|
|
191
|
+
await client.call("list_projects", {});
|
|
192
|
+
const elapsed = Date.now() - start;
|
|
193
|
+
results.push(createPassResult(
|
|
194
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
195
|
+
apiUrl
|
|
196
|
+
));
|
|
197
|
+
if (elapsed < PERFORMANCE_THRESHOLDS.RESPONSE_TIME_WARNING) {
|
|
198
|
+
results.push(createPassResult(
|
|
199
|
+
CONNECTION_CHECK_NAMES.RESPONSE_TIME,
|
|
200
|
+
`${elapsed}ms`,
|
|
201
|
+
{ elapsed }
|
|
202
|
+
));
|
|
203
|
+
} else if (elapsed < PERFORMANCE_THRESHOLDS.RESPONSE_TIME_ERROR) {
|
|
204
|
+
results.push(createWarnResult(
|
|
205
|
+
CONNECTION_CHECK_NAMES.RESPONSE_TIME,
|
|
206
|
+
`${elapsed}ms (slow)`,
|
|
207
|
+
void 0,
|
|
208
|
+
{ elapsed }
|
|
209
|
+
));
|
|
210
|
+
} else {
|
|
211
|
+
results.push(createFailResult(
|
|
212
|
+
CONNECTION_CHECK_NAMES.RESPONSE_TIME,
|
|
213
|
+
`${elapsed}ms (very slow)`,
|
|
214
|
+
FIX_SUGGESTIONS.CONNECTION_TIMEOUT,
|
|
215
|
+
{ elapsed }
|
|
216
|
+
));
|
|
217
|
+
}
|
|
218
|
+
} catch (error) {
|
|
219
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
220
|
+
if (message.includes("ENOTFOUND") || message.includes("ECONNREFUSED") || message.includes("getaddrinfo")) {
|
|
221
|
+
results.push(createFailResult(
|
|
222
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
223
|
+
"Could not connect to API",
|
|
224
|
+
FIX_SUGGESTIONS.CONNECTION_FAILED
|
|
225
|
+
));
|
|
226
|
+
} else if (message.includes("timeout") || message.includes("TimeoutError")) {
|
|
227
|
+
results.push(createFailResult(
|
|
228
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
229
|
+
"Connection timed out",
|
|
230
|
+
FIX_SUGGESTIONS.CONNECTION_TIMEOUT
|
|
231
|
+
));
|
|
232
|
+
} else if (message.includes("401") || message.includes("Unauthorized")) {
|
|
233
|
+
results.push(createPassResult(
|
|
234
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
235
|
+
`${apiUrl} (auth issue handled separately)`
|
|
236
|
+
));
|
|
237
|
+
} else {
|
|
238
|
+
results.push(createFailResult(
|
|
239
|
+
CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,
|
|
240
|
+
message
|
|
241
|
+
));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
async function runProjectAccessChecks() {
|
|
247
|
+
const results = [];
|
|
248
|
+
const config = resolveConfig();
|
|
249
|
+
if (!config.apiKey) {
|
|
250
|
+
return results;
|
|
251
|
+
}
|
|
252
|
+
const client = createCliClient({
|
|
253
|
+
apiKey: config.apiKey,
|
|
254
|
+
apiUrl: config.apiUrl,
|
|
255
|
+
debug: config.debug
|
|
256
|
+
});
|
|
257
|
+
if (config.projectId) {
|
|
258
|
+
try {
|
|
259
|
+
await client.call("get_project", { projectId: config.projectId });
|
|
260
|
+
results.push(createPassResult(
|
|
261
|
+
PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,
|
|
262
|
+
config.projectId
|
|
263
|
+
));
|
|
264
|
+
} catch (error) {
|
|
265
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
266
|
+
results.push(createFailResult(
|
|
267
|
+
PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,
|
|
268
|
+
`Cannot access: ${message}`,
|
|
269
|
+
FIX_SUGGESTIONS.PROJECT_NOT_ACCESSIBLE
|
|
270
|
+
));
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
results.push(createWarnResult(
|
|
274
|
+
PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,
|
|
275
|
+
"No default project configured",
|
|
276
|
+
FIX_SUGGESTIONS.NO_PROJECT_CONFIGURED
|
|
277
|
+
));
|
|
278
|
+
}
|
|
279
|
+
if (config.specificationId) {
|
|
280
|
+
try {
|
|
281
|
+
await client.call("get_specification", { specificationId: config.specificationId });
|
|
282
|
+
results.push(createPassResult(
|
|
283
|
+
PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,
|
|
284
|
+
config.specificationId
|
|
285
|
+
));
|
|
286
|
+
} catch (error) {
|
|
287
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
288
|
+
results.push(createFailResult(
|
|
289
|
+
PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,
|
|
290
|
+
`Cannot access: ${message}`,
|
|
291
|
+
FIX_SUGGESTIONS.SPEC_NOT_ACCESSIBLE
|
|
292
|
+
));
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
results.push(createWarnResult(
|
|
296
|
+
PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,
|
|
297
|
+
"No default specification configured"
|
|
298
|
+
));
|
|
299
|
+
}
|
|
300
|
+
return results;
|
|
301
|
+
}
|
|
302
|
+
function displayReport(report) {
|
|
303
|
+
printBlank();
|
|
304
|
+
printHeader("SpecForge MCP Health Check");
|
|
305
|
+
printBlank();
|
|
306
|
+
for (const category of CHECK_CATEGORIES) {
|
|
307
|
+
const checks = report.checks[category.id];
|
|
308
|
+
if (checks.length === 0) continue;
|
|
309
|
+
console.log(colors.bold(category.name));
|
|
310
|
+
for (const check of checks) {
|
|
311
|
+
const icon = check.status === "pass" ? colors.success(getStatusIcon("pass")) : check.status === "warn" ? colors.warning(getStatusIcon("warn")) : colors.error(getStatusIcon("fail"));
|
|
312
|
+
console.log(` ${icon} ${check.name}: ${check.message}`);
|
|
313
|
+
if (check.fix && check.status !== "pass") {
|
|
314
|
+
console.log(colors.muted(` \u2192 ${check.fix}`));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
printBlank();
|
|
318
|
+
}
|
|
319
|
+
const { passed, failed, warnings, total } = report.summary;
|
|
320
|
+
if (failed === 0 && warnings === 0) {
|
|
321
|
+
console.log(colors.success(`All ${total} checks passed!`));
|
|
322
|
+
} else if (failed === 0) {
|
|
323
|
+
console.log(
|
|
324
|
+
colors.success("All checks passed!") + colors.warning(` (${warnings} warning${warnings > 1 ? "s" : ""})`)
|
|
325
|
+
);
|
|
326
|
+
} else {
|
|
327
|
+
const failMsg = `${failed} check${failed > 1 ? "s" : ""} failed`;
|
|
328
|
+
const warnMsg = warnings > 0 ? `, ${warnings} warning${warnings > 1 ? "s" : ""}` : "";
|
|
329
|
+
console.log(colors.error(failMsg) + colors.warning(warnMsg));
|
|
330
|
+
}
|
|
331
|
+
printBlank();
|
|
332
|
+
}
|
|
333
|
+
async function doctorAction(options) {
|
|
334
|
+
const config = resolveConfig();
|
|
335
|
+
let configChecks = [];
|
|
336
|
+
let authChecks = [];
|
|
337
|
+
let connectionChecks = [];
|
|
338
|
+
let projectChecks = [];
|
|
339
|
+
if (options.json) {
|
|
340
|
+
configChecks = runConfigurationChecks();
|
|
341
|
+
authChecks = await runAuthenticationChecks(config.apiKey);
|
|
342
|
+
connectionChecks = await runConnectionChecks(config.apiKey);
|
|
343
|
+
projectChecks = await runProjectAccessChecks();
|
|
344
|
+
} else {
|
|
345
|
+
await forgeProgress("Running diagnostics", [
|
|
346
|
+
{
|
|
347
|
+
label: "config",
|
|
348
|
+
fn: async () => {
|
|
349
|
+
configChecks = runConfigurationChecks();
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
label: "auth",
|
|
354
|
+
fn: async () => {
|
|
355
|
+
authChecks = await runAuthenticationChecks(config.apiKey);
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
label: "connection",
|
|
360
|
+
fn: async () => {
|
|
361
|
+
connectionChecks = await runConnectionChecks(config.apiKey);
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
label: "project",
|
|
366
|
+
fn: async () => {
|
|
367
|
+
projectChecks = await runProjectAccessChecks();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
]);
|
|
371
|
+
}
|
|
372
|
+
const checks = {
|
|
373
|
+
configuration: configChecks,
|
|
374
|
+
authentication: authChecks,
|
|
375
|
+
connection: connectionChecks,
|
|
376
|
+
projectAccess: projectChecks
|
|
377
|
+
};
|
|
378
|
+
const report = {
|
|
379
|
+
checks,
|
|
380
|
+
summary: calculateSummary(checks),
|
|
381
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
382
|
+
};
|
|
383
|
+
if (options.json) {
|
|
384
|
+
console.log(JSON.stringify(report, null, 2));
|
|
385
|
+
} else {
|
|
386
|
+
displayReport(report);
|
|
387
|
+
}
|
|
388
|
+
if (hasFailures(report)) {
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function registerDoctorCommand(program) {
|
|
393
|
+
program.command("doctor").description("Diagnose configuration and connection issues").option("--json", "Output as JSON for scripting").option("--fix", "Attempt to fix issues automatically (future)").addHelpText("after", `
|
|
394
|
+
Examples:
|
|
395
|
+
$ specforge doctor # Run health checks
|
|
396
|
+
$ specforge doctor --json # Output as JSON
|
|
397
|
+
|
|
398
|
+
Check Categories:
|
|
399
|
+
Configuration - Config files presence and validity
|
|
400
|
+
Authentication - API key format and authentication
|
|
401
|
+
Connection - API connectivity and response time
|
|
402
|
+
Project Access - Access to configured project/specification
|
|
403
|
+
|
|
404
|
+
Exit Codes:
|
|
405
|
+
0 - All checks passed (warnings OK)
|
|
406
|
+
1 - One or more checks failed
|
|
407
|
+
`).action(withErrorHandler(doctorAction));
|
|
408
|
+
}
|
|
409
|
+
export {
|
|
410
|
+
doctorAction,
|
|
411
|
+
registerDoctorCommand
|
|
412
|
+
};
|
|
413
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/doctor.ts"],"sourcesContent":["/**\n * Doctor Command\n *\n * Diagnoses configuration and connection issues for SpecForge MCP.\n */\n\nimport { Command } from 'commander';\nimport fs from 'node:fs';\nimport {\n resolveConfig,\n loadGlobalConfig,\n tryLoadProjectConfig,\n getConfigPaths,\n} from '../config/index.js';\nimport { withErrorHandler } from '../middleware/error-handler.js';\nimport { printBlank, printHeader } from '../ui/output.js';\nimport { colors } from '../ui/colors.js';\nimport { forgeProgress } from '../ui/spinner.js';\nimport { createCliClient } from '../../client/cli-client.js';\nimport { CHANNEL } from '../../channel.js';\nimport {\n DoctorOptions,\n DoctorReport,\n CheckResult,\n CheckCategory,\n createPassResult,\n createFailResult,\n createWarnResult,\n calculateSummary,\n hasFailures,\n getStatusIcon,\n CHECK_CATEGORIES,\n CONFIG_CHECK_NAMES,\n AUTH_CHECK_NAMES,\n CONNECTION_CHECK_NAMES,\n PROJECT_CHECK_NAMES,\n PERFORMANCE_THRESHOLDS,\n API_KEY_VALIDATION,\n FIX_SUGGESTIONS,\n} from './doctor.types.js';\n\n/**\n * Mask an API key for display (show only last N characters)\n */\nfunction maskApiKey(apiKey: string, visibleChars = 8): string {\n if (apiKey.length <= visibleChars) {\n return '***';\n }\n return `${API_KEY_VALIDATION.PREFIX}...${apiKey.slice(-visibleChars)}`;\n}\n\n/**\n * Run configuration checks\n */\nfunction runConfigurationChecks(): CheckResult[] {\n const results: CheckResult[] = [];\n const paths = getConfigPaths();\n const globalConfig = loadGlobalConfig();\n const projectConfig = tryLoadProjectConfig();\n\n // Channel + endpoint the binary is wired to (M9.6c).\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.CHANNEL,\n `${CHANNEL.name} · ${CHANNEL.packageName} · ${CHANNEL.endpoint.primary}`,\n { name: CHANNEL.name, packageName: CHANNEL.packageName, endpoint: CHANNEL.endpoint.primary },\n ));\n\n // Check .mcp.json\n if (fs.existsSync(paths.mcpConfig)) {\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.MCP_CONFIG_FOUND,\n paths.mcpConfig\n ));\n } else {\n results.push(createFailResult(\n CONFIG_CHECK_NAMES.MCP_CONFIG_FOUND,\n 'File not found',\n FIX_SUGGESTIONS.MISSING_MCP_CONFIG\n ));\n }\n\n // Check .specforge.json (optional)\n if (projectConfig) {\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.PROJECT_CONFIG_FOUND,\n paths.projectConfig\n ));\n } else {\n results.push(createWarnResult(\n CONFIG_CHECK_NAMES.PROJECT_CONFIG_FOUND,\n 'File not found (optional)',\n FIX_SUGGESTIONS.MISSING_PROJECT_CONFIG\n ));\n }\n\n // Global config directory (M9.6c — channel-aware path).\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.GLOBAL_CONFIG_DIR,\n paths.globalConfig\n ));\n\n // Active planning session for this spec (M9.6c) — read from local config; the\n // agent injects this id per-call. (The old `get_working_context` op is dead.)\n if (projectConfig?.planningSessionId) {\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.PLANNING_SESSION,\n projectConfig.planningSessionId\n ));\n } else {\n results.push(createWarnResult(\n CONFIG_CHECK_NAMES.PLANNING_SESSION,\n 'None (no planning session persisted for this spec)'\n ));\n }\n\n // Check API key configured\n const apiKeySource = process.env.SPECFORGE_API_KEY\n ? 'From environment variable'\n : globalConfig.apiKey\n ? 'From ~/.specforge/config.json'\n : undefined;\n\n if (apiKeySource) {\n results.push(createPassResult(\n CONFIG_CHECK_NAMES.API_KEY_CONFIGURED,\n apiKeySource\n ));\n } else {\n results.push(createFailResult(\n CONFIG_CHECK_NAMES.API_KEY_CONFIGURED,\n 'No API key found',\n FIX_SUGGESTIONS.MISSING_API_KEY\n ));\n }\n\n return results;\n}\n\n/**\n * Run authentication checks\n */\nasync function runAuthenticationChecks(apiKey: string | null | undefined): Promise<CheckResult[]> {\n const results: CheckResult[] = [];\n\n if (!apiKey) {\n results.push(createFailResult(\n AUTH_CHECK_NAMES.API_KEY_FORMAT,\n 'No API key to validate'\n ));\n return results;\n }\n\n // Check format\n const hasValidPrefix = apiKey.startsWith(API_KEY_VALIDATION.PREFIX);\n const hasValidLength = apiKey.length >= API_KEY_VALIDATION.MIN_LENGTH;\n\n if (hasValidPrefix && hasValidLength) {\n results.push(createPassResult(\n AUTH_CHECK_NAMES.API_KEY_FORMAT,\n maskApiKey(apiKey)\n ));\n } else {\n const issues: string[] = [];\n if (!hasValidPrefix) issues.push(`should start with ${API_KEY_VALIDATION.PREFIX}`);\n if (!hasValidLength) issues.push(`minimum ${API_KEY_VALIDATION.MIN_LENGTH} characters`);\n\n results.push(createFailResult(\n AUTH_CHECK_NAMES.API_KEY_FORMAT,\n `Invalid format (${issues.join(', ')})`,\n FIX_SUGGESTIONS.INVALID_API_KEY_FORMAT\n ));\n return results; // Don't test against backend if format is invalid\n }\n\n // Validate against backend\n const config = resolveConfig();\n const client = createCliClient({\n apiKey,\n apiUrl: config.apiUrl,\n debug: config.debug,\n });\n\n try {\n // First verify authentication works\n await client.call('list_projects', {});\n\n results.push(createPassResult(\n AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,\n 'Successfully authenticated'\n ));\n\n // Get user info\n try {\n const userResponse = await client.call<{ email?: string; name?: string }>(\n 'get_current_user',\n {}\n );\n const userInfo = userResponse.name\n ? `${userResponse.name} (${userResponse.email})`\n : userResponse.email || 'Unknown';\n results.push(createPassResult(\n AUTH_CHECK_NAMES.USER_INFO,\n userInfo\n ));\n } catch {\n results.push(createPassResult(\n AUTH_CHECK_NAMES.USER_INFO,\n 'Authenticated (email not available)'\n ));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n if (message.includes('401') || message.includes('Unauthorized')) {\n results.push(createFailResult(\n AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,\n 'Invalid or expired API key',\n FIX_SUGGESTIONS.EXPIRED_API_KEY\n ));\n } else {\n results.push(createFailResult(\n AUTH_CHECK_NAMES.API_KEY_AUTHENTICATED,\n `Authentication failed: ${message}`\n ));\n }\n }\n\n return results;\n}\n\n/**\n * Run connection checks\n */\nasync function runConnectionChecks(apiKey: string | null | undefined): Promise<CheckResult[]> {\n const results: CheckResult[] = [];\n const config = resolveConfig();\n const apiUrl = config.apiUrl;\n\n // Skip connection check if no API key (auth checks will fail anyway)\n if (!apiKey) {\n results.push(createFailResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n 'No API key to test connection',\n FIX_SUGGESTIONS.MISSING_API_KEY\n ));\n return results;\n }\n\n const client = createCliClient({\n apiKey,\n apiUrl: config.apiUrl,\n debug: config.debug,\n });\n\n try {\n const start = Date.now();\n // Use an authenticated call to test connectivity\n await client.call('list_projects', {});\n const elapsed = Date.now() - start;\n\n results.push(createPassResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n apiUrl\n ));\n\n // Response time check\n if (elapsed < PERFORMANCE_THRESHOLDS.RESPONSE_TIME_WARNING) {\n results.push(createPassResult(\n CONNECTION_CHECK_NAMES.RESPONSE_TIME,\n `${elapsed}ms`,\n { elapsed }\n ));\n } else if (elapsed < PERFORMANCE_THRESHOLDS.RESPONSE_TIME_ERROR) {\n results.push(createWarnResult(\n CONNECTION_CHECK_NAMES.RESPONSE_TIME,\n `${elapsed}ms (slow)`,\n undefined,\n { elapsed }\n ));\n } else {\n results.push(createFailResult(\n CONNECTION_CHECK_NAMES.RESPONSE_TIME,\n `${elapsed}ms (very slow)`,\n FIX_SUGGESTIONS.CONNECTION_TIMEOUT,\n { elapsed }\n ));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n if (message.includes('ENOTFOUND') || message.includes('ECONNREFUSED') || message.includes('getaddrinfo')) {\n results.push(createFailResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n 'Could not connect to API',\n FIX_SUGGESTIONS.CONNECTION_FAILED\n ));\n } else if (message.includes('timeout') || message.includes('TimeoutError')) {\n results.push(createFailResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n 'Connection timed out',\n FIX_SUGGESTIONS.CONNECTION_TIMEOUT\n ));\n } else if (message.includes('401') || message.includes('Unauthorized')) {\n // Auth issue, but connection works\n results.push(createPassResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n `${apiUrl} (auth issue handled separately)`\n ));\n } else {\n results.push(createFailResult(\n CONNECTION_CHECK_NAMES.API_ENDPOINT_REACHABLE,\n message\n ));\n }\n }\n\n return results;\n}\n\n/**\n * Run project access checks\n */\nasync function runProjectAccessChecks(): Promise<CheckResult[]> {\n const results: CheckResult[] = [];\n const config = resolveConfig();\n\n if (!config.apiKey) {\n // Skip if no API key (auth checks already failed)\n return results;\n }\n\n const client = createCliClient({\n apiKey: config.apiKey,\n apiUrl: config.apiUrl,\n debug: config.debug,\n });\n\n // Check project access\n if (config.projectId) {\n try {\n await client.call('get_project', { projectId: config.projectId });\n results.push(createPassResult(\n PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,\n config.projectId\n ));\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n results.push(createFailResult(\n PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,\n `Cannot access: ${message}`,\n FIX_SUGGESTIONS.PROJECT_NOT_ACCESSIBLE\n ));\n }\n } else {\n results.push(createWarnResult(\n PROJECT_CHECK_NAMES.PROJECT_ACCESSIBLE,\n 'No default project configured',\n FIX_SUGGESTIONS.NO_PROJECT_CONFIGURED\n ));\n }\n\n // Check specification access\n if (config.specificationId) {\n try {\n await client.call('get_specification', { specificationId: config.specificationId });\n results.push(createPassResult(\n PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,\n config.specificationId\n ));\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n results.push(createFailResult(\n PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,\n `Cannot access: ${message}`,\n FIX_SUGGESTIONS.SPEC_NOT_ACCESSIBLE\n ));\n }\n } else {\n results.push(createWarnResult(\n PROJECT_CHECK_NAMES.SPECIFICATION_ACCESSIBLE,\n 'No default specification configured'\n ));\n }\n\n // NOTE: the implementation-session probe (old `get_working_context`) was\n // removed in M8/M9 — that backend op no longer exists. The active planning\n // session is surfaced from local config in runConfigurationChecks (M9.6c).\n\n return results;\n}\n\n/**\n * Display the report in formatted console output\n */\nfunction displayReport(report: DoctorReport): void {\n printBlank();\n printHeader('SpecForge MCP Health Check');\n printBlank();\n\n for (const category of CHECK_CATEGORIES) {\n const checks = report.checks[category.id];\n if (checks.length === 0) continue;\n\n console.log(colors.bold(category.name));\n\n for (const check of checks) {\n const icon = check.status === 'pass'\n ? colors.success(getStatusIcon('pass'))\n : check.status === 'warn'\n ? colors.warning(getStatusIcon('warn'))\n : colors.error(getStatusIcon('fail'));\n\n console.log(` ${icon} ${check.name}: ${check.message}`);\n\n if (check.fix && check.status !== 'pass') {\n console.log(colors.muted(` → ${check.fix}`));\n }\n }\n\n printBlank();\n }\n\n // Summary\n const { passed, failed, warnings, total } = report.summary;\n\n if (failed === 0 && warnings === 0) {\n console.log(colors.success(`All ${total} checks passed!`));\n } else if (failed === 0) {\n console.log(\n colors.success('All checks passed!') +\n colors.warning(` (${warnings} warning${warnings > 1 ? 's' : ''})`)\n );\n } else {\n const failMsg = `${failed} check${failed > 1 ? 's' : ''} failed`;\n const warnMsg = warnings > 0\n ? `, ${warnings} warning${warnings > 1 ? 's' : ''}`\n : '';\n console.log(colors.error(failMsg) + colors.warning(warnMsg));\n }\n\n printBlank();\n}\n\n/**\n * Doctor command action handler\n */\nexport async function doctorAction(options: DoctorOptions): Promise<void> {\n const config = resolveConfig();\n\n let configChecks: CheckResult[] = [];\n let authChecks: CheckResult[] = [];\n let connectionChecks: CheckResult[] = [];\n let projectChecks: CheckResult[] = [];\n\n if (options.json) {\n configChecks = runConfigurationChecks();\n authChecks = await runAuthenticationChecks(config.apiKey);\n connectionChecks = await runConnectionChecks(config.apiKey);\n projectChecks = await runProjectAccessChecks();\n } else {\n await forgeProgress('Running diagnostics', [\n {\n label: 'config',\n fn: async () => { configChecks = runConfigurationChecks(); },\n },\n {\n label: 'auth',\n fn: async () => { authChecks = await runAuthenticationChecks(config.apiKey); },\n },\n {\n label: 'connection',\n fn: async () => { connectionChecks = await runConnectionChecks(config.apiKey); },\n },\n {\n label: 'project',\n fn: async () => { projectChecks = await runProjectAccessChecks(); },\n },\n ]);\n }\n\n // Compile report\n const checks: Record<CheckCategory, CheckResult[]> = {\n configuration: configChecks,\n authentication: authChecks,\n connection: connectionChecks,\n projectAccess: projectChecks,\n };\n\n const report: DoctorReport = {\n checks,\n summary: calculateSummary(checks),\n timestamp: new Date().toISOString(),\n };\n\n // Output\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n } else {\n displayReport(report);\n }\n\n // Exit with error if any checks failed\n if (hasFailures(report)) {\n process.exit(1);\n }\n}\n\n/**\n * Register doctor command with Commander\n */\nexport function registerDoctorCommand(program: Command): void {\n program\n .command('doctor')\n .description('Diagnose configuration and connection issues')\n .option('--json', 'Output as JSON for scripting')\n .option('--fix', 'Attempt to fix issues automatically (future)')\n .addHelpText('after', `\nExamples:\n $ specforge doctor # Run health checks\n $ specforge doctor --json # Output as JSON\n\nCheck Categories:\n Configuration - Config files presence and validity\n Authentication - API key format and authentication\n Connection - API connectivity and response time\n Project Access - Access to configured project/specification\n\nExit Codes:\n 0 - All checks passed (warnings OK)\n 1 - One or more checks failed\n`)\n .action(withErrorHandler(doctorAction));\n}\n"],"mappings":"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","names":[]}
|