gsd-pi 2.29.0 → 2.30.0-dev.7e1bbce
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 +24 -17
- package/dist/cli.js +51 -0
- package/dist/extension-registry.d.ts +63 -0
- package/dist/extension-registry.js +166 -0
- package/dist/headless.js +4 -0
- package/dist/help-text.js +35 -0
- package/dist/loader.js +10 -1
- package/dist/resource-loader.js +11 -1
- package/dist/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/dist/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/dist/resources/extensions/context7/extension-manifest.json +12 -0
- package/dist/resources/extensions/google-search/extension-manifest.json +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +31 -0
- package/dist/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/dist/resources/extensions/gsd/auto-post-unit.ts +45 -13
- package/dist/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/dist/resources/extensions/gsd/auto-recovery.ts +18 -23
- package/dist/resources/extensions/gsd/auto-start.ts +18 -32
- package/dist/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/dist/resources/extensions/gsd/auto.ts +2 -24
- package/dist/resources/extensions/gsd/captures.ts +4 -10
- package/dist/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/dist/resources/extensions/gsd/commands-handlers.ts +22 -2
- package/dist/resources/extensions/gsd/commands-logs.ts +13 -14
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +108 -24
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/dist/resources/extensions/gsd/detection.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +3 -1
- package/dist/resources/extensions/gsd/extension-manifest.json +18 -0
- package/dist/resources/extensions/gsd/forensics.ts +2 -2
- package/dist/resources/extensions/gsd/git-service.ts +3 -2
- package/dist/resources/extensions/gsd/gitignore.ts +9 -63
- package/dist/resources/extensions/gsd/gsd-db.ts +1 -165
- package/dist/resources/extensions/gsd/guided-flow.ts +8 -5
- package/dist/resources/extensions/gsd/index.ts +16 -3
- package/dist/resources/extensions/gsd/json-persistence.ts +16 -1
- package/dist/resources/extensions/gsd/md-importer.ts +3 -2
- package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +3 -2
- package/dist/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/dist/resources/extensions/gsd/migrate-external.ts +123 -0
- package/dist/resources/extensions/gsd/paths.ts +24 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
- package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/dist/resources/extensions/gsd/preferences.ts +10 -5
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/queue-order.ts +10 -11
- package/dist/resources/extensions/gsd/repo-identity.ts +148 -0
- package/dist/resources/extensions/gsd/resource-version.ts +99 -0
- package/dist/resources/extensions/gsd/roadmap-slices.ts +22 -7
- package/dist/resources/extensions/gsd/session-forensics.ts +4 -3
- package/dist/resources/extensions/gsd/session-lock.ts +53 -4
- package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
- package/dist/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/dist/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +1 -11
- package/dist/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/dist/resources/extensions/gsd/worktree.ts +42 -5
- package/dist/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +8 -19
- package/dist/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -17
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
- package/dist/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/dist/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/dist/resources/extensions/subagent/extension-manifest.json +13 -0
- package/dist/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/dist/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/dist/resources/extensions/voice/extension-manifest.json +12 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/skills/react-best-practices/SKILL.md +1 -1
- package/dist/worktree-cli.d.ts +34 -0
- package/dist/worktree-cli.js +294 -0
- package/dist/worktree-name-gen.d.ts +7 -0
- package/dist/worktree-name-gen.js +44 -0
- package/package.json +1 -1
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/src/resources/extensions/context7/extension-manifest.json +12 -0
- package/src/resources/extensions/google-search/extension-manifest.json +12 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +31 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/src/resources/extensions/gsd/auto-post-unit.ts +45 -13
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/src/resources/extensions/gsd/auto-recovery.ts +18 -23
- package/src/resources/extensions/gsd/auto-start.ts +18 -32
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/src/resources/extensions/gsd/auto.ts +2 -24
- package/src/resources/extensions/gsd/captures.ts +4 -10
- package/src/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +22 -2
- package/src/resources/extensions/gsd/commands-logs.ts +13 -14
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +108 -24
- package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/src/resources/extensions/gsd/detection.ts +2 -1
- package/src/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/extension-manifest.json +18 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +3 -2
- package/src/resources/extensions/gsd/gitignore.ts +9 -63
- package/src/resources/extensions/gsd/gsd-db.ts +1 -165
- package/src/resources/extensions/gsd/guided-flow.ts +8 -5
- package/src/resources/extensions/gsd/index.ts +16 -3
- package/src/resources/extensions/gsd/json-persistence.ts +16 -1
- package/src/resources/extensions/gsd/md-importer.ts +3 -2
- package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/src/resources/extensions/gsd/migrate-external.ts +123 -0
- package/src/resources/extensions/gsd/paths.ts +24 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/src/resources/extensions/gsd/preferences-models.ts +7 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +10 -5
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/queue-order.ts +10 -11
- package/src/resources/extensions/gsd/repo-identity.ts +148 -0
- package/src/resources/extensions/gsd/resource-version.ts +99 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +22 -7
- package/src/resources/extensions/gsd/session-forensics.ts +4 -3
- package/src/resources/extensions/gsd/session-lock.ts +53 -4
- package/src/resources/extensions/gsd/session-status-io.ts +23 -41
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/src/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/gsd/worktree-command.ts +1 -11
- package/src/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/src/resources/extensions/gsd/worktree.ts +42 -5
- package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/src/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/src/resources/extensions/remote-questions/discord-adapter.ts +8 -19
- package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/src/resources/extensions/remote-questions/http-client.ts +76 -0
- package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -17
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
- package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/src/resources/extensions/subagent/extension-manifest.json +13 -0
- package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/src/resources/extensions/voice/extension-manifest.json +12 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/src/resources/skills/react-best-practices/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/src/resources/extensions/mcporter/index.ts +0 -525
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Extensions Command — /gsd extensions
|
|
3
|
+
*
|
|
4
|
+
* Manage the extension registry: list, enable, disable, info.
|
|
5
|
+
* Self-contained — no imports outside the extensions tree (extensions are loaded
|
|
6
|
+
* via jiti at runtime from ~/.gsd/agent/, not compiled by tsc).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
|
|
14
|
+
// ─── Types (mirrored from extension-registry.ts) ────────────────────────────
|
|
15
|
+
|
|
16
|
+
interface ExtensionManifest {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
version: string;
|
|
20
|
+
description: string;
|
|
21
|
+
tier: "core" | "bundled" | "community";
|
|
22
|
+
requires: { platform: string };
|
|
23
|
+
provides?: {
|
|
24
|
+
tools?: string[];
|
|
25
|
+
commands?: string[];
|
|
26
|
+
hooks?: string[];
|
|
27
|
+
shortcuts?: string[];
|
|
28
|
+
};
|
|
29
|
+
dependencies?: {
|
|
30
|
+
extensions?: string[];
|
|
31
|
+
runtime?: string[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface ExtensionRegistryEntry {
|
|
36
|
+
id: string;
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
source: "bundled" | "user" | "project";
|
|
39
|
+
disabledAt?: string;
|
|
40
|
+
disabledReason?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ExtensionRegistry {
|
|
44
|
+
version: 1;
|
|
45
|
+
entries: Record<string, ExtensionRegistryEntry>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─── Registry I/O ───────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
function getRegistryPath(): string {
|
|
51
|
+
return join(homedir(), ".gsd", "extensions", "registry.json");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getAgentExtensionsDir(): string {
|
|
55
|
+
return join(homedir(), ".gsd", "agent", "extensions");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function loadRegistry(): ExtensionRegistry {
|
|
59
|
+
const filePath = getRegistryPath();
|
|
60
|
+
try {
|
|
61
|
+
if (!existsSync(filePath)) return { version: 1, entries: {} };
|
|
62
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
63
|
+
const parsed = JSON.parse(raw);
|
|
64
|
+
if (typeof parsed === "object" && parsed !== null && parsed.version === 1 && typeof parsed.entries === "object") {
|
|
65
|
+
return parsed as ExtensionRegistry;
|
|
66
|
+
}
|
|
67
|
+
return { version: 1, entries: {} };
|
|
68
|
+
} catch {
|
|
69
|
+
return { version: 1, entries: {} };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function saveRegistry(registry: ExtensionRegistry): void {
|
|
74
|
+
const filePath = getRegistryPath();
|
|
75
|
+
try {
|
|
76
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
77
|
+
const tmp = filePath + ".tmp";
|
|
78
|
+
writeFileSync(tmp, JSON.stringify(registry, null, 2), "utf-8");
|
|
79
|
+
renameSync(tmp, filePath);
|
|
80
|
+
} catch { /* non-fatal */ }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isEnabled(registry: ExtensionRegistry, id: string): boolean {
|
|
84
|
+
const entry = registry.entries[id];
|
|
85
|
+
if (!entry) return true;
|
|
86
|
+
return entry.enabled;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readManifest(dir: string): ExtensionManifest | null {
|
|
90
|
+
const mPath = join(dir, "extension-manifest.json");
|
|
91
|
+
if (!existsSync(mPath)) return null;
|
|
92
|
+
try {
|
|
93
|
+
const raw = JSON.parse(readFileSync(mPath, "utf-8"));
|
|
94
|
+
if (typeof raw?.id === "string" && typeof raw?.name === "string") return raw as ExtensionManifest;
|
|
95
|
+
return null;
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function discoverManifests(): Map<string, ExtensionManifest> {
|
|
102
|
+
const extDir = getAgentExtensionsDir();
|
|
103
|
+
const manifests = new Map<string, ExtensionManifest>();
|
|
104
|
+
if (!existsSync(extDir)) return manifests;
|
|
105
|
+
for (const entry of readdirSync(extDir, { withFileTypes: true })) {
|
|
106
|
+
if (!entry.isDirectory()) continue;
|
|
107
|
+
const m = readManifest(join(extDir, entry.name));
|
|
108
|
+
if (m) manifests.set(m.id, m);
|
|
109
|
+
}
|
|
110
|
+
return manifests;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ─── Command Handler ────────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
export async function handleExtensions(args: string, ctx: ExtensionCommandContext): Promise<void> {
|
|
116
|
+
const parts = args.split(/\s+/).filter(Boolean);
|
|
117
|
+
const subCmd = parts[0] ?? "list";
|
|
118
|
+
|
|
119
|
+
if (subCmd === "list") {
|
|
120
|
+
handleList(ctx);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (subCmd === "enable") {
|
|
125
|
+
handleEnable(parts[1], ctx);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (subCmd === "disable") {
|
|
130
|
+
handleDisable(parts[1], parts.slice(2).join(" "), ctx);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (subCmd === "info") {
|
|
135
|
+
handleInfo(parts[1], ctx);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ctx.ui.notify(
|
|
140
|
+
`Unknown: /gsd extensions ${subCmd}. Usage: /gsd extensions [list|enable|disable|info]`,
|
|
141
|
+
"warning",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function handleList(ctx: ExtensionCommandContext): void {
|
|
146
|
+
const manifests = discoverManifests();
|
|
147
|
+
const registry = loadRegistry();
|
|
148
|
+
|
|
149
|
+
if (manifests.size === 0) {
|
|
150
|
+
ctx.ui.notify("No extension manifests found.", "warning");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Sort: core first, then alphabetical
|
|
155
|
+
const sorted = [...manifests.values()].sort((a, b) => {
|
|
156
|
+
if (a.tier === "core" && b.tier !== "core") return -1;
|
|
157
|
+
if (b.tier === "core" && a.tier !== "core") return 1;
|
|
158
|
+
return a.id.localeCompare(b.id);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const lines: string[] = [];
|
|
162
|
+
const hdr = padRight("Extensions", 38) + padRight("Status", 10) + padRight("Tier", 10) + padRight("Tools", 7) + "Commands";
|
|
163
|
+
lines.push(hdr);
|
|
164
|
+
lines.push("─".repeat(hdr.length));
|
|
165
|
+
|
|
166
|
+
for (const m of sorted) {
|
|
167
|
+
const enabled = isEnabled(registry, m.id);
|
|
168
|
+
const status = enabled ? "enabled" : "disabled";
|
|
169
|
+
const toolCount = m.provides?.tools?.length ?? 0;
|
|
170
|
+
const cmdCount = m.provides?.commands?.length ?? 0;
|
|
171
|
+
const label = `${m.id} (${m.name})`;
|
|
172
|
+
|
|
173
|
+
lines.push(
|
|
174
|
+
padRight(label, 38) +
|
|
175
|
+
padRight(status, 10) +
|
|
176
|
+
padRight(m.tier, 10) +
|
|
177
|
+
padRight(String(toolCount), 7) +
|
|
178
|
+
String(cmdCount),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
if (!enabled) {
|
|
182
|
+
lines.push(` ↳ gsd extensions enable ${m.id}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
ctx.ui.notify(lines.join("\n"), "info");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function handleEnable(id: string | undefined, ctx: ExtensionCommandContext): void {
|
|
190
|
+
if (!id) {
|
|
191
|
+
ctx.ui.notify("Usage: /gsd extensions enable <id>", "warning");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const manifests = discoverManifests();
|
|
196
|
+
if (!manifests.has(id)) {
|
|
197
|
+
ctx.ui.notify(`Extension "${id}" not found. Run /gsd extensions list to see available extensions.`, "warning");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const registry = loadRegistry();
|
|
202
|
+
if (isEnabled(registry, id)) {
|
|
203
|
+
ctx.ui.notify(`Extension "${id}" is already enabled.`, "info");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const entry = registry.entries[id];
|
|
208
|
+
if (entry) {
|
|
209
|
+
entry.enabled = true;
|
|
210
|
+
delete entry.disabledAt;
|
|
211
|
+
delete entry.disabledReason;
|
|
212
|
+
} else {
|
|
213
|
+
registry.entries[id] = { id, enabled: true, source: "bundled" };
|
|
214
|
+
}
|
|
215
|
+
saveRegistry(registry);
|
|
216
|
+
ctx.ui.notify(`Enabled "${id}". Restart GSD to activate.`, "info");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function handleDisable(id: string | undefined, reason: string, ctx: ExtensionCommandContext): void {
|
|
220
|
+
if (!id) {
|
|
221
|
+
ctx.ui.notify("Usage: /gsd extensions disable <id>", "warning");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const manifests = discoverManifests();
|
|
226
|
+
const manifest = manifests.get(id) ?? null;
|
|
227
|
+
|
|
228
|
+
if (!manifests.has(id)) {
|
|
229
|
+
ctx.ui.notify(`Extension "${id}" not found. Run /gsd extensions list to see available extensions.`, "warning");
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (manifest?.tier === "core") {
|
|
234
|
+
ctx.ui.notify(`Cannot disable "${id}" — it is a core extension.`, "warning");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const registry = loadRegistry();
|
|
239
|
+
if (!isEnabled(registry, id)) {
|
|
240
|
+
ctx.ui.notify(`Extension "${id}" is already disabled.`, "info");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const entry = registry.entries[id];
|
|
245
|
+
if (entry) {
|
|
246
|
+
entry.enabled = false;
|
|
247
|
+
entry.disabledAt = new Date().toISOString();
|
|
248
|
+
entry.disabledReason = reason || undefined;
|
|
249
|
+
} else {
|
|
250
|
+
registry.entries[id] = {
|
|
251
|
+
id,
|
|
252
|
+
enabled: false,
|
|
253
|
+
source: "bundled",
|
|
254
|
+
disabledAt: new Date().toISOString(),
|
|
255
|
+
disabledReason: reason || undefined,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
saveRegistry(registry);
|
|
259
|
+
ctx.ui.notify(`Disabled "${id}". Restart GSD to deactivate.`, "info");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function handleInfo(id: string | undefined, ctx: ExtensionCommandContext): void {
|
|
263
|
+
if (!id) {
|
|
264
|
+
ctx.ui.notify("Usage: /gsd extensions info <id>", "warning");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const manifests = discoverManifests();
|
|
269
|
+
const manifest = manifests.get(id);
|
|
270
|
+
if (!manifest) {
|
|
271
|
+
ctx.ui.notify(`Extension "${id}" not found.`, "warning");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const registry = loadRegistry();
|
|
276
|
+
const enabled = isEnabled(registry, id);
|
|
277
|
+
const entry = registry.entries[id];
|
|
278
|
+
|
|
279
|
+
const lines: string[] = [
|
|
280
|
+
`${manifest.name} (${manifest.id})`,
|
|
281
|
+
"",
|
|
282
|
+
` Version: ${manifest.version}`,
|
|
283
|
+
` Description: ${manifest.description}`,
|
|
284
|
+
` Tier: ${manifest.tier}`,
|
|
285
|
+
` Status: ${enabled ? "enabled" : "disabled"}`,
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
if (entry?.disabledAt) {
|
|
289
|
+
lines.push(` Disabled at: ${entry.disabledAt}`);
|
|
290
|
+
}
|
|
291
|
+
if (entry?.disabledReason) {
|
|
292
|
+
lines.push(` Reason: ${entry.disabledReason}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (manifest.provides) {
|
|
296
|
+
lines.push("");
|
|
297
|
+
lines.push(" Provides:");
|
|
298
|
+
if (manifest.provides.tools?.length) {
|
|
299
|
+
lines.push(` Tools: ${manifest.provides.tools.join(", ")}`);
|
|
300
|
+
}
|
|
301
|
+
if (manifest.provides.commands?.length) {
|
|
302
|
+
lines.push(` Commands: ${manifest.provides.commands.join(", ")}`);
|
|
303
|
+
}
|
|
304
|
+
if (manifest.provides.hooks?.length) {
|
|
305
|
+
lines.push(` Hooks: ${manifest.provides.hooks.join(", ")}`);
|
|
306
|
+
}
|
|
307
|
+
if (manifest.provides.shortcuts?.length) {
|
|
308
|
+
lines.push(` Shortcuts: ${manifest.provides.shortcuts.join(", ")}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (manifest.dependencies) {
|
|
313
|
+
lines.push("");
|
|
314
|
+
lines.push(" Dependencies:");
|
|
315
|
+
if (manifest.dependencies.extensions?.length) {
|
|
316
|
+
lines.push(` Extensions: ${manifest.dependencies.extensions.join(", ")}`);
|
|
317
|
+
}
|
|
318
|
+
if (manifest.dependencies.runtime?.length) {
|
|
319
|
+
lines.push(` Runtime: ${manifest.dependencies.runtime.join(", ")}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
ctx.ui.notify(lines.join("\n"), "info");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function padRight(str: string, len: number): string {
|
|
327
|
+
return str.length >= len ? str + " " : str + " ".repeat(len - str.length);
|
|
328
|
+
}
|
|
@@ -9,6 +9,7 @@ import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent
|
|
|
9
9
|
import { existsSync, readFileSync, mkdirSync } from "node:fs";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { deriveState } from "./state.js";
|
|
12
|
+
import { gsdRoot } from "./paths.js";
|
|
12
13
|
import { appendCapture, hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
13
14
|
import { appendOverride, appendKnowledge } from "./files.js";
|
|
14
15
|
import {
|
|
@@ -19,7 +20,26 @@ import {
|
|
|
19
20
|
filterDoctorIssues,
|
|
20
21
|
} from "./doctor.js";
|
|
21
22
|
import { isAutoActive } from "./auto.js";
|
|
22
|
-
import { projectRoot
|
|
23
|
+
import { projectRoot } from "./commands.js";
|
|
24
|
+
import { loadPrompt } from "./prompt-loader.js";
|
|
25
|
+
|
|
26
|
+
export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void {
|
|
27
|
+
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
|
|
28
|
+
const workflow = readFileSync(workflowPath, "utf-8");
|
|
29
|
+
const prompt = loadPrompt("doctor-heal", {
|
|
30
|
+
doctorSummary: reportText,
|
|
31
|
+
structuredIssues,
|
|
32
|
+
scopeLabel: scope ?? "active milestone / blocking scope",
|
|
33
|
+
doctorCommandSuffix: scope ? ` ${scope}` : "",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const content = `Read the following GSD workflow protocol and execute exactly.\n\n${workflow}\n\n## Your Task\n\n${prompt}`;
|
|
37
|
+
|
|
38
|
+
pi.sendMessage(
|
|
39
|
+
{ customType: "gsd-doctor-heal", content, display: false },
|
|
40
|
+
{ triggerTurn: true },
|
|
41
|
+
);
|
|
42
|
+
}
|
|
23
43
|
|
|
24
44
|
export async function handleDoctor(args: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
|
|
25
45
|
const trimmed = args.trim();
|
|
@@ -117,7 +137,7 @@ export async function handleCapture(args: string, ctx: ExtensionCommandContext):
|
|
|
117
137
|
const basePath = process.cwd();
|
|
118
138
|
|
|
119
139
|
// Ensure .gsd/ exists — capture should work even without a milestone
|
|
120
|
-
const gsdDir =
|
|
140
|
+
const gsdDir = gsdRoot(basePath);
|
|
121
141
|
if (!existsSync(gsdDir)) {
|
|
122
142
|
mkdirSync(gsdDir, { recursive: true });
|
|
123
143
|
}
|
|
@@ -14,6 +14,7 @@ import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
|
14
14
|
import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from "node:fs";
|
|
15
15
|
import { join } from "node:path";
|
|
16
16
|
import { gsdRoot } from "./paths.js";
|
|
17
|
+
import { loadJsonFileOrNull } from "./json-persistence.js";
|
|
17
18
|
|
|
18
19
|
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
19
20
|
|
|
@@ -331,20 +332,18 @@ async function handleLogsList(basePath: string, ctx: ExtensionCommandContext): P
|
|
|
331
332
|
|
|
332
333
|
// Metrics summary
|
|
333
334
|
const metricsPath = join(gsdRoot(basePath), "metrics.json");
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
} catch { /* ignore */ }
|
|
335
|
+
const isMetrics = (d: unknown): d is { units: Array<Record<string, unknown>> } =>
|
|
336
|
+
d !== null && typeof d === "object" && "units" in d! && Array.isArray((d as Record<string, unknown>).units);
|
|
337
|
+
const metrics = loadJsonFileOrNull(metricsPath, isMetrics);
|
|
338
|
+
if (metrics && metrics.units.length > 0) {
|
|
339
|
+
const units = metrics.units;
|
|
340
|
+
const totalCost = units.reduce((sum: number, u) => sum + ((u.cost as number) ?? 0), 0);
|
|
341
|
+
const totalTokens = units.reduce((sum: number, u) => {
|
|
342
|
+
const t = u.tokens as Record<string, number> | undefined;
|
|
343
|
+
return sum + (t?.total ?? 0);
|
|
344
|
+
}, 0);
|
|
345
|
+
lines.push("");
|
|
346
|
+
lines.push(`Metrics: ${units.length} units tracked · $${totalCost.toFixed(2)} · ${(totalTokens / 1000).toFixed(0)}K tokens`);
|
|
348
347
|
}
|
|
349
348
|
|
|
350
349
|
lines.push("");
|
|
@@ -260,27 +260,57 @@ async function configureModels(ctx: ExtensionCommandContext, prefs: Record<strin
|
|
|
260
260
|
group.push(m);
|
|
261
261
|
}
|
|
262
262
|
const providers = Array.from(byProvider.keys()).sort((a, b) => a.localeCompare(b));
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const group = byProvider.get(provider)!;
|
|
267
|
-
modelOptions.push(`─── ${provider} (${group.length}) ───`);
|
|
268
|
-
for (const m of group) {
|
|
269
|
-
modelOptions.push(`${m.id} · ${m.provider}`);
|
|
270
|
-
}
|
|
263
|
+
// Sort models within each provider
|
|
264
|
+
for (const group of byProvider.values()) {
|
|
265
|
+
group.sort((a, b) => a.id.localeCompare(b.id));
|
|
271
266
|
}
|
|
272
|
-
|
|
267
|
+
|
|
268
|
+
// Build provider menu with model counts
|
|
269
|
+
const providerOptions = providers.map(p => {
|
|
270
|
+
const count = byProvider.get(p)!.length;
|
|
271
|
+
return `${p} (${count} models)`;
|
|
272
|
+
});
|
|
273
|
+
providerOptions.push("(keep current)", "(clear)", "(type manually)");
|
|
273
274
|
|
|
274
275
|
for (const phase of modelPhases) {
|
|
275
276
|
const current = models[phase] ?? "";
|
|
276
|
-
const
|
|
277
|
-
|
|
277
|
+
const phaseLabel = `Model for ${phase} phase${current ? ` (current: ${current})` : ""}`;
|
|
278
|
+
|
|
279
|
+
// Step 1: pick provider
|
|
280
|
+
const providerChoice = await ctx.ui.select(`${phaseLabel} — choose provider:`, providerOptions);
|
|
281
|
+
if (!providerChoice || typeof providerChoice !== "string" || providerChoice === "(keep current)") continue;
|
|
282
|
+
|
|
283
|
+
if (providerChoice === "(clear)") {
|
|
284
|
+
delete models[phase];
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (providerChoice === "(type manually)") {
|
|
289
|
+
const input = await ctx.ui.input(
|
|
290
|
+
`${phaseLabel} — enter model ID:`,
|
|
291
|
+
current || "e.g. claude-sonnet-4-20250514",
|
|
292
|
+
);
|
|
293
|
+
if (input !== null && input !== undefined) {
|
|
294
|
+
const val = input.trim();
|
|
295
|
+
if (val) models[phase] = val;
|
|
296
|
+
}
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Step 2: pick model within provider
|
|
301
|
+
const providerName = providerChoice.replace(/ \(\d+ models?\)$/, "");
|
|
302
|
+
const group = byProvider.get(providerName);
|
|
303
|
+
if (!group) continue;
|
|
304
|
+
|
|
305
|
+
const modelOptions = group.map(m => m.id);
|
|
306
|
+
modelOptions.push("(keep current)", "(clear)");
|
|
278
307
|
|
|
279
|
-
|
|
280
|
-
|
|
308
|
+
const modelChoice = await ctx.ui.select(`${phaseLabel} — ${providerName}:`, modelOptions);
|
|
309
|
+
if (modelChoice && typeof modelChoice === "string" && modelChoice !== "(keep current)") {
|
|
310
|
+
if (modelChoice === "(clear)") {
|
|
281
311
|
delete models[phase];
|
|
282
312
|
} else {
|
|
283
|
-
models[phase] =
|
|
313
|
+
models[phase] = modelChoice;
|
|
284
314
|
}
|
|
285
315
|
}
|
|
286
316
|
}
|