@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545
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/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/help-text.js +5 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
- package/dist/resources/extensions/gsd/auto/phases.js +28 -3
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -23
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
- package/dist/resources/extensions/gsd/auto.js +11 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/gsd-db.js +12 -0
- package/dist/resources/extensions/gsd/guided-flow.js +34 -468
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
- package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +147 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +52 -8
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/uat-policy.js +16 -10
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
- package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-cmd.js +20 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
- 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/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 +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.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/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/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/package.json +2 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- 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 +2 -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 +14 -0
- 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/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +8 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +8 -93
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +35 -120
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
- package/src/resources/extensions/gsd/auto/phases.ts +35 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
- package/src/resources/extensions/gsd/auto-start.ts +17 -20
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
- package/src/resources/extensions/gsd/auto.ts +15 -8
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/gsd-db.ts +12 -0
- package/src/resources/extensions/gsd/guided-flow.ts +47 -558
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
- package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +173 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
- package/src/resources/extensions/gsd/tool-contract.ts +86 -8
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/uat-policy.ts +19 -10
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
- package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
|
@@ -27,13 +27,29 @@ import { homedir } from "node:os";
|
|
|
27
27
|
import { createRequire } from "node:module";
|
|
28
28
|
import { dirname, join } from "node:path";
|
|
29
29
|
import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
|
|
30
|
+
import {
|
|
31
|
+
attachExternalResultsToToolBlocks,
|
|
32
|
+
buildFinalAssistantContent,
|
|
33
|
+
extractToolResultsFromSdkUserMessage,
|
|
34
|
+
handleClaudeCodePartialStreamEvent,
|
|
35
|
+
} from "./turn-assembler.js";
|
|
36
|
+
import type {
|
|
37
|
+
ExternalToolResultPayload,
|
|
38
|
+
ToolCallWithExternalResult,
|
|
39
|
+
} from "./turn-assembler.js";
|
|
30
40
|
import {
|
|
31
41
|
buildWorkflowMcpServers,
|
|
32
42
|
getRequiredWorkflowToolsForAutoUnit,
|
|
33
43
|
resolveWorkflowMcpProjectRoot,
|
|
34
44
|
} from "../gsd/workflow-mcp.js";
|
|
45
|
+
import { resolveWorkflowQuestionToolSurface } from "../gsd/question-transport.js";
|
|
35
46
|
import { buildProjectGsdMcpServers, ensureProjectWorkflowMcpConfig } from "../gsd/mcp-project-config.js";
|
|
36
47
|
import { loadProjectGSDPreferences } from "../gsd/preferences.js";
|
|
48
|
+
import { markToolStart, markToolEnd } from "../gsd/auto.js";
|
|
49
|
+
import {
|
|
50
|
+
markInteractiveElicitationStart,
|
|
51
|
+
markInteractiveElicitationEnd,
|
|
52
|
+
} from "../gsd/auto-tool-tracking.js";
|
|
37
53
|
import {
|
|
38
54
|
discoverBrowserMcpServerName,
|
|
39
55
|
discoverMcpServers,
|
|
@@ -45,7 +61,6 @@ import {
|
|
|
45
61
|
import { RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, resolveToolPresentationPlan } from "../gsd/tool-presentation-plan.js";
|
|
46
62
|
import { showInterviewRound, type Question, type RoundResult } from "../shared/tui.js";
|
|
47
63
|
import type {
|
|
48
|
-
BetaRawMessageStreamEvent,
|
|
49
64
|
SDKAssistantMessage,
|
|
50
65
|
SDKMessage,
|
|
51
66
|
SDKPartialAssistantMessage,
|
|
@@ -53,25 +68,17 @@ import type {
|
|
|
53
68
|
SDKUserMessage,
|
|
54
69
|
} from "./sdk-types.js";
|
|
55
70
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
details?: Record<string, unknown>;
|
|
68
|
-
isError: boolean;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** A `ToolCall` block augmented with the external result attached by the SDK synthetic user message. */
|
|
72
|
-
type ToolCallWithExternalResult = ToolCall & {
|
|
73
|
-
externalResult?: ExternalToolResultPayload;
|
|
74
|
-
};
|
|
71
|
+
export {
|
|
72
|
+
buildFinalAssistantContent,
|
|
73
|
+
extractToolResultsFromSdkUserMessage,
|
|
74
|
+
handleClaudeCodePartialStreamEvent,
|
|
75
|
+
mergePendingToolCalls,
|
|
76
|
+
} from "./turn-assembler.js";
|
|
77
|
+
export type {
|
|
78
|
+
ExternalToolResultContentBlock,
|
|
79
|
+
ExternalToolResultPayload,
|
|
80
|
+
ToolCallWithExternalResult,
|
|
81
|
+
} from "./turn-assembler.js";
|
|
75
82
|
|
|
76
83
|
interface PromptToolContextOptions {
|
|
77
84
|
workflowMcpServerName?: string | null;
|
|
@@ -1359,7 +1366,27 @@ export function createClaudeCodeCanUseToolHandler(
|
|
|
1359
1366
|
// Elicitation handler
|
|
1360
1367
|
// ---------------------------------------------------------------------------
|
|
1361
1368
|
|
|
1362
|
-
/**
|
|
1369
|
+
/**
|
|
1370
|
+
* Create an SDK elicitation handler that routes requests through the extension UI dialogs, or undefined if no UI is available.
|
|
1371
|
+
*
|
|
1372
|
+
* For structured (AskUserQuestion) elicitations, the interview round's result
|
|
1373
|
+
* disambiguates two cases that must not be conflated: an `undefined` result
|
|
1374
|
+
* means the custom UI is unavailable, so we fall back to the simpler `select`
|
|
1375
|
+
* dialogs; an empty-answers result means the user dismissed the question, which
|
|
1376
|
+
* is treated as a clean cancel. Falling back to dialogs on dismissal would
|
|
1377
|
+
* re-ask the same questions (the duplicate-question bug).
|
|
1378
|
+
*/
|
|
1379
|
+
/**
|
|
1380
|
+
* Monotonic counter so concurrent/sequential elicitations resolved within the
|
|
1381
|
+
* same millisecond get distinct synthetic in-flight-tool ids (the `cc-elicit-*`
|
|
1382
|
+
* namespace never collides with real MCP toolCallIds).
|
|
1383
|
+
*/
|
|
1384
|
+
let _elicitationSeq = 0;
|
|
1385
|
+
function nextElicitationSeq(): number {
|
|
1386
|
+
_elicitationSeq = (_elicitationSeq + 1) % Number.MAX_SAFE_INTEGER;
|
|
1387
|
+
return _elicitationSeq;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1363
1390
|
export function createClaudeCodeElicitationHandler(
|
|
1364
1391
|
ui: ExtensionUIContext | undefined,
|
|
1365
1392
|
): ((request: SdkElicitationRequest, options: { signal: AbortSignal }) => Promise<SdkElicitationResult>) | undefined {
|
|
@@ -1375,20 +1402,67 @@ export function createClaudeCodeElicitationHandler(
|
|
|
1375
1402
|
const headlessAnswer = answerElicitationFromHeadlessAnswers(questions, loadHeadlessAnswers());
|
|
1376
1403
|
if (headlessAnswer) return headlessAnswer;
|
|
1377
1404
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1405
|
+
// The SDK elicitation blocks waiting for human input, but it is not an
|
|
1406
|
+
// MCP tool dispatch, so markToolStart/markToolEnd are never called for
|
|
1407
|
+
// it. Without this the soft/context/idle/hard watchdogs see zero
|
|
1408
|
+
// in-flight tools and re-dispatch (and ultimately abort) the agent
|
|
1409
|
+
// turn hosting this elicitation, tearing the question down (#2676 /
|
|
1410
|
+
// claude-code-cli self-cancel loop). Bracketing the human wait with
|
|
1411
|
+
// the s.active-gated interactive-tool guard makes it visible to
|
|
1412
|
+
// hasInteractiveToolInFlight()/getInFlightToolCount() so those
|
|
1413
|
+
// watchdogs exempt it. No-op outside auto-mode (wrapper self-gates).
|
|
1414
|
+
//
|
|
1415
|
+
// markInteractiveElicitationStart/End is a SEPARATE, ungated signal that
|
|
1416
|
+
// is observable in FOREGROUND (where the s.active-gated markToolStart is a
|
|
1417
|
+
// no-op). The foreground approval-gate pause path (register-hooks
|
|
1418
|
+
// message_update) consults isInteractiveElicitationInFlight() and bails so
|
|
1419
|
+
// it does not tear down the very elicitation that IS the human boundary
|
|
1420
|
+
// (#cc-elicitation-self-cancel). It clears in the finally on every exit.
|
|
1421
|
+
const elicId = "cc-elicit-" + ((request as { id?: string | number }).id ?? `${Date.now()}-${nextElicitationSeq()}`);
|
|
1422
|
+
markInteractiveElicitationStart();
|
|
1423
|
+
markToolStart(elicId, "ask_user_questions");
|
|
1424
|
+
try {
|
|
1425
|
+
const interviewResult = await showInterviewRound(
|
|
1426
|
+
questions,
|
|
1427
|
+
{ signal, overlay: true },
|
|
1428
|
+
{ ui } as any,
|
|
1429
|
+
).catch(() => undefined);
|
|
1430
|
+
if (interviewResult === undefined) {
|
|
1431
|
+
// `await` so the dialog human-wait stays inside try/finally and the
|
|
1432
|
+
// in-flight guard is held until the dialog resolves. Without it,
|
|
1433
|
+
// `finally` runs the moment the promise is created and the fallback
|
|
1434
|
+
// wait runs with zero in-flight tools — reintroducing the
|
|
1435
|
+
// self-cancel on this path (Bugbot #1c00624d).
|
|
1436
|
+
return await promptElicitationWithDialogs(request, questions, ui, signal);
|
|
1437
|
+
}
|
|
1438
|
+
if (Object.keys(interviewResult.answers).length === 0) {
|
|
1439
|
+
// A system/host teardown (compaction, session_switch, true
|
|
1440
|
+
// interrupt) that aborted the signal mid-wait sets `interrupted`.
|
|
1441
|
+
// Surface that as a non-affirmative `decline` so it is not
|
|
1442
|
+
// laundered into a clean user-declined `cancel` the model re-asks
|
|
1443
|
+
// against. A genuine user dismissal leaves `interrupted` falsy and
|
|
1444
|
+
// keeps the prior `cancel` semantics.
|
|
1445
|
+
return interviewResult.interrupted ? { action: "decline" } : { action: "cancel" };
|
|
1446
|
+
}
|
|
1380
1447
|
return {
|
|
1381
1448
|
action: "accept",
|
|
1382
1449
|
content: roundResultToElicitationContent(questions, interviewResult),
|
|
1383
1450
|
};
|
|
1451
|
+
} finally {
|
|
1452
|
+
markToolEnd(elicId);
|
|
1453
|
+
markInteractiveElicitationEnd();
|
|
1384
1454
|
}
|
|
1385
|
-
|
|
1386
|
-
return promptElicitationWithDialogs(request, questions, ui, signal);
|
|
1387
1455
|
}
|
|
1388
1456
|
|
|
1389
1457
|
const textFields = parseTextInputElicitation(request);
|
|
1390
1458
|
if (textFields) {
|
|
1391
|
-
|
|
1459
|
+
const elicId = "cc-elicit-" + ((request as { id?: string | number }).id ?? `${Date.now()}-${nextElicitationSeq()}`);
|
|
1460
|
+
markToolStart(elicId, "secure_env_collect");
|
|
1461
|
+
try {
|
|
1462
|
+
return await promptTextInputElicitation(request, textFields, ui, signal);
|
|
1463
|
+
} finally {
|
|
1464
|
+
markToolEnd(elicId);
|
|
1465
|
+
}
|
|
1392
1466
|
}
|
|
1393
1467
|
|
|
1394
1468
|
return { action: "decline" };
|
|
@@ -1743,6 +1817,13 @@ export function buildSdkOptions(
|
|
|
1743
1817
|
workflowServerName,
|
|
1744
1818
|
workflowExplicitlyBlocked,
|
|
1745
1819
|
);
|
|
1820
|
+
const questionToolSurface = resolveWorkflowQuestionToolSurface({
|
|
1821
|
+
workflowServerName,
|
|
1822
|
+
workflowExplicitlyBlocked,
|
|
1823
|
+
workflowMcpTools,
|
|
1824
|
+
exactWorkflowMcpTools,
|
|
1825
|
+
env: process.env,
|
|
1826
|
+
});
|
|
1746
1827
|
const runUatDisallowedTools = gsdPhase === "run-uat" && workflowServerName
|
|
1747
1828
|
? [
|
|
1748
1829
|
...RUN_UAT_FORBIDDEN_TOOL_NAMES.filter((toolName) => !toolName.startsWith("mcp__")),
|
|
@@ -1756,6 +1837,7 @@ export function buildSdkOptions(
|
|
|
1756
1837
|
const disallowedTools: string[] = [...new Set([
|
|
1757
1838
|
"ToolSearch",
|
|
1758
1839
|
...(workflowMcpTools.length > 0 || exactWorkflowMcpTools.length > 0 ? ["AskUserQuestion"] : []),
|
|
1840
|
+
...questionToolSurface.disallowedTools,
|
|
1759
1841
|
...runUatDisallowedTools,
|
|
1760
1842
|
...extraDisallowedTools,
|
|
1761
1843
|
])];
|
|
@@ -1824,261 +1906,6 @@ export function buildSdkOptions(
|
|
|
1824
1906
|
};
|
|
1825
1907
|
}
|
|
1826
1908
|
|
|
1827
|
-
/** Normalise heterogeneous SDK tool-result content (string, array, or object) into a uniform `ExternalToolResultContentBlock[]`. */
|
|
1828
|
-
function normalizeToolResultContent(content: unknown): ExternalToolResultContentBlock[] {
|
|
1829
|
-
if (typeof content === "string") {
|
|
1830
|
-
return [{ type: "text", text: content }];
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
if (!Array.isArray(content)) {
|
|
1834
|
-
if (content == null) return [{ type: "text", text: "" }];
|
|
1835
|
-
return [{ type: "text", text: JSON.stringify(content) }];
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
const blocks: ExternalToolResultContentBlock[] = [];
|
|
1839
|
-
|
|
1840
|
-
for (const item of content) {
|
|
1841
|
-
if (typeof item === "string") {
|
|
1842
|
-
blocks.push({ type: "text", text: item });
|
|
1843
|
-
continue;
|
|
1844
|
-
}
|
|
1845
|
-
if (!item || typeof item !== "object") {
|
|
1846
|
-
blocks.push({ type: "text", text: String(item) });
|
|
1847
|
-
continue;
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
const block = item as Record<string, unknown>;
|
|
1851
|
-
if (block.type === "text") {
|
|
1852
|
-
blocks.push({ type: "text", text: typeof block.text === "string" ? block.text : "" });
|
|
1853
|
-
continue;
|
|
1854
|
-
}
|
|
1855
|
-
if (
|
|
1856
|
-
block.type === "image"
|
|
1857
|
-
&& typeof block.data === "string"
|
|
1858
|
-
&& typeof block.mimeType === "string"
|
|
1859
|
-
) {
|
|
1860
|
-
blocks.push({ type: "image", data: block.data, mimeType: block.mimeType });
|
|
1861
|
-
continue;
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
|
-
blocks.push({ type: "text", text: JSON.stringify(block) });
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
return blocks.length > 0 ? blocks : [{ type: "text", text: "" }];
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
/**
|
|
1871
|
-
* Extract a `details` payload from an MCP tool-result block.
|
|
1872
|
-
*
|
|
1873
|
-
* MCP's `CallToolResult` carries structured data in `structuredContent` — the
|
|
1874
|
-
* protocol's supported channel for non-text payloads. Claude Code's synthetic
|
|
1875
|
-
* user message may surface that field in one of two shapes depending on SDK
|
|
1876
|
-
* version: as a sibling on the `mcp_tool_result` block itself, or as a
|
|
1877
|
-
* dedicated content sub-block with `type: "structuredContent"`. Snake-case
|
|
1878
|
-
* (`structured_content`) is accepted defensively in case a transport hop
|
|
1879
|
-
* rewrites casing. All other shapes fall back to an empty object so callers
|
|
1880
|
-
* can rely on `details` being present.
|
|
1881
|
-
*/
|
|
1882
|
-
function extractStructuredDetailsFromBlock(block: Record<string, unknown>): Record<string, unknown> | undefined {
|
|
1883
|
-
const sibling = block.structuredContent ?? (block as Record<string, unknown>).structured_content;
|
|
1884
|
-
if (sibling && typeof sibling === "object" && !Array.isArray(sibling)) {
|
|
1885
|
-
return sibling as Record<string, unknown>;
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
if (Array.isArray(block.content)) {
|
|
1889
|
-
for (const item of block.content) {
|
|
1890
|
-
if (!item || typeof item !== "object") continue;
|
|
1891
|
-
const sub = item as Record<string, unknown>;
|
|
1892
|
-
if (sub.type !== "structuredContent" && sub.type !== "structured_content") continue;
|
|
1893
|
-
const payload = sub.structuredContent ?? sub.structured_content ?? sub.data ?? sub.value;
|
|
1894
|
-
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
1895
|
-
return payload as Record<string, unknown>;
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
// Return undefined (not {}) when no structured payload is present, matching
|
|
1901
|
-
// the pre-#4477 contract where `details` was nullable. An empty-object
|
|
1902
|
-
// sentinel is truthy and breaks downstream consumers that gate on
|
|
1903
|
-
// `if (details)`. `undefined` matches the type of the field these results
|
|
1904
|
-
// flow into (`Record<string, unknown> | undefined`).
|
|
1905
|
-
return undefined;
|
|
1906
|
-
}
|
|
1907
|
-
|
|
1908
|
-
/**
|
|
1909
|
-
* True for items that are MCP `structuredContent` pseudo-blocks living inside
|
|
1910
|
-
* a tool-result `content[]` array. These blocks carry the structured payload
|
|
1911
|
-
* (extracted separately by `extractStructuredDetailsFromBlock`) and must NOT
|
|
1912
|
-
* leak into the visible content rendered to the user — otherwise the renderer
|
|
1913
|
-
* stringifies the JSON pseudo-block and shows it next to the actual tool
|
|
1914
|
-
* output. See PR #4477 review (post-fix-round).
|
|
1915
|
-
*/
|
|
1916
|
-
function isStructuredContentPseudoBlock(item: unknown): boolean {
|
|
1917
|
-
if (!item || typeof item !== "object") return false;
|
|
1918
|
-
const type = (item as Record<string, unknown>).type;
|
|
1919
|
-
return type === "structuredContent" || type === "structured_content";
|
|
1920
|
-
}
|
|
1921
|
-
|
|
1922
|
-
/**
|
|
1923
|
-
* Strip `structuredContent` pseudo-blocks from a tool-result content array
|
|
1924
|
-
* before normalization. The structured payload is extracted via the sibling
|
|
1925
|
-
* `structuredContent` field (or a dedicated extractor pass on the raw block);
|
|
1926
|
-
* the visible content path must not include the pseudo-block itself.
|
|
1927
|
-
*/
|
|
1928
|
-
function stripStructuredContentPseudoBlocks(content: unknown): unknown {
|
|
1929
|
-
if (!Array.isArray(content)) return content;
|
|
1930
|
-
return content.filter((item) => !isStructuredContentPseudoBlock(item));
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
/** Extract tool result payloads from an SDK synthetic user message, keyed by tool-use ID. */
|
|
1934
|
-
export function extractToolResultsFromSdkUserMessage(message: SDKUserMessage): Array<{
|
|
1935
|
-
toolUseId: string;
|
|
1936
|
-
result: ExternalToolResultPayload;
|
|
1937
|
-
}> {
|
|
1938
|
-
const extracted: Array<{ toolUseId: string; result: ExternalToolResultPayload }> = [];
|
|
1939
|
-
const seen = new Set<string>();
|
|
1940
|
-
const rawMessage = message.message as Record<string, unknown> | null | undefined;
|
|
1941
|
-
const content = Array.isArray(rawMessage?.content) ? rawMessage.content : [];
|
|
1942
|
-
|
|
1943
|
-
for (const item of content) {
|
|
1944
|
-
if (!item || typeof item !== "object") continue;
|
|
1945
|
-
const block = item as Record<string, unknown>;
|
|
1946
|
-
const type = typeof block.type === "string" ? block.type : "";
|
|
1947
|
-
if (type !== "tool_result" && type !== "mcp_tool_result") continue;
|
|
1948
|
-
|
|
1949
|
-
const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : "";
|
|
1950
|
-
if (!toolUseId || seen.has(toolUseId)) continue;
|
|
1951
|
-
seen.add(toolUseId);
|
|
1952
|
-
|
|
1953
|
-
extracted.push({
|
|
1954
|
-
toolUseId,
|
|
1955
|
-
result: {
|
|
1956
|
-
content: normalizeToolResultContent(stripStructuredContentPseudoBlocks(block.content)),
|
|
1957
|
-
details: extractStructuredDetailsFromBlock(block),
|
|
1958
|
-
isError: block.is_error === true,
|
|
1959
|
-
},
|
|
1960
|
-
});
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
if (extracted.length === 0) {
|
|
1964
|
-
const fallback = message.tool_use_result;
|
|
1965
|
-
if (fallback && typeof fallback === "object") {
|
|
1966
|
-
const toolResult = fallback as Record<string, unknown>;
|
|
1967
|
-
const toolUseId = typeof toolResult.tool_use_id === "string" ? toolResult.tool_use_id : "";
|
|
1968
|
-
if (toolUseId) {
|
|
1969
|
-
extracted.push({
|
|
1970
|
-
toolUseId,
|
|
1971
|
-
result: {
|
|
1972
|
-
content: normalizeToolResultContent(stripStructuredContentPseudoBlocks(toolResult.content)),
|
|
1973
|
-
details: extractStructuredDetailsFromBlock(toolResult),
|
|
1974
|
-
isError: toolResult.is_error === true,
|
|
1975
|
-
},
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
return extracted;
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
/** Attach external tool results from the SDK synthetic user message to their corresponding tool-call blocks by ID. */
|
|
1985
|
-
function attachExternalResultsToToolBlocks(
|
|
1986
|
-
toolBlocks: AssistantMessage["content"],
|
|
1987
|
-
toolResultsById: ReadonlyMap<string, ExternalToolResultPayload>,
|
|
1988
|
-
): void {
|
|
1989
|
-
for (const block of toolBlocks) {
|
|
1990
|
-
if (block.type !== "toolCall" && block.type !== "serverToolUse") continue;
|
|
1991
|
-
const externalResult = toolResultsById.get(block.id);
|
|
1992
|
-
if (!externalResult) continue;
|
|
1993
|
-
(block as ToolCallWithExternalResult & { id: string }).externalResult = externalResult;
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
|
|
1997
|
-
/**
|
|
1998
|
-
* Build the final assistant content that Agent Core consumes in
|
|
1999
|
-
* `externalToolExecution` mode. This preserves tool-call blocks, attaches any
|
|
2000
|
-
* SDK-produced external results by tool-call id, and then appends the final
|
|
2001
|
-
* text/thinking blocks for the completed turn.
|
|
2002
|
-
*/
|
|
2003
|
-
export function buildFinalAssistantContent(params: {
|
|
2004
|
-
intermediateToolBlocks: AssistantMessage["content"];
|
|
2005
|
-
pendingContent?: AssistantMessage["content"];
|
|
2006
|
-
toolResultsById: ReadonlyMap<string, ExternalToolResultPayload>;
|
|
2007
|
-
lastThinkingContent?: string;
|
|
2008
|
-
lastTextContent?: string;
|
|
2009
|
-
fallbackResultText?: string;
|
|
2010
|
-
}): AssistantMessage["content"] {
|
|
2011
|
-
const mergedToolBlocks = [...params.intermediateToolBlocks];
|
|
2012
|
-
if (params.pendingContent) {
|
|
2013
|
-
mergePendingToolCalls(mergedToolBlocks, params.pendingContent);
|
|
2014
|
-
}
|
|
2015
|
-
attachExternalResultsToToolBlocks(mergedToolBlocks, params.toolResultsById);
|
|
2016
|
-
|
|
2017
|
-
const finalContent: AssistantMessage["content"] = [...mergedToolBlocks];
|
|
2018
|
-
if (params.pendingContent && params.pendingContent.length > 0) {
|
|
2019
|
-
for (const block of params.pendingContent) {
|
|
2020
|
-
if (block.type === "text" || block.type === "thinking") {
|
|
2021
|
-
finalContent.push(block);
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
} else {
|
|
2025
|
-
if (params.lastThinkingContent) {
|
|
2026
|
-
finalContent.push({ type: "thinking", thinking: params.lastThinkingContent });
|
|
2027
|
-
}
|
|
2028
|
-
if (params.lastTextContent) {
|
|
2029
|
-
finalContent.push({ type: "text", text: params.lastTextContent });
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
if (finalContent.length === 0 && params.fallbackResultText) {
|
|
2034
|
-
finalContent.push({ type: "text", text: params.fallbackResultText });
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
|
-
return finalContent;
|
|
2038
|
-
}
|
|
2039
|
-
|
|
2040
|
-
/**
|
|
2041
|
-
* Merge tool-call blocks from the active partial-message builder into the
|
|
2042
|
-
* running list of intermediate tool calls, preserving order and de-duping
|
|
2043
|
-
* by tool-call id. Exposed for testing the F3 fix (final-turn tool calls
|
|
2044
|
-
* dropped when `result` arrives without a preceding synthetic `user`).
|
|
2045
|
-
*/
|
|
2046
|
-
export function mergePendingToolCalls(
|
|
2047
|
-
intermediate: AssistantMessage["content"],
|
|
2048
|
-
pending: AssistantMessage["content"],
|
|
2049
|
-
): AssistantMessage["content"] {
|
|
2050
|
-
const alreadyIncluded = new Set<string>();
|
|
2051
|
-
for (const block of intermediate) {
|
|
2052
|
-
if (block.type === "toolCall") alreadyIncluded.add(block.id);
|
|
2053
|
-
}
|
|
2054
|
-
for (const block of pending) {
|
|
2055
|
-
if (block.type !== "toolCall") continue;
|
|
2056
|
-
if (alreadyIncluded.has(block.id)) continue;
|
|
2057
|
-
alreadyIncluded.add(block.id);
|
|
2058
|
-
intermediate.push(block);
|
|
2059
|
-
}
|
|
2060
|
-
return intermediate;
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
export function handleClaudeCodePartialStreamEvent(
|
|
2064
|
-
builder: PartialMessageBuilder | null,
|
|
2065
|
-
event: BetaRawMessageStreamEvent,
|
|
2066
|
-
modelId: string,
|
|
2067
|
-
): { builder: PartialMessageBuilder | null; assistantEvent: AssistantMessageEvent | null } {
|
|
2068
|
-
if (event.type === "message_start") {
|
|
2069
|
-
// Claude Code can emit repeated SDK message_start events inside one
|
|
2070
|
-
// logical assistant response. Keep appending until a synthetic user
|
|
2071
|
-
// tool-result boundary explicitly clears the builder.
|
|
2072
|
-
return {
|
|
2073
|
-
builder: builder ?? new PartialMessageBuilder((event as any).message?.model ?? modelId),
|
|
2074
|
-
assistantEvent: null,
|
|
2075
|
-
};
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
if (!builder) return { builder, assistantEvent: null };
|
|
2079
|
-
return { builder, assistantEvent: builder.handleEvent(event) };
|
|
2080
|
-
}
|
|
2081
|
-
|
|
2082
1909
|
// ---------------------------------------------------------------------------
|
|
2083
1910
|
// streamSimple implementation
|
|
2084
1911
|
// ---------------------------------------------------------------------------
|