gsd-pi 2.70.0 → 2.70.1-dev.366a872
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/dist/loader.js +4 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +270 -23
- package/dist/resources/extensions/get-secrets-from-user.js +17 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +33 -19
- package/dist/resources/extensions/gsd/auto-prompts.js +7 -3
- package/dist/resources/extensions/gsd/auto-start.js +28 -12
- package/dist/resources/extensions/gsd/auto.js +12 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +22 -8
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +12 -0
- package/dist/resources/extensions/gsd/doctor-format.js +2 -0
- package/dist/resources/extensions/gsd/file-lock.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +33 -20
- package/dist/resources/extensions/gsd/init-wizard.js +3 -11
- package/dist/resources/extensions/gsd/pre-execution-checks.js +5 -3
- package/dist/resources/extensions/gsd/prompts/discuss.md +31 -13
- package/dist/resources/extensions/gsd/state.js +234 -332
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +34 -0
- package/dist/resources/extensions/gsd/validate-directory.js +30 -12
- package/dist/resources/extensions/gsd/workflow-events.js +25 -13
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +12 -1
- package/dist/resources/extensions/slash-commands/audit.js +2 -1
- package/dist/resources/extensions/subagent/isolation.js +4 -2
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +30 -27
- package/dist/update-cmd.js +3 -11
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +4 -0
- package/package.json +11 -11
- package/packages/mcp-server/dist/env-writer.d.ts +39 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
- package/packages/mcp-server/dist/env-writer.js +158 -0
- package/packages/mcp-server/dist/env-writer.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +11 -2
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +102 -2
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +2 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +35 -3
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/env-writer.test.ts +280 -0
- package/packages/mcp-server/src/env-writer.ts +183 -0
- package/packages/mcp-server/src/import-candidates.test.ts +48 -0
- package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
- package/packages/mcp-server/src/server.ts +137 -3
- package/packages/mcp-server/src/workflow-tools.ts +34 -1
- package/packages/pi-agent-core/dist/agent.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +3 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/src/agent.test.ts +82 -0
- package/packages/pi-agent-core/src/agent.ts +12 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +348 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.js +38 -15
- package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +10 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +158 -23
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +58 -2
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +418 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/lsp/config.ts +43 -17
- package/packages/pi-coding-agent/src/core/sdk.ts +8 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +189 -29
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +66 -2
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +7 -5
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
- package/packages/pi-tui/dist/components/input.d.ts +2 -0
- package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/input.js +7 -4
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
- package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/markdown.js +17 -1
- package/packages/pi-tui/dist/components/markdown.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
- package/packages/pi-tui/src/components/input.ts +7 -4
- package/packages/pi-tui/src/components/markdown.ts +22 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +384 -24
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +317 -0
- package/src/resources/extensions/get-secrets-from-user.ts +24 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +39 -25
- package/src/resources/extensions/gsd/auto-prompts.ts +7 -3
- package/src/resources/extensions/gsd/auto-start.ts +37 -14
- package/src/resources/extensions/gsd/auto.ts +12 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +22 -7
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +14 -0
- package/src/resources/extensions/gsd/doctor-format.ts +1 -0
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/file-lock.ts +59 -0
- package/src/resources/extensions/gsd/guided-flow.ts +36 -17
- package/src/resources/extensions/gsd/init-wizard.ts +3 -13
- package/src/resources/extensions/gsd/pre-execution-checks.ts +6 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +31 -13
- package/src/resources/extensions/gsd/state.ts +274 -344
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/validate-directory.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +87 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +180 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +60 -25
- package/src/resources/extensions/gsd/validate-directory.ts +33 -11
- package/src/resources/extensions/gsd/workflow-events.ts +34 -25
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +16 -1
- package/src/resources/extensions/slash-commands/audit.ts +2 -1
- package/src/resources/extensions/subagent/isolation.ts +4 -3
- package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → eMly3KqfZihJJAHQGmxvO}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → eMly3KqfZihJJAHQGmxvO}/_ssgManifest.js +0 -0
|
@@ -16,10 +16,12 @@ import type {
|
|
|
16
16
|
SimpleStreamOptions,
|
|
17
17
|
ToolCall,
|
|
18
18
|
} from "@gsd/pi-ai";
|
|
19
|
+
import type { ExtensionUIContext } from "@gsd/pi-coding-agent";
|
|
19
20
|
import { EventStream } from "@gsd/pi-ai";
|
|
20
21
|
import { execSync } from "node:child_process";
|
|
21
22
|
import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
|
|
22
23
|
import { buildWorkflowMcpServers } from "../gsd/workflow-mcp.js";
|
|
24
|
+
import { showInterviewRound, type Question, type RoundResult } from "../shared/tui.js";
|
|
23
25
|
import type {
|
|
24
26
|
SDKAssistantMessage,
|
|
25
27
|
SDKMessage,
|
|
@@ -45,6 +47,58 @@ type ToolCallWithExternalResult = ToolCall & {
|
|
|
45
47
|
externalResult?: ExternalToolResultPayload;
|
|
46
48
|
};
|
|
47
49
|
|
|
50
|
+
interface ClaudeCodeStreamOptions extends SimpleStreamOptions {
|
|
51
|
+
extensionUIContext?: ExtensionUIContext;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface SdkElicitationRequestOption {
|
|
55
|
+
const?: string;
|
|
56
|
+
title?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface SdkElicitationFieldSchema {
|
|
60
|
+
type?: string;
|
|
61
|
+
title?: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
format?: string;
|
|
64
|
+
writeOnly?: boolean;
|
|
65
|
+
oneOf?: SdkElicitationRequestOption[];
|
|
66
|
+
items?: {
|
|
67
|
+
anyOf?: SdkElicitationRequestOption[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface SdkElicitationRequest {
|
|
72
|
+
serverName: string;
|
|
73
|
+
message: string;
|
|
74
|
+
mode?: "form" | "url";
|
|
75
|
+
requestedSchema?: {
|
|
76
|
+
type?: string;
|
|
77
|
+
properties?: Record<string, SdkElicitationFieldSchema>;
|
|
78
|
+
required?: string[];
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface SdkElicitationResult {
|
|
83
|
+
action: "accept" | "decline" | "cancel";
|
|
84
|
+
content?: Record<string, string | string[]>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface ParsedElicitationQuestion extends Question {
|
|
88
|
+
noteFieldId?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface ParsedTextInputField {
|
|
92
|
+
id: string;
|
|
93
|
+
title: string;
|
|
94
|
+
description: string;
|
|
95
|
+
required: boolean;
|
|
96
|
+
secure: boolean;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const OTHER_OPTION_LABEL = "None of the above";
|
|
100
|
+
const SENSITIVE_FIELD_PATTERN = /(password|passphrase|secret|token|api[_\s-]*key|private[_\s-]*key|credential)/i;
|
|
101
|
+
|
|
48
102
|
// ---------------------------------------------------------------------------
|
|
49
103
|
// Stream factory
|
|
50
104
|
// ---------------------------------------------------------------------------
|
|
@@ -172,6 +226,286 @@ export function makeStreamExhaustedErrorMessage(model: string, lastTextContent:
|
|
|
172
226
|
return message;
|
|
173
227
|
}
|
|
174
228
|
|
|
229
|
+
function readElicitationChoices(options: SdkElicitationRequestOption[] | undefined): string[] {
|
|
230
|
+
if (!Array.isArray(options)) return [];
|
|
231
|
+
return options
|
|
232
|
+
.map((option) => (typeof option?.const === "string" ? option.const : typeof option?.title === "string" ? option.title : ""))
|
|
233
|
+
.filter((option): option is string => option.length > 0);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function parseAskUserQuestionsElicitation(
|
|
237
|
+
request: Pick<SdkElicitationRequest, "mode" | "requestedSchema">,
|
|
238
|
+
): ParsedElicitationQuestion[] | null {
|
|
239
|
+
if (request.mode && request.mode !== "form") return null;
|
|
240
|
+
const properties = request.requestedSchema?.properties;
|
|
241
|
+
if (!properties || typeof properties !== "object") return null;
|
|
242
|
+
|
|
243
|
+
const questions: ParsedElicitationQuestion[] = [];
|
|
244
|
+
|
|
245
|
+
for (const [fieldId, rawField] of Object.entries(properties)) {
|
|
246
|
+
if (fieldId.endsWith("__note")) continue;
|
|
247
|
+
if (!rawField || typeof rawField !== "object") return null;
|
|
248
|
+
|
|
249
|
+
const header = typeof rawField.title === "string" && rawField.title.length > 0 ? rawField.title : fieldId;
|
|
250
|
+
const question = typeof rawField.description === "string" ? rawField.description : "";
|
|
251
|
+
|
|
252
|
+
if (rawField.type === "array") {
|
|
253
|
+
const options = readElicitationChoices(rawField.items?.anyOf).map((label) => ({ label, description: "" }));
|
|
254
|
+
if (options.length === 0) return null;
|
|
255
|
+
questions.push({
|
|
256
|
+
id: fieldId,
|
|
257
|
+
header,
|
|
258
|
+
question,
|
|
259
|
+
options,
|
|
260
|
+
allowMultiple: true,
|
|
261
|
+
});
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (rawField.type === "string") {
|
|
266
|
+
const noteFieldId = Object.prototype.hasOwnProperty.call(properties, `${fieldId}__note`)
|
|
267
|
+
? `${fieldId}__note`
|
|
268
|
+
: undefined;
|
|
269
|
+
const options = readElicitationChoices(rawField.oneOf)
|
|
270
|
+
.filter((label) => label !== OTHER_OPTION_LABEL)
|
|
271
|
+
.map((label) => ({ label, description: "" }));
|
|
272
|
+
if (options.length === 0) return null;
|
|
273
|
+
questions.push({
|
|
274
|
+
id: fieldId,
|
|
275
|
+
header,
|
|
276
|
+
question,
|
|
277
|
+
options,
|
|
278
|
+
noteFieldId,
|
|
279
|
+
});
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return questions.length > 0 ? questions : null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function isSecureElicitationField(
|
|
290
|
+
requestMessage: string,
|
|
291
|
+
fieldId: string,
|
|
292
|
+
field: SdkElicitationFieldSchema,
|
|
293
|
+
): boolean {
|
|
294
|
+
if (field.format === "password") return true;
|
|
295
|
+
if (field.writeOnly === true) return true;
|
|
296
|
+
|
|
297
|
+
const rawField = field as Record<string, unknown>;
|
|
298
|
+
if (rawField.sensitive === true || rawField["x-sensitive"] === true) return true;
|
|
299
|
+
|
|
300
|
+
const haystack = [
|
|
301
|
+
requestMessage,
|
|
302
|
+
fieldId.replace(/[_-]+/g, " "),
|
|
303
|
+
typeof field.title === "string" ? field.title : "",
|
|
304
|
+
typeof field.description === "string" ? field.description : "",
|
|
305
|
+
]
|
|
306
|
+
.join(" ")
|
|
307
|
+
.toLowerCase();
|
|
308
|
+
|
|
309
|
+
return SENSITIVE_FIELD_PATTERN.test(haystack);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function parseTextInputElicitation(
|
|
313
|
+
request: Pick<SdkElicitationRequest, "message" | "mode" | "requestedSchema">,
|
|
314
|
+
): ParsedTextInputField[] | null {
|
|
315
|
+
if (request.mode && request.mode !== "form") return null;
|
|
316
|
+
const schema = request.requestedSchema as
|
|
317
|
+
| ({ properties?: Record<string, SdkElicitationFieldSchema>; keys?: Record<string, SdkElicitationFieldSchema> } & Record<string, unknown>)
|
|
318
|
+
| undefined;
|
|
319
|
+
const fieldsSource = schema?.properties && typeof schema.properties === "object"
|
|
320
|
+
? schema.properties
|
|
321
|
+
: schema?.keys && typeof schema.keys === "object"
|
|
322
|
+
? schema.keys
|
|
323
|
+
: undefined;
|
|
324
|
+
if (!fieldsSource) return null;
|
|
325
|
+
|
|
326
|
+
const requiredSet = new Set(
|
|
327
|
+
Array.isArray(request.requestedSchema?.required)
|
|
328
|
+
? request.requestedSchema.required.filter((value): value is string => typeof value === "string")
|
|
329
|
+
: [],
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
const fields: ParsedTextInputField[] = [];
|
|
333
|
+
for (const [fieldId, field] of Object.entries(fieldsSource)) {
|
|
334
|
+
if (!field || typeof field !== "object") continue;
|
|
335
|
+
if (field.type !== "string") continue;
|
|
336
|
+
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) continue;
|
|
337
|
+
|
|
338
|
+
fields.push({
|
|
339
|
+
id: fieldId,
|
|
340
|
+
title: typeof field.title === "string" && field.title.length > 0 ? field.title : fieldId,
|
|
341
|
+
description: typeof field.description === "string" ? field.description : "",
|
|
342
|
+
required: requiredSet.has(fieldId),
|
|
343
|
+
secure: isSecureElicitationField(request.message, fieldId, field),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return fields.length > 0 ? fields : null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function roundResultToElicitationContent(
|
|
351
|
+
questions: ParsedElicitationQuestion[],
|
|
352
|
+
result: RoundResult,
|
|
353
|
+
): Record<string, string | string[]> {
|
|
354
|
+
const content: Record<string, string | string[]> = {};
|
|
355
|
+
|
|
356
|
+
for (const question of questions) {
|
|
357
|
+
const answer = result.answers[question.id];
|
|
358
|
+
if (!answer) continue;
|
|
359
|
+
|
|
360
|
+
if (question.allowMultiple) {
|
|
361
|
+
const selected = Array.isArray(answer.selected) ? answer.selected : [answer.selected];
|
|
362
|
+
content[question.id] = selected;
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const selected = Array.isArray(answer.selected) ? answer.selected[0] ?? "" : answer.selected;
|
|
367
|
+
content[question.id] = selected;
|
|
368
|
+
if (question.noteFieldId && selected === OTHER_OPTION_LABEL && answer.notes.trim().length > 0) {
|
|
369
|
+
content[question.noteFieldId] = answer.notes.trim();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return content;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function buildElicitationPromptTitle(request: SdkElicitationRequest, question: ParsedElicitationQuestion): string {
|
|
377
|
+
const parts = [
|
|
378
|
+
request.serverName ? `[${request.serverName}]` : "",
|
|
379
|
+
question.header,
|
|
380
|
+
question.question,
|
|
381
|
+
].filter((part) => part && part.trim().length > 0);
|
|
382
|
+
return parts.join("\n\n");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function promptElicitationWithDialogs(
|
|
386
|
+
request: SdkElicitationRequest,
|
|
387
|
+
questions: ParsedElicitationQuestion[],
|
|
388
|
+
ui: ExtensionUIContext,
|
|
389
|
+
signal: AbortSignal,
|
|
390
|
+
): Promise<SdkElicitationResult> {
|
|
391
|
+
const content: Record<string, string | string[]> = {};
|
|
392
|
+
|
|
393
|
+
for (const question of questions) {
|
|
394
|
+
const title = buildElicitationPromptTitle(request, question);
|
|
395
|
+
|
|
396
|
+
if (question.allowMultiple) {
|
|
397
|
+
const selected = await ui.select(title, question.options.map((option) => option.label), {
|
|
398
|
+
allowMultiple: true,
|
|
399
|
+
signal,
|
|
400
|
+
});
|
|
401
|
+
if (Array.isArray(selected)) {
|
|
402
|
+
if (selected.length === 0) return { action: "cancel" };
|
|
403
|
+
content[question.id] = selected;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (typeof selected === "string" && selected.length > 0) {
|
|
407
|
+
content[question.id] = [selected];
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
return { action: "cancel" };
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const selected = await ui.select(title, [...question.options.map((option) => option.label), OTHER_OPTION_LABEL], { signal });
|
|
414
|
+
if (typeof selected !== "string" || selected.length === 0) {
|
|
415
|
+
return { action: "cancel" };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
content[question.id] = selected;
|
|
419
|
+
if (question.noteFieldId && selected === OTHER_OPTION_LABEL) {
|
|
420
|
+
const note = await ui.input(`${question.header} note`, "Explain your answer", { signal });
|
|
421
|
+
if (note === undefined) return { action: "cancel" };
|
|
422
|
+
if (note.trim().length > 0) {
|
|
423
|
+
content[question.noteFieldId] = note.trim();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return { action: "accept", content };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function buildTextInputPromptTitle(request: SdkElicitationRequest, field: ParsedTextInputField): string {
|
|
432
|
+
const parts = [
|
|
433
|
+
request.serverName ? `[${request.serverName}]` : "",
|
|
434
|
+
field.title,
|
|
435
|
+
field.description,
|
|
436
|
+
].filter((part) => typeof part === "string" && part.trim().length > 0);
|
|
437
|
+
return parts.join("\n\n");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function buildTextInputPlaceholder(field: ParsedTextInputField): string | undefined {
|
|
441
|
+
const desc = field.description.trim();
|
|
442
|
+
if (!desc) return field.required ? "Required" : "Leave empty to skip";
|
|
443
|
+
|
|
444
|
+
const formatLine = desc
|
|
445
|
+
.split(/\r?\n/)
|
|
446
|
+
.map((line) => line.trim())
|
|
447
|
+
.find((line) => /^format:/i.test(line));
|
|
448
|
+
|
|
449
|
+
if (!formatLine) return field.required ? "Required" : "Leave empty to skip";
|
|
450
|
+
const hint = formatLine.replace(/^format:\s*/i, "").trim();
|
|
451
|
+
return hint.length > 0 ? hint : field.required ? "Required" : "Leave empty to skip";
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
async function promptTextInputElicitation(
|
|
455
|
+
request: SdkElicitationRequest,
|
|
456
|
+
fields: ParsedTextInputField[],
|
|
457
|
+
ui: ExtensionUIContext,
|
|
458
|
+
signal: AbortSignal,
|
|
459
|
+
): Promise<SdkElicitationResult> {
|
|
460
|
+
const content: Record<string, string | string[]> = {};
|
|
461
|
+
|
|
462
|
+
for (const field of fields) {
|
|
463
|
+
const value = await ui.input(
|
|
464
|
+
buildTextInputPromptTitle(request, field),
|
|
465
|
+
buildTextInputPlaceholder(field),
|
|
466
|
+
{ signal, ...(field.secure ? { secure: true } : {}) },
|
|
467
|
+
);
|
|
468
|
+
if (value === undefined) {
|
|
469
|
+
return { action: "cancel" };
|
|
470
|
+
}
|
|
471
|
+
content[field.id] = value;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return { action: "accept", content };
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function createClaudeCodeElicitationHandler(
|
|
478
|
+
ui: ExtensionUIContext | undefined,
|
|
479
|
+
): ((request: SdkElicitationRequest, options: { signal: AbortSignal }) => Promise<SdkElicitationResult>) | undefined {
|
|
480
|
+
if (!ui) return undefined;
|
|
481
|
+
|
|
482
|
+
return async (request, { signal }) => {
|
|
483
|
+
if (request.mode === "url") {
|
|
484
|
+
return { action: "decline" };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const questions = parseAskUserQuestionsElicitation(request);
|
|
488
|
+
if (questions) {
|
|
489
|
+
const interviewResult = await showInterviewRound(questions, { signal }, { ui } as any).catch(() => undefined);
|
|
490
|
+
if (interviewResult && Object.keys(interviewResult.answers).length > 0) {
|
|
491
|
+
return {
|
|
492
|
+
action: "accept",
|
|
493
|
+
content: roundResultToElicitationContent(questions, interviewResult),
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return promptElicitationWithDialogs(request, questions, ui, signal);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const textFields = parseTextInputElicitation(request);
|
|
501
|
+
if (textFields) {
|
|
502
|
+
return promptTextInputElicitation(request, textFields, ui, signal);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return { action: "decline" };
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
175
509
|
// ---------------------------------------------------------------------------
|
|
176
510
|
// SDK options builder
|
|
177
511
|
// ---------------------------------------------------------------------------
|
|
@@ -182,8 +516,13 @@ export function makeStreamExhaustedErrorMessage(model: string, lastTextContent:
|
|
|
182
516
|
* Extracted for testability — callers can verify session persistence,
|
|
183
517
|
* beta flags, and other configuration without mocking the full SDK.
|
|
184
518
|
*/
|
|
185
|
-
export function buildSdkOptions(
|
|
519
|
+
export function buildSdkOptions(
|
|
520
|
+
modelId: string,
|
|
521
|
+
prompt: string,
|
|
522
|
+
extraOptions: Record<string, unknown> = {},
|
|
523
|
+
): Record<string, unknown> {
|
|
186
524
|
const mcpServers = buildWorkflowMcpServers();
|
|
525
|
+
const disallowedTools = ["AskUserQuestion"];
|
|
187
526
|
return {
|
|
188
527
|
pathToClaudeCodeExecutable: getClaudePath(),
|
|
189
528
|
model: modelId,
|
|
@@ -194,8 +533,10 @@ export function buildSdkOptions(modelId: string, prompt: string): Record<string,
|
|
|
194
533
|
allowDangerouslySkipPermissions: true,
|
|
195
534
|
settingSources: ["project"],
|
|
196
535
|
systemPrompt: { type: "preset", preset: "claude_code" },
|
|
536
|
+
disallowedTools,
|
|
197
537
|
...(mcpServers ? { mcpServers } : {}),
|
|
198
538
|
betas: modelId.includes("sonnet") ? ["context-1m-2025-08-07"] : [],
|
|
539
|
+
...extraOptions,
|
|
199
540
|
};
|
|
200
541
|
}
|
|
201
542
|
|
|
@@ -291,15 +632,15 @@ export function extractToolResultsFromSdkUserMessage(message: SDKUserMessage): A
|
|
|
291
632
|
return extracted;
|
|
292
633
|
}
|
|
293
634
|
|
|
294
|
-
function
|
|
295
|
-
|
|
635
|
+
function attachExternalResultsToToolBlocks(
|
|
636
|
+
toolBlocks: AssistantMessage["content"],
|
|
296
637
|
toolResultsById: ReadonlyMap<string, ExternalToolResultPayload>,
|
|
297
638
|
): void {
|
|
298
|
-
for (const block of
|
|
299
|
-
if (block.type !== "toolCall") continue;
|
|
639
|
+
for (const block of toolBlocks) {
|
|
640
|
+
if (block.type !== "toolCall" && block.type !== "serverToolUse") continue;
|
|
300
641
|
const externalResult = toolResultsById.get(block.id);
|
|
301
642
|
if (!externalResult) continue;
|
|
302
|
-
(block as ToolCallWithExternalResult).externalResult = externalResult;
|
|
643
|
+
(block as ToolCallWithExternalResult & { id: string }).externalResult = externalResult;
|
|
303
644
|
}
|
|
304
645
|
}
|
|
305
646
|
|
|
@@ -337,8 +678,8 @@ async function pumpSdkMessages(
|
|
|
337
678
|
/** Track the last text content seen across all assistant turns for the final message. */
|
|
338
679
|
let lastTextContent = "";
|
|
339
680
|
let lastThinkingContent = "";
|
|
340
|
-
/** Collect tool
|
|
341
|
-
const
|
|
681
|
+
/** Collect tool blocks from intermediate SDK turns for tool execution rendering. */
|
|
682
|
+
const intermediateToolBlocks: AssistantMessage["content"] = [];
|
|
342
683
|
/** Preserve real external tool results from Claude Code's synthetic user messages. */
|
|
343
684
|
const toolResultsById = new Map<string, ExternalToolResultPayload>();
|
|
344
685
|
|
|
@@ -359,7 +700,17 @@ async function pumpSdkMessages(
|
|
|
359
700
|
}
|
|
360
701
|
|
|
361
702
|
const prompt = buildPromptFromContext(context);
|
|
362
|
-
const sdkOpts = buildSdkOptions(
|
|
703
|
+
const sdkOpts = buildSdkOptions(
|
|
704
|
+
modelId,
|
|
705
|
+
prompt,
|
|
706
|
+
typeof (options as ClaudeCodeStreamOptions | undefined)?.extensionUIContext === "object"
|
|
707
|
+
? {
|
|
708
|
+
onElicitation: createClaudeCodeElicitationHandler(
|
|
709
|
+
(options as ClaudeCodeStreamOptions | undefined)?.extensionUIContext,
|
|
710
|
+
),
|
|
711
|
+
}
|
|
712
|
+
: {},
|
|
713
|
+
);
|
|
363
714
|
|
|
364
715
|
const queryResult = sdk.query({
|
|
365
716
|
prompt,
|
|
@@ -439,9 +790,9 @@ async function pumpSdkMessages(
|
|
|
439
790
|
lastTextContent = block.text;
|
|
440
791
|
} else if (block.type === "thinking" && block.thinking) {
|
|
441
792
|
lastThinkingContent = block.thinking;
|
|
442
|
-
} else if (block.type === "toolCall") {
|
|
443
|
-
// Collect tool
|
|
444
|
-
|
|
793
|
+
} else if (block.type === "toolCall" || block.type === "serverToolUse") {
|
|
794
|
+
// Collect tool blocks for externalToolExecution rendering
|
|
795
|
+
intermediateToolBlocks.push(block);
|
|
445
796
|
}
|
|
446
797
|
}
|
|
447
798
|
}
|
|
@@ -451,24 +802,33 @@ async function pumpSdkMessages(
|
|
|
451
802
|
for (const { toolUseId, result } of extractToolResultsFromSdkUserMessage(msg as SDKUserMessage)) {
|
|
452
803
|
toolResultsById.set(toolUseId, result);
|
|
453
804
|
}
|
|
454
|
-
|
|
805
|
+
attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
|
|
455
806
|
|
|
456
807
|
// Push a synthetic toolcall_end for each tool call from this turn
|
|
457
808
|
// so the TUI can render tool results in real-time during the SDK
|
|
458
809
|
// session instead of waiting until the entire session completes.
|
|
459
810
|
if (builder) {
|
|
460
811
|
for (const block of builder.message.content) {
|
|
461
|
-
if (block.type !== "toolCall") continue;
|
|
462
812
|
const extResult = (block as ToolCallWithExternalResult).externalResult;
|
|
463
813
|
if (!extResult) continue;
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
814
|
+
const contentIndex = builder.message.content.indexOf(block);
|
|
815
|
+
if (contentIndex < 0) continue;
|
|
816
|
+
// Push synthetic completion events with result attached so the
|
|
817
|
+
// chat-controller can update pending ToolExecutionComponents.
|
|
818
|
+
if (block.type === "toolCall") {
|
|
819
|
+
stream.push({
|
|
820
|
+
type: "toolcall_end",
|
|
821
|
+
contentIndex,
|
|
822
|
+
toolCall: block,
|
|
823
|
+
partial: builder.message,
|
|
824
|
+
});
|
|
825
|
+
} else if (block.type === "serverToolUse") {
|
|
826
|
+
stream.push({
|
|
827
|
+
type: "server_tool_use",
|
|
828
|
+
contentIndex,
|
|
829
|
+
partial: builder.message,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
472
832
|
}
|
|
473
833
|
}
|
|
474
834
|
|
|
@@ -486,8 +846,8 @@ async function pumpSdkMessages(
|
|
|
486
846
|
const finalContent: AssistantMessage["content"] = [];
|
|
487
847
|
|
|
488
848
|
// Add tool calls from intermediate turns first (renders above text)
|
|
489
|
-
|
|
490
|
-
finalContent.push(...
|
|
849
|
+
attachExternalResultsToToolBlocks(intermediateToolBlocks, toolResultsById);
|
|
850
|
+
finalContent.push(...intermediateToolBlocks);
|
|
491
851
|
|
|
492
852
|
// Add text/thinking from the last turn
|
|
493
853
|
if (builder && builder.message.content.length > 0) {
|