@stigmer/runner 3.15.0 → 3.15.2-dev.20260913223433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
- package/dist/__test-utils__/execution-record-fixture.js +4 -0
- package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
- package/dist/__test-utils__/file-review-projection.d.ts +40 -0
- package/dist/__test-utils__/file-review-projection.js +136 -0
- package/dist/__test-utils__/file-review-projection.js.map +1 -0
- package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
- package/dist/__test-utils__/harness-contract/types.js +15 -0
- package/dist/__test-utils__/harness-contract/types.js.map +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
- package/dist/__test-utils__/hermetic-activity.js +52 -14
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
- package/dist/__test-utils__/model-registry-fixture.js +31 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
- package/dist/__test-utils__/turn-input-fixture.js +1 -1
- package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
- package/dist/activities/call-agent.js +2 -2
- package/dist/activities/call-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +7 -5
- package/dist/activities/execute-cursor/adapter.js +7 -5
- package/dist/activities/execute-cursor/adapter.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
- package/dist/activities/execute-cursor/approval-policy.js +5 -2
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
- package/dist/activities/execute-cursor/approval-state.js +6 -3
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
- package/dist/activities/execute-cursor/cas-observations.js +19 -2
- package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
- package/dist/activities/execute-cursor/message-translator.js +19 -32
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
- package/dist/activities/execute-cursor/prompt-builder.js +76 -95
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
- package/dist/activities/execute-cursor/turn-boundary.js +30 -90
- package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
- package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
- package/dist/activities/execute-cursor/turn-settle.js +37 -49
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
- package/dist/activities/execute-cursor/turn-setup.js +29 -59
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
- package/dist/activities/execute-cursor/turn-stream.js +9 -22
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.js +5 -1
- package/dist/activities/execute-cursor/turn.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
- package/dist/activities/execute-deep-agent/adapter.js +78 -0
- package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
- package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
- package/dist/activities/execute-deep-agent/execution-state.js +4 -12
- package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
- package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
- package/dist/activities/execute-deep-agent/hitl.js +77 -103
- package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
- package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
- package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
- package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
- package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
- package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
- package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
- package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn.js +116 -0
- package/dist/activities/execute-deep-agent/turn.js.map +1 -0
- package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
- package/dist/activities/execute-deep-agent/v3-events.js +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
- package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/harness/approval-decisions.d.ts +61 -0
- package/dist/harness/approval-decisions.js +102 -0
- package/dist/harness/approval-decisions.js.map +1 -0
- package/dist/harness/capabilities.d.ts +16 -5
- package/dist/harness/capabilities.js +9 -0
- package/dist/harness/capabilities.js.map +1 -1
- package/dist/harness/capture.d.ts +144 -0
- package/dist/harness/capture.js +219 -0
- package/dist/harness/capture.js.map +1 -0
- package/dist/harness/persist-chokepoint.d.ts +19 -4
- package/dist/harness/persist-chokepoint.js +17 -4
- package/dist/harness/persist-chokepoint.js.map +1 -1
- package/dist/harness/run-turn.js +115 -29
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/terminal-table.d.ts +40 -11
- package/dist/harness/terminal-table.js +58 -19
- package/dist/harness/terminal-table.js.map +1 -1
- package/dist/harness/turn-context.d.ts +141 -76
- package/dist/harness/turn-context.js +194 -99
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +65 -12
- package/dist/harness/types.js +8 -2
- package/dist/harness/types.js.map +1 -1
- package/dist/harness-adapters.d.ts +12 -8
- package/dist/harness-adapters.js +17 -9
- package/dist/harness-adapters.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +1 -1
- package/dist/middleware/approval-gate.js +1 -1
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +39 -0
- package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
- package/dist/middleware/cost-advisory.js.map +1 -0
- package/dist/middleware/index.d.ts +23 -12
- package/dist/middleware/index.js +26 -18
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -2
- package/dist/runner-manager.js +1 -5
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +1 -5
- package/dist/runner.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +41 -18
- package/dist/shared/attachment-resolver.js +178 -46
- package/dist/shared/attachment-resolver.js.map +1 -1
- package/dist/shared/attachment-zip.d.ts +85 -0
- package/dist/shared/attachment-zip.js +185 -0
- package/dist/shared/attachment-zip.js.map +1 -0
- package/dist/shared/connect-backfill.js +5 -4
- package/dist/shared/connect-backfill.js.map +1 -1
- package/dist/shared/cost-guard.d.ts +3 -3
- package/dist/shared/cost-guard.js +3 -3
- package/dist/shared/execution-status-writer.d.ts +5 -5
- package/dist/shared/execution-status-writer.js +5 -5
- package/dist/shared/extract-structured-output.d.ts +8 -7
- package/dist/shared/extract-structured-output.js +8 -7
- package/dist/shared/extract-structured-output.js.map +1 -1
- package/dist/shared/filereview/cas-progress.d.ts +1 -18
- package/dist/shared/filereview/cas-progress.js +4 -0
- package/dist/shared/filereview/cas-progress.js.map +1 -1
- package/dist/shared/filereview/cas-touched.d.ts +56 -0
- package/dist/shared/filereview/cas-touched.js +63 -0
- package/dist/shared/filereview/cas-touched.js.map +1 -0
- package/dist/shared/filereview/index.d.ts +2 -1
- package/dist/shared/filereview/index.js +2 -1
- package/dist/shared/filereview/index.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +4 -5
- package/dist/shared/mcp-resolver.js +4 -5
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +3 -4
- package/dist/shared/persist-decision.js +3 -4
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +2 -2
- package/dist/shared/plan-mode-permissions.js +2 -2
- package/dist/shared/plan-mode-prompt.d.ts +1 -1
- package/dist/shared/plan-mode-prompt.js +1 -1
- package/dist/shared/prompt-sections.d.ts +163 -0
- package/dist/shared/prompt-sections.js +164 -0
- package/dist/shared/prompt-sections.js.map +1 -0
- package/dist/shared/skill-resolver.d.ts +4 -2
- package/dist/shared/skill-resolver.js +4 -2
- package/dist/shared/skill-resolver.js.map +1 -1
- package/dist/shared/tool-rounds.d.ts +32 -0
- package/dist/shared/tool-rounds.js +43 -0
- package/dist/shared/tool-rounds.js.map +1 -1
- package/dist/shared/tool-row.d.ts +34 -0
- package/dist/shared/tool-row.js +52 -0
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/workspace/session-provision.d.ts +3 -3
- package/dist/shared/workspace/session-provision.js +3 -3
- package/dist/shared/workspace/stigmer-link.d.ts +3 -3
- package/dist/shared/workspace/stigmer-link.js +3 -3
- package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
- package/dist/shared/workspace/writeback-coordinator.js +16 -53
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/package.json +4 -4
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
- package/src/__test-utils__/execution-record-fixture.ts +18 -2
- package/src/__test-utils__/file-review-projection.ts +156 -0
- package/src/__test-utils__/git-workspace-fixture.ts +58 -0
- package/src/__test-utils__/harness-boot-order-child.ts +7 -2
- package/src/__test-utils__/harness-contract/contract.ts +33 -20
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
- package/src/__test-utils__/harness-contract/types.ts +27 -3
- package/src/__test-utils__/hermetic-activity.ts +52 -14
- package/src/__test-utils__/model-registry-fixture.ts +32 -7
- package/src/__test-utils__/module-specifiers.ts +24 -0
- package/src/__test-utils__/turn-input-fixture.ts +2 -2
- package/src/__tests__/harness-boot-order.test.ts +9 -2
- package/src/activities/call-agent.ts +2 -2
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
- package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
- package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
- package/src/activities/execute-cursor/adapter.ts +7 -5
- package/src/activities/execute-cursor/approval-policy.ts +5 -2
- package/src/activities/execute-cursor/approval-state.ts +16 -8
- package/src/activities/execute-cursor/cas-observations.ts +20 -2
- package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
- package/src/activities/execute-cursor/message-translator.ts +29 -41
- package/src/activities/execute-cursor/prompt-builder.ts +99 -157
- package/src/activities/execute-cursor/turn-boundary.ts +34 -140
- package/src/activities/execute-cursor/turn-settle.ts +37 -51
- package/src/activities/execute-cursor/turn-setup.ts +30 -70
- package/src/activities/execute-cursor/turn-stream.ts +8 -31
- package/src/activities/execute-cursor/turn.ts +5 -1
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
- package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
- package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
- package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
- package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
- package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
- package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
- package/src/activities/execute-deep-agent/adapter.ts +94 -0
- package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
- package/src/activities/execute-deep-agent/execution-state.ts +4 -13
- package/src/activities/execute-deep-agent/hitl.ts +100 -123
- package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
- package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
- package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
- package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
- package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
- package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
- package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
- package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
- package/src/activities/execute-deep-agent/turn.ts +131 -0
- package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
- package/src/activities/execute-deep-agent/v3-events.ts +1 -1
- package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
- package/src/harness/__tests__/approval-decisions.test.ts +116 -0
- package/src/harness/__tests__/capture.test.ts +268 -0
- package/src/harness/__tests__/mount-skills.test.ts +169 -0
- package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
- package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
- package/src/harness/__tests__/run-turn.test.ts +39 -23
- package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
- package/src/harness/__tests__/turn-context.test.ts +73 -26
- package/src/harness/approval-decisions.ts +104 -0
- package/src/harness/capabilities.ts +16 -5
- package/src/harness/capture.ts +301 -0
- package/src/harness/persist-chokepoint.ts +24 -4
- package/src/harness/run-turn.ts +120 -29
- package/src/harness/terminal-table.ts +61 -20
- package/src/harness/turn-context.ts +208 -111
- package/src/harness/types.ts +66 -12
- package/src/harness-adapters.ts +17 -9
- package/src/middleware/__tests__/approval-gate.test.ts +1 -1
- package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
- package/src/middleware/approval-gate.ts +2 -2
- package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
- package/src/middleware/index.ts +29 -29
- package/src/middleware/types.ts +3 -2
- package/src/runner-manager.ts +0 -8
- package/src/runner.ts +0 -8
- package/src/shared/__tests__/attachment-naming.test.ts +6 -19
- package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
- package/src/shared/__tests__/attachment-zip.test.ts +236 -0
- package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
- package/src/shared/__tests__/cost-guard.test.ts +3 -3
- package/src/shared/__tests__/prompt-sections.test.ts +167 -0
- package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
- package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
- package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
- package/src/shared/attachment-resolver.ts +218 -55
- package/src/shared/attachment-zip.ts +281 -0
- package/src/shared/connect-backfill.ts +9 -11
- package/src/shared/cost-guard.ts +3 -3
- package/src/shared/execution-status-writer.ts +5 -5
- package/src/shared/extract-structured-output.ts +8 -7
- package/src/shared/filereview/__tests__/capture.test.ts +86 -4
- package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
- package/src/shared/filereview/cas-progress.ts +5 -19
- package/src/shared/filereview/cas-touched.ts +89 -0
- package/src/shared/filereview/index.ts +4 -2
- package/src/shared/mcp-resolver.ts +4 -5
- package/src/shared/persist-decision.ts +3 -4
- package/src/shared/plan-mode-permissions.ts +2 -2
- package/src/shared/plan-mode-prompt.ts +1 -1
- package/src/shared/prompt-sections.ts +256 -0
- package/src/shared/skill-resolver.ts +4 -2
- package/src/shared/tool-rounds.ts +48 -0
- package/src/shared/tool-row.ts +61 -0
- package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
- package/src/shared/workspace/session-provision.ts +3 -3
- package/src/shared/workspace/stigmer-link.ts +3 -3
- package/src/shared/workspace/writeback-coordinator.ts +16 -64
- package/src/tools/index.ts +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
- package/dist/activities/execute-cursor/capture-flow.js +0 -285
- package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
- package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
- package/dist/activities/execute-cursor/command-provenance.js +0 -38
- package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
- package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
- package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
- package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
- package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
- package/dist/activities/execute-deep-agent/environment.js +0 -58
- package/dist/activities/execute-deep-agent/environment.js.map +0 -1
- package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
- package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
- package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
- package/dist/activities/execute-deep-agent/index.d.ts +0 -15
- package/dist/activities/execute-deep-agent/index.js +0 -918
- package/dist/activities/execute-deep-agent/index.js.map +0 -1
- package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
- package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
- package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
- package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
- package/dist/activities/execute-deep-agent/post-stream.js +0 -71
- package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
- package/dist/activities/execute-deep-agent/setup.js +0 -767
- package/dist/activities/execute-deep-agent/setup.js.map +0 -1
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
- package/dist/activities/execute-deep-agent/status-builder.js +0 -365
- package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
- package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
- package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
- package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
- package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
- package/dist/activities/execute-deep-agent/streaming.js +0 -160
- package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
- package/dist/middleware/cost-cap.d.ts +0 -22
- package/dist/middleware/cost-cap.js.map +0 -1
- package/dist/middleware/graceful-stop.d.ts +0 -17
- package/dist/middleware/graceful-stop.js +0 -63
- package/dist/middleware/graceful-stop.js.map +0 -1
- package/dist/shared/skill-writer.d.ts +0 -75
- package/dist/shared/skill-writer.js +0 -207
- package/dist/shared/skill-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
- package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
- package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
- package/src/activities/execute-cursor/capture-flow.ts +0 -379
- package/src/activities/execute-cursor/command-provenance.ts +0 -73
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
- package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
- package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
- package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
- package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
- package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
- package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
- package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
- package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
- package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
- package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
- package/src/activities/execute-deep-agent/environment.ts +0 -76
- package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
- package/src/activities/execute-deep-agent/index.ts +0 -1072
- package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
- package/src/activities/execute-deep-agent/post-stream.ts +0 -109
- package/src/activities/execute-deep-agent/setup.ts +0 -1081
- package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
- package/src/activities/execute-deep-agent/status-builder.ts +0 -481
- package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
- package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
- package/src/activities/execute-deep-agent/streaming.ts +0 -313
- package/src/middleware/__tests__/cost-cap.test.ts +0 -192
- package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
- package/src/middleware/graceful-stop.ts +0 -86
- package/src/shared/__tests__/skill-writer.test.ts +0 -372
- package/src/shared/skill-writer.ts +0 -266
|
@@ -10,8 +10,26 @@
|
|
|
10
10
|
* their first segment (e.g. "tools:<pregelUuid>|model_request:<innerUuid>")
|
|
11
11
|
* - First segment match (before "|") correlates child events to sub-agent
|
|
12
12
|
*
|
|
13
|
-
* The tracker
|
|
14
|
-
*
|
|
13
|
+
* The tracker builds INTO the status's own `subAgentExecutions` array, by
|
|
14
|
+
* reference: it pushes new rows and mutates existing ones, never replaces the
|
|
15
|
+
* array, so the caller that seeded the array from the persisted transcript
|
|
16
|
+
* (the turn runtime's `seedFromPersistedStatus`) keeps every prior turn's
|
|
17
|
+
* row and every wrapper of the status sees the same rows. Seeded rows are
|
|
18
|
+
* indexed by id on construction; a re-emitted `task` tool start for a known
|
|
19
|
+
* id binds its routing prefix to the existing row instead of pushing a twin
|
|
20
|
+
* (the memory-checkpointer replay re-drives the whole graph), exactly as the
|
|
21
|
+
* parent builder reconciles re-emitted tool calls through its rebuilt index.
|
|
22
|
+
* Until S3 M2a the tracker owned a private array that `syncSubAgentExecutions`
|
|
23
|
+
* assigned onto the status wholesale, which a resumed turn's first delegation
|
|
24
|
+
* would have used to drop turn 1's rows (S3 M1 deferred debt).
|
|
25
|
+
*
|
|
26
|
+
* V3StatusBuilder delegates sub-agent-scoped events here instead of the
|
|
27
|
+
* parent message list. Marking rows CANCELLED when a turn stops is NOT the
|
|
28
|
+
* tracker's: `shared/subagent-rows.ts` `cancelInProgressSubAgentProtos` is
|
|
29
|
+
* the one home of that transition for every harness (the runtime's thrown
|
|
30
|
+
* arms and both adapters' stops call it); the tracker only clears the
|
|
31
|
+
* streaming flags those rows' messages still carry
|
|
32
|
+
* ({@link SubAgentTracker.finalizeAllStreaming}).
|
|
15
33
|
*/
|
|
16
34
|
|
|
17
35
|
import { create, type JsonObject } from "@bufbuild/protobuf";
|
|
@@ -30,7 +48,7 @@ import {
|
|
|
30
48
|
import { utcTimestamp } from "../../shared/status.js";
|
|
31
49
|
import { classifyTool } from "../../shared/tool-kind.js";
|
|
32
50
|
import { extractToolResultV3 } from "./status-builder-shared.js";
|
|
33
|
-
import type { StigmerRunEvent
|
|
51
|
+
import type { StigmerRunEvent } from "./v3-events.js";
|
|
34
52
|
|
|
35
53
|
// ── Per-SubAgent State ───────────────────────────────────────────────────────
|
|
36
54
|
|
|
@@ -51,16 +69,50 @@ interface SubAgentState {
|
|
|
51
69
|
toolArgBuffers: Map<string, string>;
|
|
52
70
|
}
|
|
53
71
|
|
|
72
|
+
/** Fresh routing state over a row; `namespacePrefix` is `""` for a seeded row until its `task` start re-announces it. */
|
|
73
|
+
function newSubAgentState(proto: SubAgentExecution, callId: string, namespacePrefix: string): SubAgentState {
|
|
74
|
+
return {
|
|
75
|
+
proto,
|
|
76
|
+
callId,
|
|
77
|
+
namespacePrefix,
|
|
78
|
+
messagesByRun: new Map(),
|
|
79
|
+
currentAiMessage: new Map(),
|
|
80
|
+
lastLlmRunId: new Map(),
|
|
81
|
+
toolCalls: new Map(),
|
|
82
|
+
toolArgBuffers: new Map(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
54
86
|
// ── SubAgentTracker ──────────────────────────────────────────────────────────
|
|
55
87
|
|
|
56
88
|
export class SubAgentTracker {
|
|
57
|
-
private readonly executions: SubAgentExecution[] = [];
|
|
58
89
|
private readonly stateByCallId = new Map<string, SubAgentState>();
|
|
59
90
|
private readonly stateByPrefix = new Map<string, SubAgentState>();
|
|
60
91
|
|
|
92
|
+
/**
|
|
93
|
+
* @param executions - The status's own `subAgentExecutions` array, built
|
|
94
|
+
* into by reference. Rows already on it (the runtime's seed on a
|
|
95
|
+
* reinvocation) are indexed by id, with their tool calls, so a re-driven
|
|
96
|
+
* event reconciles onto them; their routing prefix is unknown until a
|
|
97
|
+
* `task` tool start re-announces it.
|
|
98
|
+
*/
|
|
99
|
+
constructor(private readonly executions: SubAgentExecution[]) {
|
|
100
|
+
for (const proto of executions) {
|
|
101
|
+
const state = newSubAgentState(proto, proto.id, "");
|
|
102
|
+
for (const message of proto.messages) {
|
|
103
|
+
for (const tc of message.toolCalls) {
|
|
104
|
+
if (tc.id) state.toolCalls.set(tc.id, tc);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.stateByCallId.set(proto.id, state);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
61
111
|
/**
|
|
62
112
|
* Called when a "task" tool_started event is observed at depth 0 or 1.
|
|
63
|
-
* Creates a new SubAgentExecution and begins tracking
|
|
113
|
+
* Creates a new SubAgentExecution and begins tracking — or, for a seeded
|
|
114
|
+
* row re-announced by a replayed graph, binds the routing prefix to the
|
|
115
|
+
* row that already exists.
|
|
64
116
|
*
|
|
65
117
|
* @param callId - Provider tool call ID (e.g. "toolu_01HW...")
|
|
66
118
|
* @param args - Tool input arguments (subagent_type, description)
|
|
@@ -70,7 +122,15 @@ export class SubAgentTracker {
|
|
|
70
122
|
* caller provides a synthetic prefix like "tools:<callId>".
|
|
71
123
|
*/
|
|
72
124
|
onTaskToolStarted(callId: string, args: Record<string, unknown>, routingPrefix: string): void {
|
|
73
|
-
|
|
125
|
+
const existing = this.stateByCallId.get(callId);
|
|
126
|
+
if (existing) {
|
|
127
|
+
if (existing.namespacePrefix === "") {
|
|
128
|
+
const bound = { ...existing, namespacePrefix: routingPrefix };
|
|
129
|
+
this.stateByCallId.set(callId, bound);
|
|
130
|
+
this.stateByPrefix.set(routingPrefix, bound);
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
74
134
|
|
|
75
135
|
const name = safeString(args, "subagent_type") || "task";
|
|
76
136
|
const description = safeString(args, "description") || "";
|
|
@@ -84,16 +144,7 @@ export class SubAgentTracker {
|
|
|
84
144
|
startedAt: utcTimestamp(),
|
|
85
145
|
});
|
|
86
146
|
|
|
87
|
-
const state
|
|
88
|
-
proto,
|
|
89
|
-
callId,
|
|
90
|
-
namespacePrefix: routingPrefix,
|
|
91
|
-
messagesByRun: new Map(),
|
|
92
|
-
currentAiMessage: new Map(),
|
|
93
|
-
lastLlmRunId: new Map(),
|
|
94
|
-
toolCalls: new Map(),
|
|
95
|
-
toolArgBuffers: new Map(),
|
|
96
|
-
};
|
|
147
|
+
const state = newSubAgentState(proto, callId, routingPrefix);
|
|
97
148
|
|
|
98
149
|
this.executions.push(proto);
|
|
99
150
|
this.stateByCallId.set(callId, state);
|
|
@@ -129,16 +180,14 @@ export class SubAgentTracker {
|
|
|
129
180
|
}
|
|
130
181
|
|
|
131
182
|
/**
|
|
132
|
-
*
|
|
183
|
+
* Clear the streaming flag on every tracked sub-agent's in-flight
|
|
184
|
+
* messages. Called when the turn stops before the sub-agents finished;
|
|
185
|
+
* the rows' own CANCELLED transition is the caller's, through the shared
|
|
186
|
+
* `cancelInProgressSubAgentProtos` (see the header).
|
|
133
187
|
*/
|
|
134
|
-
|
|
188
|
+
finalizeAllStreaming(): void {
|
|
135
189
|
for (const state of this.stateByCallId.values()) {
|
|
136
|
-
|
|
137
|
-
state.proto.status = SubAgentStatus.SUB_AGENT_CANCELLED;
|
|
138
|
-
state.proto.completedAt = utcTimestamp();
|
|
139
|
-
state.proto.error = "Cancelled: parent execution was cancelled";
|
|
140
|
-
this.finalizeStreamingMessages(state);
|
|
141
|
-
}
|
|
190
|
+
this.finalizeStreamingMessages(state);
|
|
142
191
|
}
|
|
143
192
|
}
|
|
144
193
|
|
|
@@ -186,7 +235,7 @@ export class SubAgentTracker {
|
|
|
186
235
|
this.handleToolCallArgDelta(state, event.callId, event.argsChunk);
|
|
187
236
|
break;
|
|
188
237
|
case "message_finish":
|
|
189
|
-
this.handleMessageFinish(state, event.runId
|
|
238
|
+
this.handleMessageFinish(state, event.runId);
|
|
190
239
|
break;
|
|
191
240
|
case "tool_started":
|
|
192
241
|
this.handleToolStarted(state, event.callId, event.name, event.input, localNs);
|
|
@@ -207,20 +256,6 @@ export class SubAgentTracker {
|
|
|
207
256
|
}
|
|
208
257
|
}
|
|
209
258
|
|
|
210
|
-
/**
|
|
211
|
-
* Returns the current list of SubAgentExecution protos for persist.
|
|
212
|
-
*/
|
|
213
|
-
getExecutions(): SubAgentExecution[] {
|
|
214
|
-
return this.executions;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Returns true if any sub-agents are being tracked.
|
|
219
|
-
*/
|
|
220
|
-
hasExecutions(): boolean {
|
|
221
|
-
return this.executions.length > 0;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
259
|
// ── Message Handlers ─────────────────────────────────────────────────────
|
|
225
260
|
|
|
226
261
|
private handleMessageStart(state: SubAgentState, runId: string, localNs: string): void {
|
|
@@ -258,11 +293,11 @@ export class SubAgentTracker {
|
|
|
258
293
|
state.messagesByRun.set(thinkingKey, msg);
|
|
259
294
|
}
|
|
260
295
|
|
|
261
|
-
private handleMessageFinish(state: SubAgentState, runId: string
|
|
296
|
+
private handleMessageFinish(state: SubAgentState, runId: string): void {
|
|
262
297
|
const msg = state.messagesByRun.get(runId);
|
|
263
298
|
if (msg) msg.isStreaming = false;
|
|
264
|
-
//
|
|
265
|
-
|
|
299
|
+
// The usage on this event was reported by `V3StatusBuilder.processEvent`
|
|
300
|
+
// before it routed here (Q-M2b-1); the tracker owns the transcript only.
|
|
266
301
|
}
|
|
267
302
|
|
|
268
303
|
// ── Tool Handlers ──────────────────────────────────────────────────────
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - Built-in general-purpose replaces deepagents' auto-injected one (which carries
|
|
15
15
|
* no approval gate — see deepagents-profiles.ts for the suppression half)
|
|
16
16
|
* - Sub-agent backends are shell-capable outside plan mode (issue #248), mirroring
|
|
17
|
-
* the parent's backend selection in setup.ts
|
|
17
|
+
* the parent's backend selection in turn-setup.ts
|
|
18
18
|
* - Sub-agent graphs carry the parent's filesystem permissions explicitly
|
|
19
19
|
* (issue #255): pre-built CompiledSubAgents never inherit them, so plan
|
|
20
20
|
* mode's deny-all-writes rule is baked into each graph at compile time
|
|
@@ -31,20 +31,16 @@ import type { BaseChatModel } from "@langchain/core/language_models/chat_models"
|
|
|
31
31
|
import type { SubAgent, McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
32
32
|
|
|
33
33
|
import type { WorkspaceBackend } from "../../shared/workspace/types.js";
|
|
34
|
-
import type { StigmerClient } from "../../client/stigmer-client.js";
|
|
35
34
|
import type { ApprovalGateConfig } from "../../middleware/approval-gate.js";
|
|
36
35
|
import { createCasCaptureBackend } from "./cas-capture-backend.js";
|
|
37
36
|
import type { CasCaptureObserver } from "./cas-capture-observer.js";
|
|
38
|
-
import type {
|
|
37
|
+
import type { CostAdvisoryMiddleware, StigmerMiddleware } from "../../middleware/index.js";
|
|
39
38
|
import { createThinkTool, createWebFetchTool, type GuardPosture } from "../../tools/index.js";
|
|
40
39
|
import { buildSubAgentMiddleware } from "./subagent-wiring.js";
|
|
41
40
|
import { SubAgentGate } from "../../shared/subagent-gate.js";
|
|
42
41
|
import { isModelRegistered } from "../../shared/model-registry.js";
|
|
43
|
-
import {
|
|
44
|
-
|
|
45
|
-
mountSkills,
|
|
46
|
-
generatePromptSection,
|
|
47
|
-
} from "../../shared/skill-writer.js";
|
|
42
|
+
import type { SkillMetadata } from "../../shared/skill-resolver.js";
|
|
43
|
+
import { renderSkillsSection } from "./prompt-builder.js";
|
|
48
44
|
|
|
49
45
|
// =========================================================================
|
|
50
46
|
// Built-in subagent types and prompts
|
|
@@ -141,7 +137,14 @@ export interface SubagentTransformOptions {
|
|
|
141
137
|
readonly parentMcpTools: readonly StructuredTool[];
|
|
142
138
|
readonly parentMcpServerToolMap: ReadonlyMap<string, readonly StructuredTool[]>;
|
|
143
139
|
readonly parentMcpUsages: readonly McpServerUsage[];
|
|
144
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Each sub-agent's mounted skills, keyed by the sub-agent's name — the
|
|
142
|
+
* runtime's `TurnSkills.bySubAgent` (resolved and mounted by its skills
|
|
143
|
+
* phase, S3 M1 Q-S3-5). A sub-agent with no entry renders no skills
|
|
144
|
+
* section. Until S3 M2a this module fetched and mounted them itself with
|
|
145
|
+
* a control-plane client; the compile step is client-free now.
|
|
146
|
+
*/
|
|
147
|
+
readonly skills: ReadonlyMap<string, readonly SkillMetadata[]>;
|
|
145
148
|
readonly workspaceBackend: WorkspaceBackend;
|
|
146
149
|
/**
|
|
147
150
|
* The parent's approval-gate config, inherited verbatim so a mutating tool
|
|
@@ -162,11 +165,11 @@ export interface SubagentTransformOptions {
|
|
|
162
165
|
readonly parentHasNativeThinking: boolean;
|
|
163
166
|
/**
|
|
164
167
|
* URL-guard posture for the native `web_fetch` tool, inherited from the
|
|
165
|
-
* parent (resolveGuardPosture(config.mode) in setup.ts) so a sub-agent
|
|
168
|
+
* parent (resolveGuardPosture(config.mode) in turn-setup.ts) so a sub-agent
|
|
166
169
|
* fetch is bounded exactly like a parent fetch.
|
|
167
170
|
*/
|
|
168
171
|
readonly webFetchPosture: GuardPosture;
|
|
169
|
-
readonly
|
|
172
|
+
readonly costAdvisory?: CostAdvisoryMiddleware;
|
|
170
173
|
/**
|
|
171
174
|
* Builds a configured chat-model instance for a given model name. When
|
|
172
175
|
* provided, sub-agents are compiled with the same proxy-aware model client
|
|
@@ -184,7 +187,7 @@ export interface SubagentTransformOptions {
|
|
|
184
187
|
readonly shellEnv?: Record<string, string>;
|
|
185
188
|
/**
|
|
186
189
|
* Filesystem permission rules baked into each compiled sub-agent graph,
|
|
187
|
-
* inherited from the parent's rules in setup.ts (plan mode's deny-all-writes
|
|
190
|
+
* inherited from the parent's rules in turn-setup.ts (plan mode's deny-all-writes
|
|
188
191
|
* today). Required because deepagents' parent-permission inheritance covers
|
|
189
192
|
* only spec-style sub-agents — pre-built CompiledSubAgents bypass it, so
|
|
190
193
|
* without this a plan-mode sub-agent could still write (issue #255).
|
|
@@ -321,7 +324,7 @@ export async function transformSingleSubagent(
|
|
|
321
324
|
}
|
|
322
325
|
|
|
323
326
|
// web_fetch is unconditional — unlike think, it is a capability, not a
|
|
324
|
-
// reasoning aid, and the parent always has it (setup.ts
|
|
327
|
+
// reasoning aid, and the parent always has it (turn-setup.ts `buildEngine`). A
|
|
325
328
|
// sub-agent silently lacking web access the parent has would recreate the
|
|
326
329
|
// harness-parity gap of issue #214 one level down.
|
|
327
330
|
tools.push(createWebFetchTool({ posture: opts.webFetchPosture }) as unknown as StructuredTool);
|
|
@@ -415,64 +418,38 @@ export function filterMcpToolsForSubagent(
|
|
|
415
418
|
// =========================================================================
|
|
416
419
|
|
|
417
420
|
/**
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
* Deduplicates by slug to minimize gRPC calls. Returns an array of refs
|
|
421
|
-
* and the mapping from slug to original refs for distribution.
|
|
421
|
+
* The `## Skills` section of one sub-agent's system prompt, from the skills
|
|
422
|
+
* the runtime mounted for it. Empty when it has none.
|
|
422
423
|
*/
|
|
423
|
-
export function
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
for (const sa of subAgents) {
|
|
430
|
-
for (const ref of sa.skillRefs) {
|
|
431
|
-
const slug = (ref as { slug?: string }).slug;
|
|
432
|
-
if (slug && !seen.has(slug)) {
|
|
433
|
-
seen.add(slug);
|
|
434
|
-
unique.push({ slug, ref });
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
return unique;
|
|
424
|
+
export function resolveSubagentSkillPrompt(
|
|
425
|
+
subAgent: SubAgent,
|
|
426
|
+
skills: ReadonlyMap<string, readonly SkillMetadata[]>,
|
|
427
|
+
): string {
|
|
428
|
+
return renderSkillsSection(skills.get(subAgent.name) ?? []);
|
|
440
429
|
}
|
|
441
430
|
|
|
442
431
|
/**
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* Returns empty string if no skills match or if the subagent has no skill_refs.
|
|
432
|
+
* Heuristic check for native extended thinking support. Models with thinking
|
|
433
|
+
* support don't need the explicit think tool. Read for the parent (does its
|
|
434
|
+
* graph carry `think`?) and inherited by every sub-agent that names no model
|
|
435
|
+
* of its own. Moved from `setup.ts` at S3 M2a: the compile step is where it
|
|
436
|
+
* is consumed, and the adapter's setup reads it from here too.
|
|
450
437
|
*/
|
|
451
|
-
export function
|
|
452
|
-
|
|
453
|
-
skillsBySlug: ReadonlyMap<string, { skill: unknown; path: string }>,
|
|
454
|
-
): string {
|
|
455
|
-
if (subAgent.skillRefs.length === 0) return "";
|
|
438
|
+
export function modelHasNativeThinking(modelId: string): boolean {
|
|
439
|
+
const lower = modelId.toLowerCase();
|
|
456
440
|
|
|
457
|
-
|
|
458
|
-
|
|
441
|
+
if (lower.includes("haiku")) return false;
|
|
442
|
+
if (lower.includes("gpt-4o-mini")) return false;
|
|
459
443
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
444
|
+
if (lower.includes("claude") && (
|
|
445
|
+
lower.includes("sonnet") || lower.includes("opus")
|
|
446
|
+
)) return true;
|
|
463
447
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
matchedSkills.push(entry.skill);
|
|
467
|
-
const id = (entry.skill as { metadata?: { id?: string } }).metadata?.id;
|
|
468
|
-
if (id) matchedPaths.set(id, entry.path);
|
|
469
|
-
}
|
|
448
|
+
if (lower.includes("o1") || lower.includes("o3") || lower.includes("o4")) {
|
|
449
|
+
return true;
|
|
470
450
|
}
|
|
471
451
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
475
|
-
return generatePromptSection(matchedSkills as any[], matchedPaths);
|
|
452
|
+
return false;
|
|
476
453
|
}
|
|
477
454
|
|
|
478
455
|
// =========================================================================
|
|
@@ -481,7 +458,7 @@ export function resolveSubagentSkillPrompt(
|
|
|
481
458
|
|
|
482
459
|
/**
|
|
483
460
|
* Select a sub-agent's deepagents backend, mirroring the parent's selection in
|
|
484
|
-
* setup.ts along two independent axes:
|
|
461
|
+
* turn-setup.ts along two independent axes:
|
|
485
462
|
*
|
|
486
463
|
* - CAS observation (capture mode): when a shared observer is supplied, the
|
|
487
464
|
* backend records pre-turn bytes of CAS-owned paths so the sub-agent's
|
|
@@ -535,7 +512,7 @@ async function buildSubagentBackend(opts: {
|
|
|
535
512
|
export async function compileSubagents(
|
|
536
513
|
transformed: readonly TransformedSubagent[],
|
|
537
514
|
opts: {
|
|
538
|
-
readonly
|
|
515
|
+
readonly costAdvisory?: CostAdvisoryMiddleware;
|
|
539
516
|
readonly approvalGate?: ApprovalGateConfig | null;
|
|
540
517
|
readonly parentModelName: string;
|
|
541
518
|
readonly workspaceRootDir: string;
|
|
@@ -562,7 +539,7 @@ export async function compileSubagents(
|
|
|
562
539
|
// (issue #754): every graph speaks the virtual dialect, so every graph
|
|
563
540
|
// carries the repair seam — matching the parent's composition.
|
|
564
541
|
const middleware = buildSubAgentMiddleware({
|
|
565
|
-
|
|
542
|
+
costAdvisory: opts.costAdvisory,
|
|
566
543
|
approvalGate: opts.approvalGate,
|
|
567
544
|
captureIgnored: !!opts.casObserver,
|
|
568
545
|
pathNormalization: { rootDir: opts.workspaceRootDir },
|
|
@@ -623,7 +600,7 @@ export async function compileSubagents(
|
|
|
623
600
|
/**
|
|
624
601
|
* Transform proto SubAgents and compile into CompiledSubAgent instances.
|
|
625
602
|
*
|
|
626
|
-
* This is the main entry point called from setup.ts. It orchestrates:
|
|
603
|
+
* This is the main entry point called from turn-setup.ts. It orchestrates:
|
|
627
604
|
* 1. Built-in subagent creation (explore, shell, general-purpose)
|
|
628
605
|
* 2. Per-subagent transformation (proto → TransformedSubagent)
|
|
629
606
|
* 3. MCP tool filtering per subagent
|
|
@@ -640,14 +617,14 @@ export async function transformAndCompileSubagents(
|
|
|
640
617
|
parentMcpTools,
|
|
641
618
|
parentMcpServerToolMap,
|
|
642
619
|
parentMcpUsages,
|
|
643
|
-
|
|
620
|
+
skills,
|
|
644
621
|
workspaceBackend,
|
|
645
622
|
approvalGate,
|
|
646
623
|
casObserver,
|
|
647
624
|
parentModelName,
|
|
648
625
|
parentHasNativeThinking,
|
|
649
626
|
webFetchPosture,
|
|
650
|
-
|
|
627
|
+
costAdvisory,
|
|
651
628
|
modelFactory,
|
|
652
629
|
shellEnv,
|
|
653
630
|
permissions,
|
|
@@ -669,42 +646,6 @@ export async function transformAndCompileSubagents(
|
|
|
669
646
|
webFetchPosture,
|
|
670
647
|
);
|
|
671
648
|
|
|
672
|
-
// Step 1b: Batch fetch all skills referenced by subagents
|
|
673
|
-
const allSkillRefs = collectAllSkillRefs(subAgents);
|
|
674
|
-
const skillsBySlug = new Map<string, { skill: unknown; path: string }>();
|
|
675
|
-
|
|
676
|
-
if (allSkillRefs.length > 0) {
|
|
677
|
-
try {
|
|
678
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
679
|
-
const refs = allSkillRefs.map((r) => r.ref) as any[];
|
|
680
|
-
const skills = await fetchSkillsByRefs(skillClient, refs);
|
|
681
|
-
|
|
682
|
-
if (skills.length > 0) {
|
|
683
|
-
// Runs after the parent's setup step 7b mounted its skills, so any
|
|
684
|
-
// skill shared by parent and sub-agent is a cache hit here — the
|
|
685
|
-
// hash-keyed marker turns the old double download into a no-op.
|
|
686
|
-
// platformDir is an invariant: provisionWorkspace threads
|
|
687
|
-
// ensurePlatformDir into every backend it constructs.
|
|
688
|
-
const { paths: skillPaths } = await mountSkills(
|
|
689
|
-
skillClient, skills, workspaceBackend.platformDir!,
|
|
690
|
-
);
|
|
691
|
-
|
|
692
|
-
for (const skill of skills) {
|
|
693
|
-
const slug = (skill as { metadata?: { slug?: string } }).metadata?.slug;
|
|
694
|
-
const id = (skill as { metadata?: { id?: string } }).metadata?.id;
|
|
695
|
-
if (slug && id) {
|
|
696
|
-
skillsBySlug.set(slug, { skill, path: skillPaths.get(id) ?? "" });
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
console.log(
|
|
700
|
-
`[subagent-transformer] Fetched ${skills.length} skill(s) for subagents`,
|
|
701
|
-
);
|
|
702
|
-
}
|
|
703
|
-
} catch (err) {
|
|
704
|
-
console.error(`[subagent-transformer] Failed to fetch skills for subagents: ${err}`);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
649
|
// Step 2: Transform proto subagents
|
|
709
650
|
const transformed: TransformedSubagent[] = [];
|
|
710
651
|
|
|
@@ -735,7 +676,7 @@ export async function transformAndCompileSubagents(
|
|
|
735
676
|
);
|
|
736
677
|
|
|
737
678
|
// Resolve skills prompt section for this subagent
|
|
738
|
-
const skillsSection = resolveSubagentSkillPrompt(subAgent,
|
|
679
|
+
const skillsSection = resolveSubagentSkillPrompt(subAgent, skills);
|
|
739
680
|
const enhancedPrompt = skillsSection
|
|
740
681
|
? result.systemPrompt.replace(
|
|
741
682
|
RESPONSE_RULES,
|
|
@@ -770,7 +711,7 @@ export async function transformAndCompileSubagents(
|
|
|
770
711
|
|
|
771
712
|
// Step 4: Compile all subagents
|
|
772
713
|
const compiled = await compileSubagents(allSpecs, {
|
|
773
|
-
|
|
714
|
+
costAdvisory,
|
|
774
715
|
approvalGate,
|
|
775
716
|
parentModelName,
|
|
776
717
|
workspaceRootDir: workspaceBackend.rootDir,
|
|
@@ -41,7 +41,7 @@ import type {
|
|
|
41
41
|
ToolTruncationConfig,
|
|
42
42
|
PathNormalizationConfig,
|
|
43
43
|
} from "../../middleware/types.js";
|
|
44
|
-
import type {
|
|
44
|
+
import type { CostAdvisoryMiddleware } from "../../middleware/index.js";
|
|
45
45
|
import { createPathNormalizationMiddleware } from "../../middleware/path-normalization.js";
|
|
46
46
|
import { createLoopDetectionMiddleware } from "../../middleware/loop-detection.js";
|
|
47
47
|
import { createToolTruncationMiddleware } from "../../middleware/tool-truncation.js";
|
|
@@ -57,7 +57,8 @@ const SUB_AGENT_ADVISORY_INTERVAL = 30;
|
|
|
57
57
|
const SUB_AGENT_MAX_ADVISORIES = 4;
|
|
58
58
|
|
|
59
59
|
export interface SubAgentMiddlewareOptions {
|
|
60
|
-
|
|
60
|
+
/** The parent's cost advisory, whose running total the sub-agent's calls advance. */
|
|
61
|
+
readonly costAdvisory?: CostAdvisoryMiddleware;
|
|
61
62
|
readonly toolTruncation?: Partial<ToolTruncationConfig>;
|
|
62
63
|
/**
|
|
63
64
|
* Approval gate config inherited from the parent. When present, the sub-agent
|
|
@@ -142,8 +143,8 @@ export function buildSubAgentMiddleware(
|
|
|
142
143
|
));
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
if (options.
|
|
146
|
-
stack.push(options.
|
|
146
|
+
if (options.costAdvisory) {
|
|
147
|
+
stack.push(options.costAdvisory.forSubAgent());
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
stack.push(createErrorHintsMiddleware());
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The native deep-agent harness's settle — from a consumed stream to a
|
|
3
|
+
* `TurnOutcome`.
|
|
4
|
+
*
|
|
5
|
+
* In order: drain the inline publishes the stream fired and, on a finished
|
|
6
|
+
* turn, run the auto-publish safety net; settle the gate's unattended skips
|
|
7
|
+
* (the one settlement whose evidence exists only inside this harness); on
|
|
8
|
+
* the runtime's stop, mark in-flight sub-agent rows through the shared act
|
|
9
|
+
* and settle `interrupted` with nothing further; the graph's
|
|
10
|
+
* `structuredResponse` folded onto the status; the interrupts a completed
|
|
11
|
+
* stream left pending seeded as WAITING rows; and the outcome.
|
|
12
|
+
*
|
|
13
|
+
* What this module never does: write a phase, a terminal copy or
|
|
14
|
+
* `completedAt` — those are the runtime's (`harness/run-turn.ts`,
|
|
15
|
+
* `terminal-table.ts`); settle SKIP and REJECT rows — the runtime's
|
|
16
|
+
* (`harness/approval-decisions.ts`, after every outcome); withhold secret
|
|
17
|
+
* content — the runtime's chokepoint does it on every write; finalize the
|
|
18
|
+
* write-back — the runtime's epilogue; capture the turn's file changes or
|
|
19
|
+
* decide whether a review is pending — the runtime's (`harness/capture.ts`,
|
|
20
|
+
* once, over whatever the whole turn left on the tree, after this settle
|
|
21
|
+
* returns; S3 M4). It does mutate `sink.status`'s transcript rows, which
|
|
22
|
+
* are this harness's to write.
|
|
23
|
+
*
|
|
24
|
+
* The structured response is folded BEFORE the outcome is decided, so a turn
|
|
25
|
+
* the runtime then pauses for file review persists it and the pure
|
|
26
|
+
* file-review resume completes with it (the runtime's text fallback runs on
|
|
27
|
+
* the review-pending path too, Q-M4-8).
|
|
28
|
+
*
|
|
29
|
+
* Moved from `index.ts` (post-stream through the terminal arms) at S3 M2a;
|
|
30
|
+
* the capture boundary left for the runtime at M4.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { create, type JsonObject } from "@bufbuild/protobuf";
|
|
34
|
+
import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
35
|
+
import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
36
|
+
|
|
37
|
+
import type { TurnInput, TurnOutcome, TurnSink } from "../../harness/types.js";
|
|
38
|
+
import { POLICY_ENGINE_VERSION, toProtoPolicySource } from "../../shared/approval-policy.js";
|
|
39
|
+
import { utcTimestamp } from "../../shared/status.js";
|
|
40
|
+
import { cancelInProgressSubAgentProtos } from "../../shared/subagent-rows.js";
|
|
41
|
+
import { classifyTool } from "../../shared/tool-kind.js";
|
|
42
|
+
import { captureApprovalArtifacts } from "./approval-file-change.js";
|
|
43
|
+
import { autoPublishWrittenFiles } from "./auto-publish.js";
|
|
44
|
+
import { detectPendingInterrupts, reconcileUnattendedSkips, type GraphStateSnapshot } from "./hitl.js";
|
|
45
|
+
import type { DeepAgentEngine } from "./turn-setup.js";
|
|
46
|
+
import type { DeepAgentStreamResult, DeepAgentTranscript } from "./turn-stream.js";
|
|
47
|
+
|
|
48
|
+
export interface DeepAgentSettleDeps {
|
|
49
|
+
readonly input: TurnInput;
|
|
50
|
+
readonly sink: TurnSink;
|
|
51
|
+
readonly engine: DeepAgentEngine;
|
|
52
|
+
readonly transcript: DeepAgentTranscript;
|
|
53
|
+
readonly stream: DeepAgentStreamResult;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function settleDeepAgentTurn(deps: DeepAgentSettleDeps): Promise<TurnOutcome> {
|
|
57
|
+
const { input, sink, engine, transcript, stream } = deps;
|
|
58
|
+
const { executionId } = input;
|
|
59
|
+
const { status } = sink;
|
|
60
|
+
|
|
61
|
+
// Drain the publishes the stream fired (fire-and-forget completions); the
|
|
62
|
+
// safety net that scans tool calls for files the stream missed runs only
|
|
63
|
+
// on a finished turn, as it always did.
|
|
64
|
+
if (stream.pendingPublishPromises.length > 0) {
|
|
65
|
+
await Promise.allSettled(stream.pendingPublishPromises);
|
|
66
|
+
}
|
|
67
|
+
if (stream.reason === "completed") {
|
|
68
|
+
try {
|
|
69
|
+
await autoPublishWrittenFiles(status, transcript.publisher);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.warn(`[turn-settle] execution=${executionId} — auto-publish safety net error: ${err}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
sink.recordActivity();
|
|
75
|
+
|
|
76
|
+
// Terminalize every tool call the gate auto-skipped under UNATTENDED
|
|
77
|
+
// approval mode (DD-014): the skip has no human decision behind it, so the
|
|
78
|
+
// runtime's terminalizer cannot see it; the gate's registry is this
|
|
79
|
+
// harness's evidence.
|
|
80
|
+
reconcileUnattendedSkips(status, engine.gate.unattendedSkips);
|
|
81
|
+
|
|
82
|
+
if (stream.reason === "interrupted") {
|
|
83
|
+
// A stopped turn aborted the graph run, so any sub-agent the parent had
|
|
84
|
+
// delegated is no longer executing: CANCELLED through the one shared act
|
|
85
|
+
// (the runtime marks them itself only on its thrown arms), its messages'
|
|
86
|
+
// streaming flags cleared. There is no review to open.
|
|
87
|
+
cancelInProgressSubAgentProtos(status.subAgentExecutions);
|
|
88
|
+
transcript.builder.finalizeSubAgentStreaming();
|
|
89
|
+
return { kind: "interrupted" };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The graph's structured response, when the run surfaced one: folded now,
|
|
93
|
+
// so a turn the runtime pauses for review persists it and the pure
|
|
94
|
+
// file-review resume completes with it.
|
|
95
|
+
if (engine.hasStructuredOutput) {
|
|
96
|
+
const sr = stream.runOutput?.structuredResponse;
|
|
97
|
+
if (sr != null && typeof sr === "object" && !Array.isArray(sr)) {
|
|
98
|
+
status.structuredOutput = sr as JsonObject;
|
|
99
|
+
} else if (sr !== undefined) {
|
|
100
|
+
console.warn(`[turn-settle] structuredResponse is not a plain object for execution ${executionId}: type=${typeof sr}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (stream.reason === "awaiting_approval") {
|
|
105
|
+
return { kind: "awaiting_approval" };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// A completed stream can still leave the graph interrupted at a gate whose
|
|
109
|
+
// tool start produced no row (the durable savers resume without a
|
|
110
|
+
// tool_started; the replay path never re-drives it): read the checkpoint
|
|
111
|
+
// once more and seed a WAITING row per pending interrupt. Skipped under
|
|
112
|
+
// the global bypass, where no gate is installed.
|
|
113
|
+
if (!engine.gate.globalBypass && (await seedPendingInterrupts(deps))) {
|
|
114
|
+
return { kind: "awaiting_approval" };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { kind: "completed" };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Seed one WAITING_APPROVAL row per interrupt the graph left pending, on one
|
|
122
|
+
* AI message, with the sanitized args preview AND the redacted args read
|
|
123
|
+
* from the AI message in graph state (the single source of truth for the
|
|
124
|
+
* proposed call; issue #754: a placeholder without args rendered a pathless
|
|
125
|
+
* header). Returns whether any was seeded.
|
|
126
|
+
*/
|
|
127
|
+
async function seedPendingInterrupts(deps: DeepAgentSettleDeps): Promise<boolean> {
|
|
128
|
+
const { input, sink, engine } = deps;
|
|
129
|
+
const graphState: GraphStateSnapshot = await engine.graph.getState(engine.langgraphConfig);
|
|
130
|
+
const pending = detectPendingInterrupts(graphState);
|
|
131
|
+
if (pending.length === 0) return false;
|
|
132
|
+
|
|
133
|
+
const graphMessages = (graphState.values as { messages?: unknown }).messages;
|
|
134
|
+
const aiMessages = Array.isArray(graphMessages) ? graphMessages : [];
|
|
135
|
+
console.log(`[turn-settle] Detected ${pending.length} pending interrupt(s) for execution ${input.executionId} — awaiting approval`);
|
|
136
|
+
|
|
137
|
+
const aiMsg = create(AgentMessageSchema, {
|
|
138
|
+
type: MessageType.MESSAGE_AI,
|
|
139
|
+
content: "",
|
|
140
|
+
timestamp: utcTimestamp(),
|
|
141
|
+
isStreaming: false,
|
|
142
|
+
});
|
|
143
|
+
for (const intr of pending) {
|
|
144
|
+
const toolCall = create(ToolCallSchema, {
|
|
145
|
+
id: intr.toolCallId,
|
|
146
|
+
name: intr.toolName,
|
|
147
|
+
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
148
|
+
requiresApproval: true,
|
|
149
|
+
approvalMessage: intr.message,
|
|
150
|
+
approvalRequestedAt: utcTimestamp(),
|
|
151
|
+
mcpServerSlug: intr.mcpServerSlug,
|
|
152
|
+
startedAt: utcTimestamp(),
|
|
153
|
+
toolKind: classifyTool(intr.toolName, intr.mcpServerSlug),
|
|
154
|
+
approvalPolicySource: toProtoPolicySource(intr.policySource),
|
|
155
|
+
policyEngineVersion: intr.policySource ? POLICY_ENGINE_VERSION : "",
|
|
156
|
+
});
|
|
157
|
+
const { argsPreview, args } = captureApprovalArtifacts({ toolCallId: intr.toolCallId, messages: aiMessages });
|
|
158
|
+
if (argsPreview) toolCall.argsPreview = argsPreview;
|
|
159
|
+
if (args) toolCall.args = args as typeof toolCall.args;
|
|
160
|
+
aiMsg.toolCalls.push(toolCall);
|
|
161
|
+
}
|
|
162
|
+
sink.status.messages.push(aiMsg);
|
|
163
|
+
return true;
|
|
164
|
+
}
|