@specforge/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/package.json +69 -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
package/bin/specforge
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SpecForge MCP CLI Entry Point
|
|
5
|
+
*
|
|
6
|
+
* All logic is handled by the CLI module.
|
|
7
|
+
* The 'serve' command is set as default in Commander.js for backward compatibility.
|
|
8
|
+
*
|
|
9
|
+
* When called with no arguments: starts MCP server
|
|
10
|
+
* When called with subcommands/flags: runs CLI
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import('../dist/cli/index.js')
|
|
14
|
+
.then(({ runCLI }) => runCLI())
|
|
15
|
+
.catch((error) => {
|
|
16
|
+
console.error('Fatal error:', error.message);
|
|
17
|
+
if (process.env.SPECFORGE_DEBUG === 'true') {
|
|
18
|
+
console.error(error.stack);
|
|
19
|
+
}
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel manifest — single import surface for build-time substitutions.
|
|
3
|
+
*
|
|
4
|
+
* `__CLI_*__` symbols are declared ambient in `channel.d.ts` and substituted
|
|
5
|
+
* by `tsup` (build) and `vitest` (tests) via `build/channel-defines.ts`.
|
|
6
|
+
*
|
|
7
|
+
* The rest of the CLI source must reference `CHANNEL.*` only — never the
|
|
8
|
+
* literal endpoint URLs, package name, or config dir name. The B1 acceptance
|
|
9
|
+
* grep enforces this.
|
|
10
|
+
*/
|
|
11
|
+
export declare const CHANNEL: {
|
|
12
|
+
/** Binary / display name. e.g. `"specforge"` (stable) or `"specforge-canary"`. */
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** npm package name on the public registry. */
|
|
15
|
+
readonly packageName: string;
|
|
16
|
+
/** MCP API gateway endpoint pair + health probes. */
|
|
17
|
+
readonly endpoint: {
|
|
18
|
+
readonly primary: string;
|
|
19
|
+
readonly fallback: string;
|
|
20
|
+
readonly healthPrimary: string;
|
|
21
|
+
readonly healthFallback: string;
|
|
22
|
+
};
|
|
23
|
+
/** Per-channel config dir under `$HOME` (and at the project level). */
|
|
24
|
+
readonly configDir: string;
|
|
25
|
+
};
|
|
26
|
+
export type ChannelManifest = typeof CHANNEL;
|
|
27
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,OAAO;IAClB,kFAAkF;;IAElF,+CAA+C;;IAE/C,qDAAqD;;;;;;;IAUrD,uEAAuE;;CAE/D,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,OAAO,OAAO,CAAC"}
|
package/dist/channel.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const CHANNEL = {
|
|
2
|
+
/** Binary / display name. e.g. `"specforge"` (stable) or `"specforge-canary"`. */
|
|
3
|
+
name: "specforge",
|
|
4
|
+
/** npm package name on the public registry. */
|
|
5
|
+
packageName: "@specforge/cli",
|
|
6
|
+
/** MCP API gateway endpoint pair + health probes. */
|
|
7
|
+
endpoint: {
|
|
8
|
+
primary: "https://mcp.specforge.tech/local",
|
|
9
|
+
fallback: "https://mcp.specforge.com.br/local",
|
|
10
|
+
healthPrimary: "https://mcp.specforge.tech/health",
|
|
11
|
+
healthFallback: "https://mcp.specforge.com.br/health"
|
|
12
|
+
},
|
|
13
|
+
// (CLI REST `cliRest` endpoints removed — the human CLI now uses the `/cli`
|
|
14
|
+
// route on the MCP host via `createCliClient`; the separate cli-rest gateway
|
|
15
|
+
// is retired.)
|
|
16
|
+
/** Per-channel config dir under `$HOME` (and at the project level). */
|
|
17
|
+
configDir: ".specforge"
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
CHANNEL
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/channel.ts"],"sourcesContent":["/**\n * Channel manifest — single import surface for build-time substitutions.\n *\n * `__CLI_*__` symbols are declared ambient in `channel.d.ts` and substituted\n * by `tsup` (build) and `vitest` (tests) via `build/channel-defines.ts`.\n *\n * The rest of the CLI source must reference `CHANNEL.*` only — never the\n * literal endpoint URLs, package name, or config dir name. The B1 acceptance\n * grep enforces this.\n */\n\nexport const CHANNEL = {\n /** Binary / display name. e.g. `\"specforge\"` (stable) or `\"specforge-canary\"`. */\n name: __CLI_NAME__,\n /** npm package name on the public registry. */\n packageName: __CLI_PACKAGE_NAME__,\n /** MCP API gateway endpoint pair + health probes. */\n endpoint: {\n primary: __CLI_ENDPOINT_PRIMARY__,\n fallback: __CLI_ENDPOINT_FALLBACK__,\n healthPrimary: __CLI_HEALTH_PRIMARY__,\n healthFallback: __CLI_HEALTH_FALLBACK__,\n },\n // (CLI REST `cliRest` endpoints removed — the human CLI now uses the `/cli`\n // route on the MCP host via `createCliClient`; the separate cli-rest gateway\n // is retired.)\n /** Per-channel config dir under `$HOME` (and at the project level). */\n configDir: __CLI_CONFIG_DIR__,\n} as const;\n\nexport type ChannelManifest = typeof CHANNEL;\n"],"mappings":"AAWO,MAAM,UAAU;AAAA;AAAA,EAErB,MAAM;AAAA;AAAA,EAEN,aAAa;AAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AACb;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configure Command
|
|
3
|
+
*
|
|
4
|
+
* View and modify configuration values for global and project settings.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { ConfigureOptions } from './configure.types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Configure command action handler
|
|
10
|
+
*/
|
|
11
|
+
export declare function configureAction(key: string | undefined, value: string | undefined, options: ConfigureOptions): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Register configure command with Commander
|
|
14
|
+
*/
|
|
15
|
+
export declare function registerConfigureCommand(program: Command): void;
|
|
16
|
+
//# sourceMappingURL=configure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/configure.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,OAAO,EACL,gBAAgB,EAMjB,MAAM,sBAAsB,CAAC;AA+K9B;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2B/D"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveConfig,
|
|
3
|
+
loadGlobalConfig,
|
|
4
|
+
tryLoadProjectConfig,
|
|
5
|
+
saveGlobalConfig,
|
|
6
|
+
saveProjectConfig,
|
|
7
|
+
getConfigPaths
|
|
8
|
+
} from "../config/index.js";
|
|
9
|
+
import { withErrorHandler, CliError, ValidationError } from "../middleware/error-handler.js";
|
|
10
|
+
import {
|
|
11
|
+
printSuccess,
|
|
12
|
+
printBlank,
|
|
13
|
+
printHeader
|
|
14
|
+
} from "../ui/output.js";
|
|
15
|
+
import { colors } from "../ui/colors.js";
|
|
16
|
+
import {
|
|
17
|
+
VALID_KEYS,
|
|
18
|
+
CONFIG_KEY_META,
|
|
19
|
+
isValidKeyForScope,
|
|
20
|
+
parseConfigValue
|
|
21
|
+
} from "./configure.types.js";
|
|
22
|
+
function maskValue(value, visibleChars = 8) {
|
|
23
|
+
if (value.length <= visibleChars) {
|
|
24
|
+
return "***";
|
|
25
|
+
}
|
|
26
|
+
return "***" + value.slice(-visibleChars);
|
|
27
|
+
}
|
|
28
|
+
function formatDisplayValue(key, value) {
|
|
29
|
+
if (value === void 0 || value === null || value === "") {
|
|
30
|
+
return colors.muted("(not set)");
|
|
31
|
+
}
|
|
32
|
+
if (key === "apiKey" && typeof value === "string") {
|
|
33
|
+
return colors.muted(maskValue(value));
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === "boolean") {
|
|
36
|
+
return value ? colors.success("true") : colors.muted("false");
|
|
37
|
+
}
|
|
38
|
+
return String(value);
|
|
39
|
+
}
|
|
40
|
+
function displayAllConfig() {
|
|
41
|
+
const config = resolveConfig();
|
|
42
|
+
const paths = getConfigPaths();
|
|
43
|
+
printBlank();
|
|
44
|
+
printHeader("Configuration");
|
|
45
|
+
printBlank();
|
|
46
|
+
console.log(colors.muted("# Resolved values (from all sources)"));
|
|
47
|
+
printBlank();
|
|
48
|
+
const apiKeyDisplay = config.apiKey ? colors.muted(maskValue(config.apiKey)) : colors.error("(not set)");
|
|
49
|
+
const apiKeySource = config.sources.apiKey ? colors.muted(` (from ${config.sources.apiKey})`) : "";
|
|
50
|
+
console.log(` apiKey: ${apiKeyDisplay}${apiKeySource}`);
|
|
51
|
+
const formatSource = config.sources.mcpOutputFormat ? colors.muted(` (from ${config.sources.mcpOutputFormat})`) : "";
|
|
52
|
+
console.log(` mcpOutputFormat: ${config.mcpOutputFormat}${formatSource}`);
|
|
53
|
+
const projectIdDisplay = formatDisplayValue("projectId", config.projectId);
|
|
54
|
+
const projectIdSource = config.sources.projectId ? colors.muted(` (from ${config.sources.projectId})`) : "";
|
|
55
|
+
console.log(` projectId: ${projectIdDisplay}${projectIdSource}`);
|
|
56
|
+
const specIdDisplay = formatDisplayValue("specificationId", config.specificationId);
|
|
57
|
+
const specIdSource = config.sources.specificationId ? colors.muted(` (from ${config.sources.specificationId})`) : "";
|
|
58
|
+
console.log(` specificationId: ${specIdDisplay}${specIdSource}`);
|
|
59
|
+
const autoSetDisplay = formatDisplayValue("autoSetContext", config.autoSetContext);
|
|
60
|
+
console.log(` autoSetContext: ${autoSetDisplay}`);
|
|
61
|
+
printBlank();
|
|
62
|
+
console.log(colors.muted("# File locations"));
|
|
63
|
+
console.log(` global: ${paths.globalConfig}`);
|
|
64
|
+
console.log(` project: ${paths.projectConfig}`);
|
|
65
|
+
printBlank();
|
|
66
|
+
}
|
|
67
|
+
function displayKey(key) {
|
|
68
|
+
const config = resolveConfig();
|
|
69
|
+
const value = config[key];
|
|
70
|
+
if (key === "apiKey" && typeof value === "string") {
|
|
71
|
+
console.log(maskValue(value));
|
|
72
|
+
} else if (value === void 0 || value === null || value === "") {
|
|
73
|
+
console.log(colors.muted("(not set)"));
|
|
74
|
+
} else {
|
|
75
|
+
console.log(String(value));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function setConfigValue(key, value, global) {
|
|
79
|
+
const scope = global ? "global" : "project";
|
|
80
|
+
if (!isValidKeyForScope(key, scope)) {
|
|
81
|
+
const validKeys = VALID_KEYS[scope];
|
|
82
|
+
throw new ValidationError(
|
|
83
|
+
`Invalid key "${key}" for ${scope} config`,
|
|
84
|
+
`Valid keys: ${validKeys.join(", ")}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
const parseResult = parseConfigValue(key, value);
|
|
88
|
+
if (!parseResult.valid) {
|
|
89
|
+
const meta = CONFIG_KEY_META[key];
|
|
90
|
+
throw new ValidationError(
|
|
91
|
+
`Invalid value "${value}" for key "${key}"`,
|
|
92
|
+
meta?.validValues ? `Valid values: ${meta.validValues.join(", ")}` : void 0
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (global) {
|
|
96
|
+
const currentConfig = loadGlobalConfig();
|
|
97
|
+
saveGlobalConfig({
|
|
98
|
+
...currentConfig,
|
|
99
|
+
[key]: parseResult.parsed
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
const currentConfig = tryLoadProjectConfig() || {};
|
|
103
|
+
saveProjectConfig({
|
|
104
|
+
...currentConfig,
|
|
105
|
+
[key]: parseResult.parsed
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
printSuccess(`Set ${key} = ${value}`);
|
|
109
|
+
}
|
|
110
|
+
function unsetConfigKey(key, global) {
|
|
111
|
+
const scope = global ? "global" : "project";
|
|
112
|
+
if (!isValidKeyForScope(key, scope)) {
|
|
113
|
+
const validKeys = VALID_KEYS[scope];
|
|
114
|
+
throw new ValidationError(
|
|
115
|
+
`Invalid key "${key}" for ${scope} config`,
|
|
116
|
+
`Valid keys: ${validKeys.join(", ")}`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (global) {
|
|
120
|
+
const config = loadGlobalConfig();
|
|
121
|
+
delete config[key];
|
|
122
|
+
saveGlobalConfig(config);
|
|
123
|
+
} else {
|
|
124
|
+
const config = tryLoadProjectConfig() || {};
|
|
125
|
+
delete config[key];
|
|
126
|
+
saveProjectConfig(config);
|
|
127
|
+
}
|
|
128
|
+
printSuccess(`Removed ${key} from ${scope} config`);
|
|
129
|
+
}
|
|
130
|
+
async function configureAction(key, value, options) {
|
|
131
|
+
if (options.unset) {
|
|
132
|
+
unsetConfigKey(options.unset, !!options.global);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (!key) {
|
|
136
|
+
displayAllConfig();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const isValidGlobal = isValidKeyForScope(key, "global");
|
|
140
|
+
const isValidProject = isValidKeyForScope(key, "project");
|
|
141
|
+
if (!isValidGlobal && !isValidProject && key !== "apiKey") {
|
|
142
|
+
const allKeys = [.../* @__PURE__ */ new Set([...VALID_KEYS.global, ...VALID_KEYS.project])];
|
|
143
|
+
throw new ValidationError(
|
|
144
|
+
`Unknown configuration key "${key}"`,
|
|
145
|
+
`Valid keys: ${allKeys.join(", ")}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (value === void 0) {
|
|
149
|
+
displayKey(key);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (key === "apiKey") {
|
|
153
|
+
throw new CliError(
|
|
154
|
+
"Cannot set API key via configure command",
|
|
155
|
+
1,
|
|
156
|
+
"Use `specforge login` to set your API key"
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
setConfigValue(key, value, !!options.global);
|
|
160
|
+
}
|
|
161
|
+
function registerConfigureCommand(program) {
|
|
162
|
+
program.command("configure [key] [value]").alias("config").description("View or modify configuration").option("--global", "Read/write global config (~/.specforge/config.json)").option("--unset <key>", "Remove a configuration key").addHelpText("after", `
|
|
163
|
+
Examples:
|
|
164
|
+
$ specforge configure # Show all configuration
|
|
165
|
+
$ specforge configure mcpOutputFormat # Show MCP output format value
|
|
166
|
+
$ specforge configure mcpOutputFormat toon # Set project MCP output format to toon
|
|
167
|
+
$ specforge configure --global mcpOutputFormat json # Set global MCP output format to json
|
|
168
|
+
$ specforge configure --unset projectId # Remove projectId from project config
|
|
169
|
+
|
|
170
|
+
Valid keys:
|
|
171
|
+
Global: ${VALID_KEYS.global.join(", ")}
|
|
172
|
+
Project: ${VALID_KEYS.project.join(", ")}
|
|
173
|
+
|
|
174
|
+
Key descriptions:
|
|
175
|
+
mcpOutputFormat - Local MCP response encoding: json or toon (44% smaller)
|
|
176
|
+
projectId - Default project ID for this directory
|
|
177
|
+
specificationId - Default specification ID for this directory
|
|
178
|
+
autoSetContext - Auto-set working context on start (true/false)
|
|
179
|
+
defaultProjectId - Global default project ID
|
|
180
|
+
`).action(withErrorHandler(configureAction));
|
|
181
|
+
}
|
|
182
|
+
export {
|
|
183
|
+
configureAction,
|
|
184
|
+
registerConfigureCommand
|
|
185
|
+
};
|
|
186
|
+
//# sourceMappingURL=configure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/configure.ts"],"sourcesContent":["/**\n * Configure Command\n *\n * View and modify configuration values for global and project settings.\n */\n\nimport { Command } from 'commander';\nimport {\n resolveConfig,\n loadGlobalConfig,\n tryLoadProjectConfig,\n saveGlobalConfig,\n saveProjectConfig,\n getConfigPaths,\n} from '../config/index.js';\nimport { withErrorHandler, CliError, ValidationError } from '../middleware/error-handler.js';\nimport {\n printSuccess,\n printBlank,\n printHeader,\n} from '../ui/output.js';\nimport { colors } from '../ui/colors.js';\nimport {\n ConfigureOptions,\n VALID_KEYS,\n CONFIG_KEY_META,\n ValidConfigKey,\n isValidKeyForScope,\n parseConfigValue,\n} from './configure.types.js';\n\n/**\n * Mask a sensitive value (show only last N characters)\n */\nfunction maskValue(value: string, visibleChars = 8): string {\n if (value.length <= visibleChars) {\n return '***';\n }\n return '***' + value.slice(-visibleChars);\n}\n\n/**\n * Format a value for display\n */\nfunction formatDisplayValue(key: string, value: unknown): string {\n if (value === undefined || value === null || value === '') {\n return colors.muted('(not set)');\n }\n\n // Mask API key\n if (key === 'apiKey' && typeof value === 'string') {\n return colors.muted(maskValue(value));\n }\n\n // Boolean values\n if (typeof value === 'boolean') {\n return value ? colors.success('true') : colors.muted('false');\n }\n\n return String(value);\n}\n\n/**\n * Display all configuration values with sources\n */\nfunction displayAllConfig(): void {\n const config = resolveConfig();\n const paths = getConfigPaths();\n\n printBlank();\n printHeader('Configuration');\n printBlank();\n\n console.log(colors.muted('# Resolved values (from all sources)'));\n printBlank();\n\n // API Key (always masked)\n const apiKeyDisplay = config.apiKey\n ? colors.muted(maskValue(config.apiKey))\n : colors.error('(not set)');\n const apiKeySource = config.sources.apiKey\n ? colors.muted(` (from ${config.sources.apiKey})`)\n : '';\n console.log(` apiKey: ${apiKeyDisplay}${apiKeySource}`);\n\n // MCP output format\n const formatSource = config.sources.mcpOutputFormat\n ? colors.muted(` (from ${config.sources.mcpOutputFormat})`)\n : '';\n console.log(` mcpOutputFormat: ${config.mcpOutputFormat}${formatSource}`);\n\n // Project ID\n const projectIdDisplay = formatDisplayValue('projectId', config.projectId);\n const projectIdSource = config.sources.projectId\n ? colors.muted(` (from ${config.sources.projectId})`)\n : '';\n console.log(` projectId: ${projectIdDisplay}${projectIdSource}`);\n\n // Specification ID\n const specIdDisplay = formatDisplayValue('specificationId', config.specificationId);\n const specIdSource = config.sources.specificationId\n ? colors.muted(` (from ${config.sources.specificationId})`)\n : '';\n console.log(` specificationId: ${specIdDisplay}${specIdSource}`);\n\n // Auto Set Context\n const autoSetDisplay = formatDisplayValue('autoSetContext', config.autoSetContext);\n // Note: autoSetContext source tracking not yet implemented in ConfigSources\n console.log(` autoSetContext: ${autoSetDisplay}`);\n\n printBlank();\n console.log(colors.muted('# File locations'));\n console.log(` global: ${paths.globalConfig}`);\n console.log(` project: ${paths.projectConfig}`);\n printBlank();\n}\n\n/**\n * Display a specific configuration key value\n */\nfunction displayKey(key: string): void {\n const config = resolveConfig();\n const value = (config as unknown as Record<string, unknown>)[key];\n\n if (key === 'apiKey' && typeof value === 'string') {\n console.log(maskValue(value));\n } else if (value === undefined || value === null || value === '') {\n console.log(colors.muted('(not set)'));\n } else {\n console.log(String(value));\n }\n}\n\n/**\n * Set a configuration value\n */\nfunction setConfigValue(key: string, value: string, global: boolean): void {\n const scope = global ? 'global' : 'project';\n\n // Validate key for scope\n if (!isValidKeyForScope(key, scope)) {\n const validKeys = VALID_KEYS[scope];\n throw new ValidationError(\n `Invalid key \"${key}\" for ${scope} config`,\n `Valid keys: ${validKeys.join(', ')}`\n );\n }\n\n // Parse and validate value\n const parseResult = parseConfigValue(key, value);\n if (!parseResult.valid) {\n const meta = CONFIG_KEY_META[key as ValidConfigKey];\n throw new ValidationError(\n `Invalid value \"${value}\" for key \"${key}\"`,\n meta?.validValues ? `Valid values: ${meta.validValues.join(', ')}` : undefined\n );\n }\n\n // Save to appropriate config file\n if (global) {\n const currentConfig = loadGlobalConfig();\n saveGlobalConfig({\n ...currentConfig,\n [key]: parseResult.parsed,\n });\n } else {\n const currentConfig = tryLoadProjectConfig() || {};\n saveProjectConfig({\n ...currentConfig,\n [key]: parseResult.parsed,\n });\n }\n\n printSuccess(`Set ${key} = ${value}`);\n}\n\n/**\n * Remove a configuration key\n */\nfunction unsetConfigKey(key: string, global: boolean): void {\n const scope = global ? 'global' : 'project';\n\n // Validate key for scope\n if (!isValidKeyForScope(key, scope)) {\n const validKeys = VALID_KEYS[scope];\n throw new ValidationError(\n `Invalid key \"${key}\" for ${scope} config`,\n `Valid keys: ${validKeys.join(', ')}`\n );\n }\n\n if (global) {\n const config = loadGlobalConfig();\n delete (config as Record<string, unknown>)[key];\n saveGlobalConfig(config);\n } else {\n const config = tryLoadProjectConfig() || {};\n delete (config as Record<string, unknown>)[key];\n saveProjectConfig(config);\n }\n\n printSuccess(`Removed ${key} from ${scope} config`);\n}\n\n/**\n * Configure command action handler\n */\nexport async function configureAction(\n key: string | undefined,\n value: string | undefined,\n options: ConfigureOptions\n): Promise<void> {\n // Handle --unset\n if (options.unset) {\n unsetConfigKey(options.unset, !!options.global);\n return;\n }\n\n // No key = show all config\n if (!key) {\n displayAllConfig();\n return;\n }\n\n // Validate key exists in at least one scope\n const isValidGlobal = isValidKeyForScope(key, 'global');\n const isValidProject = isValidKeyForScope(key, 'project');\n\n if (!isValidGlobal && !isValidProject && key !== 'apiKey') {\n const allKeys = [...new Set([...VALID_KEYS.global, ...VALID_KEYS.project])];\n throw new ValidationError(\n `Unknown configuration key \"${key}\"`,\n `Valid keys: ${allKeys.join(', ')}`\n );\n }\n\n // Key only = show value\n if (value === undefined) {\n displayKey(key);\n return;\n }\n\n // Key + value = set value\n // Prevent setting apiKey via configure\n if (key === 'apiKey') {\n throw new CliError(\n 'Cannot set API key via configure command',\n 1,\n 'Use `specforge login` to set your API key'\n );\n }\n\n setConfigValue(key, value, !!options.global);\n}\n\n/**\n * Register configure command with Commander\n */\nexport function registerConfigureCommand(program: Command): void {\n program\n .command('configure [key] [value]')\n .alias('config')\n .description('View or modify configuration')\n .option('--global', 'Read/write global config (~/.specforge/config.json)')\n .option('--unset <key>', 'Remove a configuration key')\n .addHelpText('after', `\nExamples:\n $ specforge configure # Show all configuration\n $ specforge configure mcpOutputFormat # Show MCP output format value\n $ specforge configure mcpOutputFormat toon # Set project MCP output format to toon\n $ specforge configure --global mcpOutputFormat json # Set global MCP output format to json\n $ specforge configure --unset projectId # Remove projectId from project config\n\nValid keys:\n Global: ${VALID_KEYS.global.join(', ')}\n Project: ${VALID_KEYS.project.join(', ')}\n\nKey descriptions:\n mcpOutputFormat - Local MCP response encoding: json or toon (44% smaller)\n projectId - Default project ID for this directory\n specificationId - Default specification ID for this directory\n autoSetContext - Auto-set working context on start (true/false)\n defaultProjectId - Global default project ID\n`)\n .action(withErrorHandler(configureAction));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configure Command Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions and constants for the configure command.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Configure command options from Commander
|
|
8
|
+
*/
|
|
9
|
+
export interface ConfigureOptions {
|
|
10
|
+
/** Read/write global config (~/.specforge/config.json) */
|
|
11
|
+
global?: boolean;
|
|
12
|
+
/** Remove a configuration key */
|
|
13
|
+
unset?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Configuration scope
|
|
17
|
+
*/
|
|
18
|
+
export type ConfigScope = 'global' | 'project';
|
|
19
|
+
/**
|
|
20
|
+
* Valid configuration keys by scope
|
|
21
|
+
*/
|
|
22
|
+
export declare const VALID_KEYS: Record<ConfigScope, string[]>;
|
|
23
|
+
/**
|
|
24
|
+
* All valid configuration keys (union of both scopes)
|
|
25
|
+
*/
|
|
26
|
+
export declare const ALL_VALID_KEYS: readonly ["mcpOutputFormat", "projectId", "specificationId", "autoSetContext", "defaultProjectId"];
|
|
27
|
+
/**
|
|
28
|
+
* Valid configuration key type
|
|
29
|
+
*/
|
|
30
|
+
export type ValidConfigKey = (typeof ALL_VALID_KEYS)[number];
|
|
31
|
+
/**
|
|
32
|
+
* Configuration key metadata
|
|
33
|
+
*/
|
|
34
|
+
export interface ConfigKeyMeta {
|
|
35
|
+
/** Human-readable description */
|
|
36
|
+
description: string;
|
|
37
|
+
/** Valid scopes for this key */
|
|
38
|
+
scopes: ConfigScope[];
|
|
39
|
+
/** Valid values (if restricted) */
|
|
40
|
+
validValues?: string[];
|
|
41
|
+
/** Whether the value should be masked in output */
|
|
42
|
+
masked?: boolean;
|
|
43
|
+
/** Value type after parsing */
|
|
44
|
+
type: 'string' | 'boolean';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Configuration key metadata map
|
|
48
|
+
*/
|
|
49
|
+
export declare const CONFIG_KEY_META: Record<ValidConfigKey, ConfigKeyMeta>;
|
|
50
|
+
/**
|
|
51
|
+
* Key validator function type
|
|
52
|
+
*/
|
|
53
|
+
export type KeyValidator = (value: string) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Key validators for values that need validation
|
|
56
|
+
*/
|
|
57
|
+
export declare const KEY_VALIDATORS: Partial<Record<ValidConfigKey, KeyValidator>>;
|
|
58
|
+
/**
|
|
59
|
+
* Value parser function type
|
|
60
|
+
*/
|
|
61
|
+
export type ValueParser = (value: string) => unknown;
|
|
62
|
+
/**
|
|
63
|
+
* Value parsers for converting string input to proper types
|
|
64
|
+
*/
|
|
65
|
+
export declare const VALUE_PARSERS: Partial<Record<ValidConfigKey, ValueParser>>;
|
|
66
|
+
/**
|
|
67
|
+
* Configuration display entry
|
|
68
|
+
*/
|
|
69
|
+
export interface ConfigDisplayEntry {
|
|
70
|
+
/** Configuration key */
|
|
71
|
+
key: string;
|
|
72
|
+
/** Resolved value */
|
|
73
|
+
value: unknown;
|
|
74
|
+
/** Source of the value */
|
|
75
|
+
source: string;
|
|
76
|
+
/** Whether to mask the value */
|
|
77
|
+
masked?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validation result
|
|
81
|
+
*/
|
|
82
|
+
export interface ValidationResult {
|
|
83
|
+
/** Whether the validation passed */
|
|
84
|
+
valid: boolean;
|
|
85
|
+
/** Error message if validation failed */
|
|
86
|
+
error?: string;
|
|
87
|
+
/** Hint for valid values */
|
|
88
|
+
hint?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a key is valid for the given scope
|
|
92
|
+
*/
|
|
93
|
+
export declare function isValidKeyForScope(key: string, scope: ConfigScope): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Get validator for a key
|
|
96
|
+
*/
|
|
97
|
+
export declare function getValidator(key: string): KeyValidator | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Get parser for a key
|
|
100
|
+
*/
|
|
101
|
+
export declare function getParser(key: string): ValueParser | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Parse and validate a configuration value
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseConfigValue(key: string, value: string): {
|
|
106
|
+
parsed: unknown;
|
|
107
|
+
valid: boolean;
|
|
108
|
+
error?: string;
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=configure.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.types.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/configure.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAGpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,oGAMjB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+BAA+B;IAC/B,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,aAAa,CA4BjE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,YAAY,CAAC,CAGxE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAErD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAEtE,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAE3E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBrD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const VALID_KEYS = {
|
|
2
|
+
global: ["mcpOutputFormat", "defaultProjectId"],
|
|
3
|
+
project: ["mcpOutputFormat", "projectId", "specificationId", "autoSetContext"]
|
|
4
|
+
};
|
|
5
|
+
const ALL_VALID_KEYS = [
|
|
6
|
+
"mcpOutputFormat",
|
|
7
|
+
"projectId",
|
|
8
|
+
"specificationId",
|
|
9
|
+
"autoSetContext",
|
|
10
|
+
"defaultProjectId"
|
|
11
|
+
];
|
|
12
|
+
const CONFIG_KEY_META = {
|
|
13
|
+
mcpOutputFormat: {
|
|
14
|
+
description: "Local MCP response encoding (json or toon)",
|
|
15
|
+
scopes: ["global", "project"],
|
|
16
|
+
validValues: ["json", "toon"],
|
|
17
|
+
type: "string"
|
|
18
|
+
},
|
|
19
|
+
projectId: {
|
|
20
|
+
description: "Default project ID",
|
|
21
|
+
scopes: ["project"],
|
|
22
|
+
type: "string"
|
|
23
|
+
},
|
|
24
|
+
specificationId: {
|
|
25
|
+
description: "Default specification ID",
|
|
26
|
+
scopes: ["project"],
|
|
27
|
+
type: "string"
|
|
28
|
+
},
|
|
29
|
+
autoSetContext: {
|
|
30
|
+
description: "Auto-set working context on MCP server start",
|
|
31
|
+
scopes: ["project"],
|
|
32
|
+
validValues: ["true", "false"],
|
|
33
|
+
type: "boolean"
|
|
34
|
+
},
|
|
35
|
+
defaultProjectId: {
|
|
36
|
+
description: "Global default project ID",
|
|
37
|
+
scopes: ["global"],
|
|
38
|
+
type: "string"
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const KEY_VALIDATORS = {
|
|
42
|
+
mcpOutputFormat: (v) => ["json", "toon"].includes(v),
|
|
43
|
+
autoSetContext: (v) => ["true", "false"].includes(v.toLowerCase())
|
|
44
|
+
};
|
|
45
|
+
const VALUE_PARSERS = {
|
|
46
|
+
autoSetContext: (v) => v.toLowerCase() === "true"
|
|
47
|
+
};
|
|
48
|
+
function isValidKeyForScope(key, scope) {
|
|
49
|
+
return VALID_KEYS[scope].includes(key);
|
|
50
|
+
}
|
|
51
|
+
function getValidator(key) {
|
|
52
|
+
return KEY_VALIDATORS[key];
|
|
53
|
+
}
|
|
54
|
+
function getParser(key) {
|
|
55
|
+
return VALUE_PARSERS[key];
|
|
56
|
+
}
|
|
57
|
+
function parseConfigValue(key, value) {
|
|
58
|
+
const validator = getValidator(key);
|
|
59
|
+
if (validator && !validator(value)) {
|
|
60
|
+
const meta = CONFIG_KEY_META[key];
|
|
61
|
+
return {
|
|
62
|
+
parsed: value,
|
|
63
|
+
valid: false,
|
|
64
|
+
error: `Invalid value "${value}" for key "${key}". Valid values: ${meta?.validValues?.join(", ")}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const parser = getParser(key);
|
|
68
|
+
const parsed = parser ? parser(value) : value;
|
|
69
|
+
return { parsed, valid: true };
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
ALL_VALID_KEYS,
|
|
73
|
+
CONFIG_KEY_META,
|
|
74
|
+
KEY_VALIDATORS,
|
|
75
|
+
VALID_KEYS,
|
|
76
|
+
VALUE_PARSERS,
|
|
77
|
+
getParser,
|
|
78
|
+
getValidator,
|
|
79
|
+
isValidKeyForScope,
|
|
80
|
+
parseConfigValue
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=configure.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/configure.types.ts"],"sourcesContent":["/**\n * Configure Command Types\n *\n * Type definitions and constants for the configure command.\n */\n\n/**\n * Configure command options from Commander\n */\nexport interface ConfigureOptions {\n /** Read/write global config (~/.specforge/config.json) */\n global?: boolean;\n /** Remove a configuration key */\n unset?: string;\n}\n\n/**\n * Configuration scope\n */\nexport type ConfigScope = 'global' | 'project';\n\n/**\n * Valid configuration keys by scope\n */\nexport const VALID_KEYS: Record<ConfigScope, string[]> = {\n global: ['mcpOutputFormat', 'defaultProjectId'],\n project: ['mcpOutputFormat', 'projectId', 'specificationId', 'autoSetContext'],\n};\n\n/**\n * All valid configuration keys (union of both scopes)\n */\nexport const ALL_VALID_KEYS = [\n 'mcpOutputFormat',\n 'projectId',\n 'specificationId',\n 'autoSetContext',\n 'defaultProjectId',\n] as const;\n\n/**\n * Valid configuration key type\n */\nexport type ValidConfigKey = (typeof ALL_VALID_KEYS)[number];\n\n/**\n * Configuration key metadata\n */\nexport interface ConfigKeyMeta {\n /** Human-readable description */\n description: string;\n /** Valid scopes for this key */\n scopes: ConfigScope[];\n /** Valid values (if restricted) */\n validValues?: string[];\n /** Whether the value should be masked in output */\n masked?: boolean;\n /** Value type after parsing */\n type: 'string' | 'boolean';\n}\n\n/**\n * Configuration key metadata map\n */\nexport const CONFIG_KEY_META: Record<ValidConfigKey, ConfigKeyMeta> = {\n mcpOutputFormat: {\n description: 'Local MCP response encoding (json or toon)',\n scopes: ['global', 'project'],\n validValues: ['json', 'toon'],\n type: 'string',\n },\n projectId: {\n description: 'Default project ID',\n scopes: ['project'],\n type: 'string',\n },\n specificationId: {\n description: 'Default specification ID',\n scopes: ['project'],\n type: 'string',\n },\n autoSetContext: {\n description: 'Auto-set working context on MCP server start',\n scopes: ['project'],\n validValues: ['true', 'false'],\n type: 'boolean',\n },\n defaultProjectId: {\n description: 'Global default project ID',\n scopes: ['global'],\n type: 'string',\n },\n};\n\n/**\n * Key validator function type\n */\nexport type KeyValidator = (value: string) => boolean;\n\n/**\n * Key validators for values that need validation\n */\nexport const KEY_VALIDATORS: Partial<Record<ValidConfigKey, KeyValidator>> = {\n mcpOutputFormat: (v: string) => ['json', 'toon'].includes(v),\n autoSetContext: (v: string) => ['true', 'false'].includes(v.toLowerCase()),\n};\n\n/**\n * Value parser function type\n */\nexport type ValueParser = (value: string) => unknown;\n\n/**\n * Value parsers for converting string input to proper types\n */\nexport const VALUE_PARSERS: Partial<Record<ValidConfigKey, ValueParser>> = {\n autoSetContext: (v: string) => v.toLowerCase() === 'true',\n};\n\n/**\n * Configuration display entry\n */\nexport interface ConfigDisplayEntry {\n /** Configuration key */\n key: string;\n /** Resolved value */\n value: unknown;\n /** Source of the value */\n source: string;\n /** Whether to mask the value */\n masked?: boolean;\n}\n\n/**\n * Validation result\n */\nexport interface ValidationResult {\n /** Whether the validation passed */\n valid: boolean;\n /** Error message if validation failed */\n error?: string;\n /** Hint for valid values */\n hint?: string;\n}\n\n/**\n * Check if a key is valid for the given scope\n */\nexport function isValidKeyForScope(key: string, scope: ConfigScope): boolean {\n return VALID_KEYS[scope].includes(key);\n}\n\n/**\n * Get validator for a key\n */\nexport function getValidator(key: string): KeyValidator | undefined {\n return KEY_VALIDATORS[key as ValidConfigKey];\n}\n\n/**\n * Get parser for a key\n */\nexport function getParser(key: string): ValueParser | undefined {\n return VALUE_PARSERS[key as ValidConfigKey];\n}\n\n/**\n * Parse and validate a configuration value\n */\nexport function parseConfigValue(\n key: string,\n value: string\n): { parsed: unknown; valid: boolean; error?: string } {\n // Validate if validator exists\n const validator = getValidator(key);\n if (validator && !validator(value)) {\n const meta = CONFIG_KEY_META[key as ValidConfigKey];\n return {\n parsed: value,\n valid: false,\n error: `Invalid value \"${value}\" for key \"${key}\". Valid values: ${meta?.validValues?.join(', ')}`,\n };\n }\n\n // Parse the value\n const parser = getParser(key);\n const parsed = parser ? parser(value) : value;\n\n return { parsed, valid: true };\n}\n"],"mappings":"AAwBO,MAAM,aAA4C;AAAA,EACvD,QAAQ,CAAC,mBAAmB,kBAAkB;AAAA,EAC9C,SAAS,CAAC,mBAAmB,aAAa,mBAAmB,gBAAgB;AAC/E;AAKO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA0BO,MAAM,kBAAyD;AAAA,EACpE,iBAAiB;AAAA,IACf,aAAa;AAAA,IACb,QAAQ,CAAC,UAAU,SAAS;AAAA,IAC5B,aAAa,CAAC,QAAQ,MAAM;AAAA,IAC5B,MAAM;AAAA,EACR;AAAA,EACA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,QAAQ,CAAC,SAAS;AAAA,IAClB,MAAM;AAAA,EACR;AAAA,EACA,iBAAiB;AAAA,IACf,aAAa;AAAA,IACb,QAAQ,CAAC,SAAS;AAAA,IAClB,MAAM;AAAA,EACR;AAAA,EACA,gBAAgB;AAAA,IACd,aAAa;AAAA,IACb,QAAQ,CAAC,SAAS;AAAA,IAClB,aAAa,CAAC,QAAQ,OAAO;AAAA,IAC7B,MAAM;AAAA,EACR;AAAA,EACA,kBAAkB;AAAA,IAChB,aAAa;AAAA,IACb,QAAQ,CAAC,QAAQ;AAAA,IACjB,MAAM;AAAA,EACR;AACF;AAUO,MAAM,iBAAgE;AAAA,EAC3E,iBAAiB,CAAC,MAAc,CAAC,QAAQ,MAAM,EAAE,SAAS,CAAC;AAAA,EAC3D,gBAAgB,CAAC,MAAc,CAAC,QAAQ,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC;AAC3E;AAUO,MAAM,gBAA8D;AAAA,EACzE,gBAAgB,CAAC,MAAc,EAAE,YAAY,MAAM;AACrD;AA+BO,SAAS,mBAAmB,KAAa,OAA6B;AAC3E,SAAO,WAAW,KAAK,EAAE,SAAS,GAAG;AACvC;AAKO,SAAS,aAAa,KAAuC;AAClE,SAAO,eAAe,GAAqB;AAC7C;AAKO,SAAS,UAAU,KAAsC;AAC9D,SAAO,cAAc,GAAqB;AAC5C;AAKO,SAAS,iBACd,KACA,OACqD;AAErD,QAAM,YAAY,aAAa,GAAG;AAClC,MAAI,aAAa,CAAC,UAAU,KAAK,GAAG;AAClC,UAAM,OAAO,gBAAgB,GAAqB;AAClD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO,kBAAkB,KAAK,cAAc,GAAG,oBAAoB,MAAM,aAAa,KAAK,IAAI,CAAC;AAAA,IAClG;AAAA,EACF;AAGA,QAAM,SAAS,UAAU,GAAG;AAC5B,QAAM,SAAS,SAAS,OAAO,KAAK,IAAI;AAExC,SAAO,EAAE,QAAQ,OAAO,KAAK;AAC/B;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call Command Implementation
|
|
3
|
+
*
|
|
4
|
+
* Allows directly calling MCP tools with JSON arguments, useful for testing
|
|
5
|
+
* and debugging.
|
|
6
|
+
*/
|
|
7
|
+
import type { CallOptions } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Call command implementation
|
|
10
|
+
*
|
|
11
|
+
* Directly calls an MCP tool with optional JSON arguments.
|
|
12
|
+
*/
|
|
13
|
+
export declare function callCommand(tool: string, options: CallOptions): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/debug/call.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAsD9C;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DnF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import { resolveConfig } from "../../config/index.js";
|
|
3
|
+
import { colors } from "../../ui/colors.js";
|
|
4
|
+
import { ApiClient } from "../../../client/api-client.js";
|
|
5
|
+
import { handleToolCall } from "../../../tools/index.js";
|
|
6
|
+
function parseArgs(argsString) {
|
|
7
|
+
if (!argsString) {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(argsString);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Invalid JSON in --args. Example: --args='{"ticketId": "abc123"}'`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function formatToon(response) {
|
|
19
|
+
if (typeof response === "object" && response !== null) {
|
|
20
|
+
const lines = ["@response"];
|
|
21
|
+
const entries = Object.entries(response);
|
|
22
|
+
for (const [key, value] of entries) {
|
|
23
|
+
if (typeof value === "object" && value !== null) {
|
|
24
|
+
lines.push(` ${key}: ${JSON.stringify(value)}`);
|
|
25
|
+
} else {
|
|
26
|
+
lines.push(` ${key}: ${value}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return lines.join("\n");
|
|
30
|
+
}
|
|
31
|
+
return String(response);
|
|
32
|
+
}
|
|
33
|
+
function formatOutput(response, options) {
|
|
34
|
+
if (options.raw) {
|
|
35
|
+
return typeof response === "string" ? response : JSON.stringify(response);
|
|
36
|
+
}
|
|
37
|
+
if (options.format === "toon") {
|
|
38
|
+
return formatToon(response);
|
|
39
|
+
}
|
|
40
|
+
return JSON.stringify(response, null, 2);
|
|
41
|
+
}
|
|
42
|
+
async function callCommand(tool, options) {
|
|
43
|
+
if (!tool) {
|
|
44
|
+
console.error(colors.error("\nError: Tool name is required."));
|
|
45
|
+
console.error(`Usage: specforge call <tool> --args='{"key": "value"}'`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
const config = resolveConfig();
|
|
49
|
+
let args;
|
|
50
|
+
try {
|
|
51
|
+
args = parseArgs(options.args);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
54
|
+
console.error(colors.error(`
|
|
55
|
+
Error: ${message}`));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const spinner = ora(`Calling ${tool}...`).start();
|
|
59
|
+
try {
|
|
60
|
+
if (!config.apiKey) {
|
|
61
|
+
spinner.fail("Not authenticated");
|
|
62
|
+
console.error(colors.error("\nError: Not authenticated."));
|
|
63
|
+
console.error(colors.muted("Run `specforge login` to authenticate first."));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const client = new ApiClient({
|
|
67
|
+
apiKey: config.apiKey,
|
|
68
|
+
apiUrl: config.apiUrl,
|
|
69
|
+
debug: config.debug
|
|
70
|
+
});
|
|
71
|
+
const response = await handleToolCall(client, tool, args, config.debug);
|
|
72
|
+
spinner.stop();
|
|
73
|
+
const output = formatOutput(response, options);
|
|
74
|
+
console.log(output);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
spinner.fail(`Failed to call ${tool}`);
|
|
77
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
78
|
+
if (message.includes("Unknown tool") || message.includes("not found")) {
|
|
79
|
+
console.error(colors.error(`
|
|
80
|
+
Error: Unknown tool "${tool}".`));
|
|
81
|
+
console.error(colors.muted("Run 'specforge tools' to see available tools."));
|
|
82
|
+
} else if (message.includes("required")) {
|
|
83
|
+
console.error(colors.error(`
|
|
84
|
+
Error: ${message}`));
|
|
85
|
+
console.error(colors.muted("Check the tool requires specific arguments."));
|
|
86
|
+
} else {
|
|
87
|
+
console.error(colors.error(`
|
|
88
|
+
Error: ${message}`));
|
|
89
|
+
}
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
callCommand
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=call.js.map
|