@opengsd/gsd-pi 1.0.2-dev.e9a1b49 → 1.0.2-dev.fb7ddf1
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 +63 -12
- package/dist/headless-answers.js +2 -1
- package/dist/headless-events.d.ts +1 -0
- package/dist/headless-events.js +8 -1
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +44 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +81 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +38 -1
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +36 -55
- package/dist/resources/extensions/gsd/auto.js +40 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +7 -2
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
- package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +3 -20
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repo-identity.js +36 -6
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/extensions/subagent/index.js +8 -15
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/resources/skills/agent-browser/SKILL.md +1 -1
- package/dist/resources/skills/api-design/SKILL.md +1 -1
- package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
- package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/dist/resources/skills/forensics/SKILL.md +2 -2
- package/dist/resources/skills/grill-me/SKILL.md +1 -1
- package/dist/resources/skills/handoff/SKILL.md +1 -1
- package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/dist/resources/skills/observability/SKILL.md +1 -1
- package/dist/resources/skills/security-review/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/dist/resources/skills/tdd/SKILL.md +1 -1
- package/dist/resources/skills/write-docs/SKILL.md +1 -1
- package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/worktree-cli.d.ts +0 -2
- package/dist/worktree-cli.js +21 -9
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
- package/packages/cloud-mcp-gateway/package.json +4 -3
- package/packages/contracts/dist/rpc.test.js +5 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +15 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/dist/workflow.test.js +1 -0
- package/packages/contracts/dist/workflow.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +7 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +47 -8
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +16 -14
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/bin/pi-ai.js +14 -0
- package/packages/pi-ai/dist/models.generated.d.ts +48 -206
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +73 -226
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
- package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +96 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +47 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +47 -57
- package/src/resources/extensions/gsd/auto.ts +50 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +7 -2
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
- package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +3 -20
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repo-identity.ts +35 -7
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/extensions/subagent/index.ts +8 -15
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/src/resources/skills/agent-browser/SKILL.md +1 -1
- package/src/resources/skills/api-design/SKILL.md +1 -1
- package/src/resources/skills/code-optimizer/SKILL.md +6 -11
- package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/src/resources/skills/forensics/SKILL.md +2 -2
- package/src/resources/skills/grill-me/SKILL.md +1 -1
- package/src/resources/skills/handoff/SKILL.md +1 -1
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/src/resources/skills/observability/SKILL.md +1 -1
- package/src/resources/skills/security-review/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/src/resources/skills/tdd/SKILL.md +1 -1
- package/src/resources/skills/write-docs/SKILL.md +1 -1
- package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
|
@@ -16,6 +16,47 @@ export const CUSTOM_SEARCH_TOOL_NAMES = ["search-the-web", "search_and_read", "g
|
|
|
16
16
|
|
|
17
17
|
/** Thinking block types that require signature validation by the API */
|
|
18
18
|
const THINKING_TYPES = new Set(["thinking", "redacted_thinking"]);
|
|
19
|
+
const NATIVE_SERVER_TOOL_USE_TYPES = new Set([
|
|
20
|
+
"server_tool_use",
|
|
21
|
+
"serverToolUse",
|
|
22
|
+
]);
|
|
23
|
+
const NATIVE_WEB_SEARCH_RESULT_TYPES = new Set([
|
|
24
|
+
"web_search_tool_result",
|
|
25
|
+
"webSearchResult",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
function nativeServerToolId(block: any): string | undefined {
|
|
29
|
+
if (!NATIVE_SERVER_TOOL_USE_TYPES.has(block?.type)) return undefined;
|
|
30
|
+
return typeof block.id === "string" ? block.id : undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function nativeWebSearchResultId(block: any): string | undefined {
|
|
34
|
+
if (!NATIVE_WEB_SEARCH_RESULT_TYPES.has(block?.type)) return undefined;
|
|
35
|
+
const id = block.type === "webSearchResult" ? block.toolUseId : block.tool_use_id;
|
|
36
|
+
return typeof id === "string" ? id : undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function hasCompleteNativeServerToolReplay(content: any[]): boolean {
|
|
40
|
+
const pendingToolUseIds = new Set<string>();
|
|
41
|
+
let sawNativeServerToolUse = false;
|
|
42
|
+
|
|
43
|
+
for (const block of content) {
|
|
44
|
+
const toolUseId = nativeServerToolId(block);
|
|
45
|
+
if (toolUseId !== undefined) {
|
|
46
|
+
if (pendingToolUseIds.has(toolUseId)) return false;
|
|
47
|
+
sawNativeServerToolUse = true;
|
|
48
|
+
pendingToolUseIds.add(toolUseId);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const resultId = nativeWebSearchResultId(block);
|
|
53
|
+
if (resultId !== undefined) {
|
|
54
|
+
if (!pendingToolUseIds.delete(resultId)) return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return sawNativeServerToolUse && pendingToolUseIds.size === 0;
|
|
59
|
+
}
|
|
19
60
|
|
|
20
61
|
/**
|
|
21
62
|
* Providers whose Anthropic-Messages endpoint is known to accept the native
|
|
@@ -36,6 +77,11 @@ const NATIVE_WEB_SEARCH_PROVIDERS = new Set([
|
|
|
36
77
|
"vercel-ai-gateway",
|
|
37
78
|
]);
|
|
38
79
|
|
|
80
|
+
function looksLikeAnthropicModelName(modelName: string): boolean {
|
|
81
|
+
const normalized = modelName.trim().toLowerCase();
|
|
82
|
+
return normalized.startsWith("claude-") || normalized.startsWith("anthropic/claude-");
|
|
83
|
+
}
|
|
84
|
+
|
|
39
85
|
/**
|
|
40
86
|
* True when the model is an Anthropic-shaped transport AND the provider is
|
|
41
87
|
* known to accept the native `web_search_20250305` tool. Gate both on api
|
|
@@ -89,11 +135,10 @@ export interface NativeSearchPI {
|
|
|
89
135
|
* those blocks. The Anthropic API detects the modification and rejects the
|
|
90
136
|
* request with "thinking blocks cannot be modified."
|
|
91
137
|
*
|
|
92
|
-
* Fix: Remove thinking blocks from
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* current turn regardless.
|
|
138
|
+
* Fix: Remove thinking blocks only from assistant messages that do not carry
|
|
139
|
+
* native server-tool blocks. Complete native server-tool histories can be
|
|
140
|
+
* replayed as-is; stripping thinking from those messages is itself a latest
|
|
141
|
+
* assistant message modification.
|
|
97
142
|
*/
|
|
98
143
|
export function stripThinkingFromHistory(
|
|
99
144
|
messages: Array<Record<string, unknown>>
|
|
@@ -103,6 +148,9 @@ export function stripThinkingFromHistory(
|
|
|
103
148
|
|
|
104
149
|
const content = msg.content;
|
|
105
150
|
if (!Array.isArray(content)) continue;
|
|
151
|
+
if (hasCompleteNativeServerToolReplay(content)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
106
154
|
|
|
107
155
|
msg.content = content.filter(
|
|
108
156
|
(block: any) => !THINKING_TYPES.has(block?.type)
|
|
@@ -180,6 +228,8 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
|
|
|
180
228
|
// The model name heuristic is needed for session restores where
|
|
181
229
|
// modelsAreEqual suppresses model_select AND the SDK doesn't pass model.
|
|
182
230
|
const eventModel = event.model as { provider?: string; api?: string } | undefined;
|
|
231
|
+
const payloadModelName = typeof payload.model === "string" ? payload.model : "";
|
|
232
|
+
const payloadLooksAnthropic = payloadModelName ? looksLikeAnthropicModelName(payloadModelName) : undefined;
|
|
183
233
|
let isAnthropic: boolean;
|
|
184
234
|
if (eventModel?.api || eventModel?.provider) {
|
|
185
235
|
// Preferred path: gate on api shape + provider allowlist. Both fields
|
|
@@ -188,12 +238,14 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
|
|
|
188
238
|
// (#444 regression) or minimax-served Claude-compat as Anthropic (#4492).
|
|
189
239
|
isAnthropic = supportsNativeWebSearch(eventModel);
|
|
190
240
|
} else if (modelSelectFired) {
|
|
191
|
-
|
|
241
|
+
// The model_select flag can be stale if the next request omits event.model
|
|
242
|
+
// after a provider switch. A concrete non-Claude payload must win so an
|
|
243
|
+
// Anthropic-only tool never leaks into OpenAI Responses requests.
|
|
244
|
+
isAnthropic = isAnthropicProvider && payloadLooksAnthropic !== false;
|
|
192
245
|
} else {
|
|
193
246
|
// Last resort: session-restore paths where the SDK doesn't pass model.
|
|
194
247
|
// The model-name prefix is best-effort and assumes direct Anthropic.
|
|
195
|
-
|
|
196
|
-
isAnthropic = modelName.startsWith("claude-");
|
|
248
|
+
isAnthropic = payloadLooksAnthropic === true;
|
|
197
249
|
}
|
|
198
250
|
if (!isAnthropic) return;
|
|
199
251
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
19
19
|
import { type Theme } from "@gsd/pi-coding-agent";
|
|
20
20
|
import { Key, matchesKey, truncateToWidth, type TUI } from "@gsd/pi-tui";
|
|
21
|
+
import { renderSharedDialogFrame } from "./dialog-frame.js";
|
|
21
22
|
import { makeUI, GLYPH } from "./ui.js";
|
|
22
23
|
|
|
23
24
|
export interface ConfirmOptions {
|
|
@@ -83,20 +84,18 @@ export async function showConfirm(
|
|
|
83
84
|
function render(width: number): string[] {
|
|
84
85
|
if (cachedLines) return cachedLines;
|
|
85
86
|
|
|
86
|
-
const
|
|
87
|
+
const contentWidth = Math.max(1, width - 4);
|
|
88
|
+
const ui = makeUI(theme, contentWidth);
|
|
87
89
|
const lines: string[] = [];
|
|
88
90
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
89
91
|
|
|
90
92
|
push(
|
|
91
|
-
ui.bar(),
|
|
92
|
-
ui.blank(),
|
|
93
|
-
ui.header(` ${opts.title}`),
|
|
94
93
|
ui.blank(),
|
|
95
94
|
ui.subtitle(` ${opts.message}`),
|
|
96
95
|
ui.blank(),
|
|
97
96
|
);
|
|
98
97
|
|
|
99
|
-
const add = (s: string) => truncateToWidth(s,
|
|
98
|
+
const add = (s: string) => truncateToWidth(s, contentWidth);
|
|
100
99
|
const option = (num: number, label: string, selected: boolean) => {
|
|
101
100
|
if (selected) {
|
|
102
101
|
return add(` ${theme.fg("accent", GLYPH.cursor)} ${theme.fg("accent", `${num}. ${label}`)}`);
|
|
@@ -107,14 +106,11 @@ export async function showConfirm(
|
|
|
107
106
|
lines.push(option(1, yesLabel, cursor === 0));
|
|
108
107
|
lines.push(option(2, noLabel, cursor === 1));
|
|
109
108
|
|
|
110
|
-
push(
|
|
111
|
-
|
|
112
|
-
ui.hints(["↑/↓ to choose", "y/n to quick-select", "enter to confirm"]),
|
|
113
|
-
ui.bar(),
|
|
114
|
-
);
|
|
109
|
+
push(ui.blank());
|
|
110
|
+
const footer = ui.hints(["↑/↓ to choose", "y/n to quick-select", "enter to confirm"])[0] ?? "";
|
|
115
111
|
|
|
116
|
-
cachedLines = lines;
|
|
117
|
-
return
|
|
112
|
+
cachedLines = renderSharedDialogFrame(theme, opts.title, lines, width, { footer });
|
|
113
|
+
return cachedLines;
|
|
118
114
|
}
|
|
119
115
|
|
|
120
116
|
return {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type Theme } from "@gsd/pi-coding-agent";
|
|
2
|
+
import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
|
|
3
|
+
|
|
4
|
+
type ThemeColor = Parameters<Theme["fg"]>[0];
|
|
5
|
+
|
|
6
|
+
export interface SharedDialogFrameOptions {
|
|
7
|
+
borderColor?: ThemeColor;
|
|
8
|
+
footer?: string | string[];
|
|
9
|
+
paddingX?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function safeLine(text: string, width: number): string {
|
|
13
|
+
return truncateToWidth(text, width, "");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function padVisible(text: string, width: number): string {
|
|
17
|
+
const clipped = safeLine(text, width);
|
|
18
|
+
return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function renderTopBorder(
|
|
22
|
+
theme: Theme,
|
|
23
|
+
title: string,
|
|
24
|
+
width: number,
|
|
25
|
+
border: (text: string) => string,
|
|
26
|
+
): string {
|
|
27
|
+
const trimmedTitle = title.trim();
|
|
28
|
+
if (!trimmedTitle || width < 10) {
|
|
29
|
+
return border("╭" + "─".repeat(width - 2) + "╮");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const safeTitle = safeLine(trimmedTitle, Math.max(0, width - 7));
|
|
33
|
+
const fill = Math.max(0, width - visibleWidth(safeTitle) - 5);
|
|
34
|
+
return border("╭─ ") + theme.bold(theme.fg("accent", safeTitle)) + border(" " + "─".repeat(fill) + "╮");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function renderSharedDialogFrame(
|
|
38
|
+
theme: Theme,
|
|
39
|
+
title: string,
|
|
40
|
+
inner: string[],
|
|
41
|
+
width: number,
|
|
42
|
+
options: SharedDialogFrameOptions = {},
|
|
43
|
+
): string[] {
|
|
44
|
+
if (width < 4) return inner.map((line) => safeLine(line, width));
|
|
45
|
+
|
|
46
|
+
const paddingX = Math.max(0, options.paddingX ?? 1);
|
|
47
|
+
const contentWidth = Math.max(0, width - 2 - paddingX * 2);
|
|
48
|
+
const border = (text: string) => theme.fg(options.borderColor ?? "borderAccent", text);
|
|
49
|
+
const pad = " ".repeat(paddingX);
|
|
50
|
+
const lines = [renderTopBorder(theme, title, width, border)];
|
|
51
|
+
|
|
52
|
+
for (const line of inner) {
|
|
53
|
+
lines.push(border("│") + pad + padVisible(line, contentWidth) + pad + border("│"));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const footer = Array.isArray(options.footer)
|
|
57
|
+
? options.footer
|
|
58
|
+
: options.footer
|
|
59
|
+
? [options.footer]
|
|
60
|
+
: [];
|
|
61
|
+
if (footer.length > 0) {
|
|
62
|
+
lines.push(border("├" + "─".repeat(width - 2) + "┤"));
|
|
63
|
+
for (const line of footer) {
|
|
64
|
+
lines.push(border("│") + pad + padVisible(line, contentWidth) + pad + border("│"));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
|
|
69
|
+
return lines;
|
|
70
|
+
}
|
|
71
|
+
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
truncateToWidth,
|
|
37
37
|
type TUI,
|
|
38
38
|
} from "@gsd/pi-tui";
|
|
39
|
+
import { renderSharedDialogFrame } from "./dialog-frame.js";
|
|
39
40
|
import { mergeSideBySide } from "./layout-utils.js";
|
|
40
41
|
import { makeUI, INDENT } from "./ui.js";
|
|
41
42
|
|
|
@@ -126,6 +127,10 @@ const DIVIDER_CHARS = " │ ";
|
|
|
126
127
|
const DIVIDER_WIDTH = 3;
|
|
127
128
|
const PREVIEW_MAX_LINES = 20; // hard cap — keeps total ≤ 24 rows for single-question
|
|
128
129
|
|
|
130
|
+
function dialogContentWidth(width: number): number {
|
|
131
|
+
return width < 4 ? Math.max(1, width) : Math.max(1, width - 4);
|
|
132
|
+
}
|
|
133
|
+
|
|
129
134
|
// ─── Wrap-up screen ───────────────────────────────────────────────────────────
|
|
130
135
|
|
|
131
136
|
export async function showWrapUpScreen(
|
|
@@ -157,11 +162,12 @@ export async function showWrapUpScreen(
|
|
|
157
162
|
|
|
158
163
|
function render(width: number): string[] {
|
|
159
164
|
if (cachedLines) return cachedLines;
|
|
160
|
-
const
|
|
165
|
+
const contentWidth = dialogContentWidth(width);
|
|
166
|
+
const ui = makeUI(theme, contentWidth);
|
|
161
167
|
const lines: string[] = [];
|
|
162
168
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
163
169
|
|
|
164
|
-
push(ui.
|
|
170
|
+
push(ui.blank());
|
|
165
171
|
if (opts.progress) push(ui.meta(` ${opts.progress}`), ui.blank());
|
|
166
172
|
|
|
167
173
|
if (cursorIdx === 1) {
|
|
@@ -175,14 +181,11 @@ export async function showWrapUpScreen(
|
|
|
175
181
|
} else {
|
|
176
182
|
push(ui.actionUnselected(2, opts.keepGoingLabel, "Continue with another batch of questions."));
|
|
177
183
|
}
|
|
178
|
-
push(
|
|
179
|
-
ui.blank(),
|
|
180
|
-
ui.hints(["↑/↓ to choose", "1/2 to quick-select", "enter to confirm"]),
|
|
181
|
-
ui.bar(),
|
|
182
|
-
);
|
|
184
|
+
push(ui.blank());
|
|
183
185
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
const footer = ui.hints(["↑/↓ to choose", "1/2 to quick-select", "enter to confirm"])[0] ?? "";
|
|
187
|
+
cachedLines = renderSharedDialogFrame(theme, opts.headline, lines, width, { footer });
|
|
188
|
+
return cachedLines;
|
|
186
189
|
}
|
|
187
190
|
|
|
188
191
|
return {
|
|
@@ -469,11 +472,13 @@ export async function showInterviewRound(
|
|
|
469
472
|
// ── Review screen ────────────────────────────────────────────────
|
|
470
473
|
|
|
471
474
|
function renderReviewScreen(width: number): string[] {
|
|
472
|
-
const
|
|
475
|
+
const contentWidth = dialogContentWidth(width);
|
|
476
|
+
const title = opts.reviewHeadline ?? "Review your answers";
|
|
477
|
+
const ui = makeUI(theme, contentWidth);
|
|
473
478
|
const lines: string[] = [];
|
|
474
479
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
475
480
|
|
|
476
|
-
push(ui.
|
|
481
|
+
push(ui.blank());
|
|
477
482
|
|
|
478
483
|
for (let i = 0; i < questions.length; i++) {
|
|
479
484
|
const q = questions[i];
|
|
@@ -500,24 +505,22 @@ export async function showInterviewRound(
|
|
|
500
505
|
push(
|
|
501
506
|
ui.actionSelected(0, "Submit answers"),
|
|
502
507
|
ui.blank(),
|
|
503
|
-
ui.hints(["← to go back and edit", "enter to submit", `esc to ${opts.exitLabel ?? "end interview"}`]),
|
|
504
|
-
ui.bar(),
|
|
505
508
|
);
|
|
506
509
|
|
|
507
|
-
|
|
510
|
+
const footer = ui.hints(["← to go back and edit", "enter to submit", `esc to ${opts.exitLabel ?? "end interview"}`])[0] ?? "";
|
|
511
|
+
return renderSharedDialogFrame(theme, title, lines, width, { footer });
|
|
508
512
|
}
|
|
509
513
|
|
|
510
514
|
// ── Exit confirm screen ──────────────────────────────────────────
|
|
511
515
|
|
|
512
516
|
function renderExitConfirm(width: number): string[] {
|
|
513
|
-
const
|
|
517
|
+
const contentWidth = dialogContentWidth(width);
|
|
518
|
+
const title = opts.exitHeadline ?? "End interview?";
|
|
519
|
+
const ui = makeUI(theme, contentWidth);
|
|
514
520
|
const lines: string[] = [];
|
|
515
521
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
516
522
|
|
|
517
523
|
push(
|
|
518
|
-
ui.bar(),
|
|
519
|
-
ui.blank(),
|
|
520
|
-
ui.header(` ${opts.exitHeadline ?? "End interview?"}`),
|
|
521
524
|
ui.blank(),
|
|
522
525
|
ui.subtitle(" Answers from this batch won't be saved."),
|
|
523
526
|
ui.blank(),
|
|
@@ -538,13 +541,10 @@ export async function showInterviewRound(
|
|
|
538
541
|
} else {
|
|
539
542
|
push(ui.actionUnselected(2, exitActionLabel, "Exit and discard this batch of answers."));
|
|
540
543
|
}
|
|
541
|
-
push(
|
|
542
|
-
ui.blank(),
|
|
543
|
-
ui.hints(["↑/↓ to choose", "1/2 to quick-select", "enter to confirm"]),
|
|
544
|
-
ui.bar(),
|
|
545
|
-
);
|
|
544
|
+
push(ui.blank());
|
|
546
545
|
|
|
547
|
-
|
|
546
|
+
const footer = ui.hints(["↑/↓ to choose", "1/2 to quick-select", "enter to confirm"])[0] ?? "";
|
|
547
|
+
return renderSharedDialogFrame(theme, title, lines, width, { footer });
|
|
548
548
|
}
|
|
549
549
|
|
|
550
550
|
// ── Preview helpers ──────────────────────────────────────────────
|
|
@@ -648,17 +648,17 @@ export async function showInterviewRound(
|
|
|
648
648
|
if (showingExitConfirm) { cachedLines = renderExitConfirm(width); return cachedLines; }
|
|
649
649
|
if (showingReview) { cachedLines = renderReviewScreen(width); return cachedLines; }
|
|
650
650
|
|
|
651
|
+
const contentWidth = dialogContentWidth(width);
|
|
652
|
+
const title = questions[currentIdx]?.header || "GSD Interview";
|
|
651
653
|
const useSideBySide = questionHasAnyPreview()
|
|
652
|
-
&&
|
|
654
|
+
&& contentWidth >= (MIN_OPTIONS_WIDTH + MIN_PREVIEW_WIDTH + DIVIDER_WIDTH);
|
|
653
655
|
|
|
654
656
|
if (useSideBySide) {
|
|
655
657
|
// ── Preview path ──────────────────────────────────────
|
|
656
|
-
const ui = makeUI(theme,
|
|
658
|
+
const ui = makeUI(theme, contentWidth);
|
|
657
659
|
const lines: string[] = [];
|
|
658
660
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
659
661
|
|
|
660
|
-
push(ui.bar());
|
|
661
|
-
|
|
662
662
|
if (isMultiQuestion) {
|
|
663
663
|
const unanswered = questions.filter((_, i) => !isQuestionAnswered(i)).length;
|
|
664
664
|
const answeredSet = new Set(questions.map((_, i) => i).filter(i => isQuestionAnswered(i)));
|
|
@@ -680,12 +680,15 @@ export async function showInterviewRound(
|
|
|
680
680
|
// component: spinner/loader (1-2), status line (1), tool header (1),
|
|
681
681
|
// plus a safety margin for future additions.
|
|
682
682
|
const termRows = (typeof process !== "undefined" && process.stdout?.rows) || 24;
|
|
683
|
-
const footerLines =
|
|
683
|
+
const footerLines = 5; // body spacer + frame top/footer/bottom chrome
|
|
684
684
|
const tuiChrome = 5;
|
|
685
685
|
const maxBody = Math.min(PREVIEW_MAX_LINES, Math.max(6, termRows - lines.length - footerLines - tuiChrome));
|
|
686
686
|
|
|
687
|
-
const previewWidth = Math.max(
|
|
688
|
-
|
|
687
|
+
const previewWidth = Math.max(
|
|
688
|
+
MIN_PREVIEW_WIDTH,
|
|
689
|
+
Math.min(contentWidth - MIN_OPTIONS_WIDTH - DIVIDER_WIDTH, Math.floor(contentWidth * PREVIEW_RATIO)),
|
|
690
|
+
);
|
|
691
|
+
const leftWidth = Math.max(MIN_OPTIONS_WIDTH, contentWidth - previewWidth - DIVIDER_WIDTH);
|
|
689
692
|
|
|
690
693
|
const fullLeft = renderOptionsColumn(leftWidth);
|
|
691
694
|
const leftLines = fullLeft.slice(0, maxBody);
|
|
@@ -709,7 +712,7 @@ export async function showInterviewRound(
|
|
|
709
712
|
while (leftLines.length < maxBody) leftLines.push("");
|
|
710
713
|
while (rightLines.length < maxBody) rightLines.push("");
|
|
711
714
|
const divider = theme.fg("dim", DIVIDER_CHARS);
|
|
712
|
-
lines.push(...mergeSideBySide(leftLines, rightLines, leftWidth, divider,
|
|
715
|
+
lines.push(...mergeSideBySide(leftLines, rightLines, leftWidth, divider, contentWidth));
|
|
713
716
|
|
|
714
717
|
// Footer
|
|
715
718
|
push(ui.blank());
|
|
@@ -729,15 +732,15 @@ export async function showInterviewRound(
|
|
|
729
732
|
hints.push(isLast && allAnswered() ? "enter to review" : "enter to next");
|
|
730
733
|
}
|
|
731
734
|
hints.push("esc to exit");
|
|
732
|
-
|
|
735
|
+
const footer = ui.hints(hints)[0] ?? "";
|
|
733
736
|
|
|
734
|
-
cachedLines = lines;
|
|
735
|
-
return
|
|
737
|
+
cachedLines = renderSharedDialogFrame(theme, title, lines, width, { footer });
|
|
738
|
+
return cachedLines;
|
|
736
739
|
}
|
|
737
740
|
|
|
738
741
|
// ── Original path — no preview, untouched ────────────────
|
|
739
742
|
|
|
740
|
-
const ui = makeUI(theme,
|
|
743
|
+
const ui = makeUI(theme, contentWidth);
|
|
741
744
|
const lines: string[] = [];
|
|
742
745
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
743
746
|
|
|
@@ -745,8 +748,6 @@ export async function showInterviewRound(
|
|
|
745
748
|
const st = states[currentIdx];
|
|
746
749
|
const multiSel = isMultiSelect(currentIdx);
|
|
747
750
|
|
|
748
|
-
push(ui.bar());
|
|
749
|
-
|
|
750
751
|
// ── Progress header ────────────────────────────────────────────
|
|
751
752
|
if (isMultiQuestion) {
|
|
752
753
|
const unanswered = questions.filter((_, i) => !isQuestionAnswered(i)).length;
|
|
@@ -809,7 +810,7 @@ export async function showInterviewRound(
|
|
|
809
810
|
if (st.notesVisible || focusNotes) {
|
|
810
811
|
push(ui.blank(), ui.notesLabel(focusNotes));
|
|
811
812
|
if (focusNotes) {
|
|
812
|
-
for (const line of getEditor().render(
|
|
813
|
+
for (const line of getEditor().render(contentWidth - 2)) lines.push(truncateToWidth(` ${line}`, contentWidth));
|
|
813
814
|
} else if (st.notes) {
|
|
814
815
|
push(ui.notesText(st.notes));
|
|
815
816
|
}
|
|
@@ -833,10 +834,10 @@ export async function showInterviewRound(
|
|
|
833
834
|
hints.push(isLast && allAnswered() ? "enter to review" : "enter to next");
|
|
834
835
|
}
|
|
835
836
|
hints.push("esc to exit");
|
|
836
|
-
|
|
837
|
+
const footer = ui.hints(hints)[0] ?? "";
|
|
837
838
|
|
|
838
|
-
cachedLines = lines;
|
|
839
|
-
return
|
|
839
|
+
cachedLines = renderSharedDialogFrame(theme, title, lines, width, { footer });
|
|
840
|
+
return cachedLines;
|
|
840
841
|
}
|
|
841
842
|
|
|
842
843
|
return {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
45
45
|
import { type Theme } from "@gsd/pi-coding-agent";
|
|
46
46
|
import { Key, matchesKey, type TUI } from "@gsd/pi-tui";
|
|
47
|
+
import { renderSharedDialogFrame } from "./dialog-frame.js";
|
|
47
48
|
import { makeUI } from "./ui.js";
|
|
48
49
|
|
|
49
50
|
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
@@ -142,14 +143,14 @@ export async function showNextAction(
|
|
|
142
143
|
|
|
143
144
|
function render(width: number): string[] {
|
|
144
145
|
if (cachedLines) return cachedLines;
|
|
145
|
-
const
|
|
146
|
+
const contentWidth = Math.max(1, width - 4);
|
|
147
|
+
const ui = makeUI(theme, contentWidth);
|
|
146
148
|
const lines: string[] = [];
|
|
147
149
|
const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
|
|
148
150
|
|
|
149
151
|
// ── Header — uses success colour to signal completion ────────────
|
|
150
152
|
// Note: next-action intentionally uses "success" for its bar/title
|
|
151
153
|
// to distinguish it from regular accent-coloured screens.
|
|
152
|
-
push(ui.bar());
|
|
153
154
|
push(ui.blank());
|
|
154
155
|
push(ui.header(` ✓ ${opts.title}`));
|
|
155
156
|
|
|
@@ -192,11 +193,10 @@ export async function showNextAction(
|
|
|
192
193
|
|
|
193
194
|
// ── Footer ────────────────────────────────────────────────────────
|
|
194
195
|
const numHint = allActions.map((_, i) => `${i + 1}`).join("/");
|
|
195
|
-
|
|
196
|
-
push(ui.bar());
|
|
196
|
+
const footer = ui.hints([`↑/↓ to choose`, `${numHint} to quick-select`, `enter to confirm`])[0] ?? "";
|
|
197
197
|
|
|
198
|
-
cachedLines = lines;
|
|
199
|
-
return
|
|
198
|
+
cachedLines = renderSharedDialogFrame(theme, "GSD Next Action", lines, width, { footer });
|
|
199
|
+
return cachedLines;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
return { render, invalidate: () => { cachedLines = undefined; }, handleInput };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { stripVTControlCharacters } from "node:util";
|
|
4
|
+
|
|
5
|
+
import { visibleWidth } from "@gsd/pi-tui";
|
|
6
|
+
|
|
7
|
+
import { showConfirm } from "../confirm-ui.js";
|
|
8
|
+
|
|
9
|
+
function assertFullOuterBorder(lines: string[], width: number): void {
|
|
10
|
+
assert.ok(lines.length >= 2, "dialog must include top and bottom borders");
|
|
11
|
+
for (const [index, line] of lines.entries()) {
|
|
12
|
+
assert.equal(visibleWidth(line), width, `line ${index} must fill dialog width`);
|
|
13
|
+
}
|
|
14
|
+
const top = stripVTControlCharacters(lines[0] ?? "");
|
|
15
|
+
const bottom = stripVTControlCharacters(lines.at(-1) ?? "");
|
|
16
|
+
assert.match(top, /^[╭┌].*[╮┐]$/);
|
|
17
|
+
assert.match(bottom, /^[╰└].*[╯┘]$/);
|
|
18
|
+
for (let index = 1; index < lines.length - 1; index++) {
|
|
19
|
+
const line = stripVTControlCharacters(lines[index] ?? "");
|
|
20
|
+
assert.match(line, /^[│┃├]/, `line ${index} missing left border: ${line}`);
|
|
21
|
+
assert.match(line, /[│┃┤]$/, `line ${index} missing right border: ${line}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe("showConfirm", () => {
|
|
26
|
+
it("renders the confirmation prompt inside a full border", async () => {
|
|
27
|
+
let rendered: string[] = [];
|
|
28
|
+
const theme = {
|
|
29
|
+
fg: (_color: string, text: string) => text,
|
|
30
|
+
bold: (text: string) => text,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const ctx = {
|
|
34
|
+
hasUI: true,
|
|
35
|
+
ui: {
|
|
36
|
+
custom: async (factory: any) => {
|
|
37
|
+
let resolved: boolean | undefined;
|
|
38
|
+
const component = factory({ requestRender() {} }, theme, null, (value: boolean) => {
|
|
39
|
+
resolved = value;
|
|
40
|
+
});
|
|
41
|
+
rendered = component.render(80);
|
|
42
|
+
component.handleInput("\r");
|
|
43
|
+
return resolved as never;
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const result = await showConfirm(ctx as any, {
|
|
49
|
+
title: "Confirm action",
|
|
50
|
+
message: "Proceed with the change?",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
assert.equal(result, true);
|
|
54
|
+
assertFullOuterBorder(rendered, 80);
|
|
55
|
+
assert.match(stripVTControlCharacters(rendered[0] ?? ""), /Confirm action/);
|
|
56
|
+
});
|
|
57
|
+
});
|