@stigmer/runner 3.15.1 → 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
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The native adapter's stream loop (`turn-stream.ts` `consumeDeepAgentStream`)
|
|
3
|
+
* over a SCRIPTED v3 run and the kit's recording sink — no graph, no model,
|
|
4
|
+
* no runtime. What the hermetic goldens prove end to end, this file pins one
|
|
5
|
+
* rule at a time, where a failure names the rule:
|
|
6
|
+
*
|
|
7
|
+
* - how the graph is invoked (the two-arg v3 `streamEvents` shape, the
|
|
8
|
+
* runtime's `langgraphConfig` carried whole, the loop's own abort signal);
|
|
9
|
+
* - what each event becomes (the normalizer feeds the builder; the sink
|
|
10
|
+
* learns of activity per event, with the tool's name as the detail);
|
|
11
|
+
* - what the sink is told and when (usage priced per `message_finish`;
|
|
12
|
+
* a persist requested on the shared cadence rule, a tool start forcing it);
|
|
13
|
+
* - how the loop ends: `completed` with the run's output, `awaiting_approval`
|
|
14
|
+
* at a gate, `interrupted` when the runtime stops it — taken at the NEXT
|
|
15
|
+
* event, the engine's own step boundary (S3 M2a F-M2a-18), and before the
|
|
16
|
+
* first if the stop came earlier;
|
|
17
|
+
* - what it refuses and what it tolerates: an empty stream throws; the
|
|
18
|
+
* engine's own error propagates; a `run.output` that rejects is logged
|
|
19
|
+
* and the turn completes without a final state;
|
|
20
|
+
* - the recorder exists only under `V3_EVENT_RECORD_DIR`.
|
|
21
|
+
*
|
|
22
|
+
* Carried from the legacy v3 loop's suite (`streaming-v3.test.ts`, retired
|
|
23
|
+
* with the loop at S3 M2b, Q-M2b-5): the arms whose rule the adapter's loop
|
|
24
|
+
* still has, re-stated against the sink. The loop-specific arms it dropped
|
|
25
|
+
* (the in-band heartbeat timer, the 120 s stall, STOP read from the persist,
|
|
26
|
+
* pause as a terminal status) are the turn runtime's now and pinned in
|
|
27
|
+
* `harness/__tests__` and the hermetic goldens.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
31
|
+
import { existsSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
32
|
+
import { tmpdir } from "node:os";
|
|
33
|
+
import { join } from "node:path";
|
|
34
|
+
import { MemorySaver } from "@langchain/langgraph";
|
|
35
|
+
import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
36
|
+
|
|
37
|
+
import { RecordingTurnSink } from "../../../__test-utils__/harness-contract/recording-sink.js";
|
|
38
|
+
import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
|
|
39
|
+
import { turnInputFixture } from "../../../__test-utils__/turn-input-fixture.js";
|
|
40
|
+
import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
|
|
41
|
+
import type { ModelPricing } from "../../../shared/model-pricing.js";
|
|
42
|
+
import type { MergedToolPolicy } from "../../../shared/approval-policy.js";
|
|
43
|
+
import { CasCaptureObserver } from "../cas-capture-observer.js";
|
|
44
|
+
import type { DeepAgentEngine, DeepAgentGateState, DeepAgentGraphInput, DeepAgentWorkspace } from "../turn-setup.js";
|
|
45
|
+
import { consumeDeepAgentStream, createDeepAgentTranscript, type StreamableRun } from "../turn-stream.js";
|
|
46
|
+
import type { V3ProtocolEvent } from "../v3-event-recorder.js";
|
|
47
|
+
import {
|
|
48
|
+
makeMessageFinish,
|
|
49
|
+
makeMessageStart,
|
|
50
|
+
makeTextDelta,
|
|
51
|
+
makeToolFinished,
|
|
52
|
+
makeToolStarted,
|
|
53
|
+
resetSeq,
|
|
54
|
+
} from "../__test-utils__/v3-event-fixtures.js";
|
|
55
|
+
|
|
56
|
+
const PRICING: ModelPricing = {
|
|
57
|
+
model: "claude-haiku-4.5",
|
|
58
|
+
displayName: "Haiku (test)",
|
|
59
|
+
costTier: "standard",
|
|
60
|
+
inputPricePerMillion: 1.0,
|
|
61
|
+
outputPricePerMillion: 5.0,
|
|
62
|
+
cacheWritePricePerMillion: 1.25,
|
|
63
|
+
cacheReadPricePerMillion: 0.1,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function openGate(overrides: Partial<DeepAgentGateState> = {}): DeepAgentGateState {
|
|
67
|
+
return {
|
|
68
|
+
policies: new Map(),
|
|
69
|
+
toolServerMap: new Map(),
|
|
70
|
+
leasedCategories: new Set(),
|
|
71
|
+
globalBypass: false,
|
|
72
|
+
unattended: false,
|
|
73
|
+
unattendedSkips: new Set(),
|
|
74
|
+
...overrides,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A workspace whose files are the given map; the publisher reads through it. */
|
|
79
|
+
function workspaceOver(files: Record<string, string>): DeepAgentWorkspace {
|
|
80
|
+
const backend: WorkspaceBackend = {
|
|
81
|
+
rootDir: "/workspace",
|
|
82
|
+
execute: vi.fn(async () => ""),
|
|
83
|
+
readFile: vi.fn(async (path: string) => {
|
|
84
|
+
const content = files[path];
|
|
85
|
+
if (content === undefined) throw new Error(`File not found: ${path}`);
|
|
86
|
+
return content;
|
|
87
|
+
}),
|
|
88
|
+
writeFile: vi.fn(async () => undefined),
|
|
89
|
+
writeFileBuffer: vi.fn(async () => undefined),
|
|
90
|
+
exists: vi.fn(async (path: string) => path in files),
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
backend,
|
|
94
|
+
casObserver: new CasCaptureObserver({ rootDir: "/workspace", isIgnored: async () => false }),
|
|
95
|
+
isCapturablePath: async () => false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface ScriptedRunOptions {
|
|
100
|
+
/** The final state `run.output` resolves to; a function so a rejection is created when the run is. */
|
|
101
|
+
readonly output?: () => Promise<unknown>;
|
|
102
|
+
/** Called between events, after the event at this index was yielded and before the next is. */
|
|
103
|
+
readonly between?: (yielded: number) => void;
|
|
104
|
+
/** Thrown from the stream after this many events. */
|
|
105
|
+
readonly failAfter?: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** A `StreamableRun` over scripted events; what the graph would hand the loop. */
|
|
109
|
+
function scriptedRun(events: readonly V3ProtocolEvent[], options: ScriptedRunOptions = {}): StreamableRun {
|
|
110
|
+
const output = options.output ? options.output() : Promise.resolve({ messages: [] });
|
|
111
|
+
const iterate = async function* (): AsyncGenerator<V3ProtocolEvent> {
|
|
112
|
+
let yielded = 0;
|
|
113
|
+
for (const event of events) {
|
|
114
|
+
if (options.failAfter !== undefined && yielded === options.failAfter) throw new Error("engine exploded mid-stream");
|
|
115
|
+
yield event;
|
|
116
|
+
yielded++;
|
|
117
|
+
options.between?.(yielded);
|
|
118
|
+
}
|
|
119
|
+
if (options.failAfter !== undefined && yielded === options.failAfter) throw new Error("engine exploded mid-stream");
|
|
120
|
+
};
|
|
121
|
+
return { output, [Symbol.asyncIterator]: iterate };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface Harness {
|
|
125
|
+
readonly sink: RecordingTurnSink;
|
|
126
|
+
readonly engine: DeepAgentEngine;
|
|
127
|
+
readonly streamEvents: ReturnType<typeof vi.fn>;
|
|
128
|
+
readonly blobs: Map<string, Buffer>;
|
|
129
|
+
run(run: StreamableRun): ReturnType<typeof consumeDeepAgentStream>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function harness(options: { gate?: DeepAgentGateState; files?: Record<string, string> } = {}): Harness {
|
|
133
|
+
// Artifact storage is part of the turn's input; the publisher uploads there
|
|
134
|
+
// and registers the artifact on the status, or does nothing at all without it.
|
|
135
|
+
const { storage, blobs } = makeInMemoryArtifactStorage();
|
|
136
|
+
const input = turnInputFixture({ message: "Say hello.", artifactStorage: storage });
|
|
137
|
+
const sink = new RecordingTurnSink();
|
|
138
|
+
const streamEvents = vi.fn();
|
|
139
|
+
const engine: DeepAgentEngine = {
|
|
140
|
+
graph: { streamEvents },
|
|
141
|
+
checkpointer: new MemorySaver(),
|
|
142
|
+
langgraphConfig: { configurable: { thread_id: "thread-fixture" }, recursionLimit: 40 },
|
|
143
|
+
modelName: PRICING.model,
|
|
144
|
+
pricing: PRICING,
|
|
145
|
+
gate: options.gate ?? openGate(),
|
|
146
|
+
hasStructuredOutput: false,
|
|
147
|
+
};
|
|
148
|
+
const workspace = workspaceOver(options.files ?? {});
|
|
149
|
+
const graphInput: DeepAgentGraphInput = { kind: "message", input: { messages: [{ role: "user", content: "Say hello." }] } };
|
|
150
|
+
return {
|
|
151
|
+
sink,
|
|
152
|
+
engine,
|
|
153
|
+
streamEvents,
|
|
154
|
+
blobs,
|
|
155
|
+
run(run) {
|
|
156
|
+
streamEvents.mockResolvedValue(run);
|
|
157
|
+
const transcript = createDeepAgentTranscript(input, sink, engine, workspace);
|
|
158
|
+
return consumeDeepAgentStream({ input, sink, engine, graphInput, transcript });
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** One text turn with usage, as the graph streams it. */
|
|
164
|
+
function textTurn(runId: string, text: string, usage = { input_tokens: 100, output_tokens: 20 }): V3ProtocolEvent[] {
|
|
165
|
+
return [makeMessageStart(runId), makeTextDelta(runId, text), makeMessageFinish(runId, { usage })];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
beforeEach(() => resetSeq());
|
|
169
|
+
afterEach(() => vi.unstubAllEnvs());
|
|
170
|
+
|
|
171
|
+
describe("consumeDeepAgentStream — how the graph is invoked", () => {
|
|
172
|
+
it("calls streamEvents with the graph input and the runtime's config plus version v3 and its own abort signal", async () => {
|
|
173
|
+
const h = harness();
|
|
174
|
+
await h.run(scriptedRun(textTurn("run-1", "Hello.")));
|
|
175
|
+
|
|
176
|
+
expect(h.streamEvents).toHaveBeenCalledTimes(1);
|
|
177
|
+
const [input, config] = h.streamEvents.mock.calls[0] as [unknown, Record<string, unknown>];
|
|
178
|
+
expect(input).toEqual({ messages: [{ role: "user", content: "Say hello." }] });
|
|
179
|
+
expect(config.version).toBe("v3");
|
|
180
|
+
expect(config.configurable, "the runtime's thread id rides the config whole").toEqual({ thread_id: "thread-fixture" });
|
|
181
|
+
expect(config.recursionLimit).toBe(40);
|
|
182
|
+
expect(config.signal).toBeInstanceOf(AbortSignal);
|
|
183
|
+
expect((config.signal as AbortSignal).aborted, "a completed run was never aborted").toBe(false);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("consumeDeepAgentStream — what each event becomes", () => {
|
|
188
|
+
it("feeds every event through the normalizer into the transcript and completes with the run's output", async () => {
|
|
189
|
+
const h = harness();
|
|
190
|
+
const result = await h.run(
|
|
191
|
+
scriptedRun(
|
|
192
|
+
[...textTurn("run-1", "Reading the file."), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "contents")],
|
|
193
|
+
{ output: () => Promise.resolve({ messages: [], structuredResponse: { ok: true } }) },
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
expect(result.reason).toBe("completed");
|
|
198
|
+
expect(result.eventsProcessed).toBe(5);
|
|
199
|
+
expect(result.runOutput?.structuredResponse).toEqual({ ok: true });
|
|
200
|
+
const [message] = h.sink.status.messages;
|
|
201
|
+
expect(message.type).toBe(MessageType.MESSAGE_AI);
|
|
202
|
+
expect(message.content).toBe("Reading the file.");
|
|
203
|
+
expect(message.toolCalls[0].name).toBe("read_file");
|
|
204
|
+
expect(message.toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("tells the sink of activity once per event, naming the tool a tool_started carries", async () => {
|
|
208
|
+
const h = harness();
|
|
209
|
+
await h.run(scriptedRun([...textTurn("run-1", "x"), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "ok")]));
|
|
210
|
+
|
|
211
|
+
const details = h.sink.events.flatMap((e) => (e.kind === "activity" ? [e.detail] : []));
|
|
212
|
+
// One mark after the run starts, one per event (5), one after the output resolved.
|
|
213
|
+
expect(details).toHaveLength(7);
|
|
214
|
+
expect(details.filter((d) => d === "read_file"), "the tool's name is the stall watchdog's last detail").toHaveLength(1);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("reports usage per message_finish, priced at the engine's rates for the engine's model", async () => {
|
|
218
|
+
const h = harness();
|
|
219
|
+
await h.run(
|
|
220
|
+
scriptedRun([
|
|
221
|
+
...textTurn("run-1", "one", { input_tokens: 1_000, output_tokens: 100 }),
|
|
222
|
+
...textTurn("run-2", "two", { input_tokens: 2_000, output_tokens: 200 }),
|
|
223
|
+
]),
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const deltas = h.sink.usageDeltas;
|
|
227
|
+
expect(deltas).toHaveLength(2);
|
|
228
|
+
expect(deltas[0]).toMatchObject({ inputTokens: 1_000, outputTokens: 100, model: PRICING.model });
|
|
229
|
+
// 1,000 in at $1/M + 100 out at $5/M.
|
|
230
|
+
expect(deltas[0].estimatedCostUsd).toBeCloseTo(0.0015, 10);
|
|
231
|
+
expect(deltas[1].estimatedCostUsd).toBeCloseTo(0.003, 10);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("requests a persist on the shared cadence rule — a tool start forces one — and clears the force flag", async () => {
|
|
235
|
+
const h = harness();
|
|
236
|
+
await h.run(scriptedRun([...textTurn("run-1", "x"), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "ok")]));
|
|
237
|
+
|
|
238
|
+
expect(h.sink.persistRequests, "the tool start and the tool finish each force a persist").toBeGreaterThanOrEqual(2);
|
|
239
|
+
const order = h.sink.events.map((e) => e.kind);
|
|
240
|
+
expect(order.indexOf("persist"), "the first persist follows the events that forced it, never precedes them").toBeGreaterThan(0);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("publishes a file-modifying tool's target as an artifact on the status when the call finishes", async () => {
|
|
244
|
+
const h = harness({ files: { "src/main.ts": "console.log('hi');" } });
|
|
245
|
+
const result = await h.run(
|
|
246
|
+
scriptedRun([
|
|
247
|
+
...textTurn("run-1", "Writing."),
|
|
248
|
+
makeToolStarted("toolu_w", "write_file", { file_path: "src/main.ts", content: "console.log('hi');" }),
|
|
249
|
+
makeToolFinished("toolu_w", "written"),
|
|
250
|
+
]),
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
expect(result.pendingPublishPromises, "one publish fired mid-turn, for the settle to drain").toHaveLength(1);
|
|
254
|
+
await Promise.all(result.pendingPublishPromises);
|
|
255
|
+
expect(h.sink.status.artifacts.map((a) => a.sandboxPath)).toEqual(["src/main.ts"]);
|
|
256
|
+
expect([...h.blobs.keys()], "the bytes were uploaded under the execution's artifact key").toEqual(["artifacts/aex_fixture_0001/main.ts"]);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe("consumeDeepAgentStream — how the loop ends", () => {
|
|
261
|
+
it("ends awaiting_approval when the builder leaves a gated tool WAITING, without awaiting the run's output", async () => {
|
|
262
|
+
const policy: MergedToolPolicy = {
|
|
263
|
+
toolName: "dangerous_tool",
|
|
264
|
+
mcpServerSlug: "my-server",
|
|
265
|
+
requiresApproval: true,
|
|
266
|
+
approvalMessage: "Approve?",
|
|
267
|
+
source: "classifier_default",
|
|
268
|
+
};
|
|
269
|
+
const h = harness({
|
|
270
|
+
gate: openGate({ policies: new Map([["my-server/dangerous_tool", policy]]), toolServerMap: new Map([["dangerous_tool", "my-server"]]) }),
|
|
271
|
+
});
|
|
272
|
+
const neverResolves = new Promise<unknown>(() => undefined);
|
|
273
|
+
const result = await h.run(
|
|
274
|
+
scriptedRun([...textTurn("run-1", "Gated."), makeToolStarted("toolu_g", "dangerous_tool", { target: "prod" })], { output: () => neverResolves }),
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
expect(result.reason).toBe("awaiting_approval");
|
|
278
|
+
expect(result.runOutput).toBeUndefined();
|
|
279
|
+
expect(h.sink.status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("a stop before the first event settles interrupted without invoking the graph", async () => {
|
|
283
|
+
const h = harness();
|
|
284
|
+
h.sink.abort("stopped before start");
|
|
285
|
+
const result = await h.run(scriptedRun(textTurn("run-1", "never")));
|
|
286
|
+
|
|
287
|
+
expect(result.reason).toBe("interrupted");
|
|
288
|
+
expect(result.eventsProcessed).toBe(0);
|
|
289
|
+
expect(h.streamEvents).not.toHaveBeenCalled();
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("a stop mid-stream is taken at the NEXT event: the events before it count, the run's signal is aborted", async () => {
|
|
293
|
+
const h = harness();
|
|
294
|
+
const [start, delta, finish] = textTurn("run-1", "partial");
|
|
295
|
+
const result = await h.run(scriptedRun([start, delta, finish], { between: (yielded) => { if (yielded === 2) h.sink.abort("runtime stop"); } }));
|
|
296
|
+
|
|
297
|
+
expect(result.reason).toBe("interrupted");
|
|
298
|
+
expect(result.eventsProcessed, "start and delta were folded; finish arrived after the stop").toBe(2);
|
|
299
|
+
const [, config] = h.streamEvents.mock.calls[0] as [unknown, { signal: AbortSignal }];
|
|
300
|
+
expect(config.signal.aborted, "the graph run itself is aborted when the stop is taken").toBe(true);
|
|
301
|
+
expect(h.sink.status.messages[0].content, "what streamed before the stop is on the transcript").toBe("partial");
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("the engine's own error propagates when the runtime did not stop the turn", async () => {
|
|
305
|
+
const h = harness();
|
|
306
|
+
await expect(h.run(scriptedRun(textTurn("run-1", "x"), { failAfter: 1 }))).rejects.toThrow("engine exploded mid-stream");
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it("an error thrown after the runtime stopped the turn is the stop, not a failure", async () => {
|
|
310
|
+
const h = harness();
|
|
311
|
+
const result = await h.run(
|
|
312
|
+
scriptedRun(textTurn("run-1", "x"), { between: (yielded) => { if (yielded === 1) h.sink.abort("runtime stop"); }, failAfter: 1 }),
|
|
313
|
+
);
|
|
314
|
+
expect(result.reason).toBe("interrupted");
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it("refuses a stream that produced no events", async () => {
|
|
318
|
+
const h = harness();
|
|
319
|
+
await expect(h.run(scriptedRun([]))).rejects.toThrow(/Stream completed without processing any events/);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("a run.output that rejects is logged and the turn completes without a final state", async () => {
|
|
323
|
+
const h = harness();
|
|
324
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
|
325
|
+
try {
|
|
326
|
+
const result = await h.run(scriptedRun(textTurn("run-1", "x"), { output: () => Promise.reject(new Error("state never settled")) }));
|
|
327
|
+
expect(result.reason).toBe("completed");
|
|
328
|
+
expect(result.runOutput).toBeUndefined();
|
|
329
|
+
expect(warn.mock.calls.some((c) => String(c[0]).includes("run.output rejected"))).toBe(true);
|
|
330
|
+
} finally {
|
|
331
|
+
warn.mockRestore();
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Regression pins for stigmer#1008 (carried from the orchestrator's
|
|
336
|
+
// `streaming-v3.test.ts`, retired with its module; the fix on that module
|
|
337
|
+
// was stigmer#1092). The run.output bound must not leave its timer armed:
|
|
338
|
+
// a referenced timer holds the runner's event loop open after its worker
|
|
339
|
+
// has stopped, for the full Kubernetes termination grace. Faked timers
|
|
340
|
+
// here so `vi.getTimerCount()` can see what the loop left behind.
|
|
341
|
+
describe("the run.output bound leaves nothing armed", () => {
|
|
342
|
+
beforeEach(() => vi.useFakeTimers());
|
|
343
|
+
afterEach(() => vi.useRealTimers());
|
|
344
|
+
|
|
345
|
+
it("once run.output has resolved", async () => {
|
|
346
|
+
const h = harness();
|
|
347
|
+
const promise = h.run(scriptedRun(textTurn("run-1", "x")));
|
|
348
|
+
// Well short of the 30 s bound: a leaked timer would still be pending here.
|
|
349
|
+
await vi.advanceTimersByTimeAsync(1_000);
|
|
350
|
+
const result = await promise;
|
|
351
|
+
expect(result.runOutput).toBeDefined();
|
|
352
|
+
expect(vi.getTimerCount(), "the loop left a timer armed after completion").toBe(0);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it("when run.output never settles: the bound ends the wait, no final state, nothing armed", async () => {
|
|
356
|
+
const h = harness();
|
|
357
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
|
358
|
+
try {
|
|
359
|
+
const promise = h.run(scriptedRun(textTurn("run-1", "x"), { output: () => new Promise(() => undefined) }));
|
|
360
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
361
|
+
const result = await promise;
|
|
362
|
+
expect(result.reason).toBe("completed");
|
|
363
|
+
expect(result.runOutput).toBeUndefined();
|
|
364
|
+
expect(warn.mock.calls.some((c) => String(c[0]).includes("run.output did not resolve within 30000ms"))).toBe(true);
|
|
365
|
+
expect(vi.getTimerCount(), "the bound's own timer is cleared on expiry").toBe(0);
|
|
366
|
+
} finally {
|
|
367
|
+
warn.mockRestore();
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe("consumeDeepAgentStream — the event recorder", () => {
|
|
374
|
+
let dir: string;
|
|
375
|
+
beforeEach(() => { dir = mkdtempSync(join(tmpdir(), "v3-events-")); });
|
|
376
|
+
afterEach(() => rmSync(dir, { recursive: true, force: true }));
|
|
377
|
+
|
|
378
|
+
it("records nothing unless V3_EVENT_RECORD_DIR is set", async () => {
|
|
379
|
+
vi.stubEnv("V3_EVENT_RECORD_DIR", "");
|
|
380
|
+
const h = harness();
|
|
381
|
+
await h.run(scriptedRun(textTurn("run-1", "x")));
|
|
382
|
+
expect(readdirSync(dir)).toEqual([]);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("records every raw event to <dir>/<executionId>.v3-events.json and flushes it when the stream ends", async () => {
|
|
386
|
+
vi.stubEnv("V3_EVENT_RECORD_DIR", dir);
|
|
387
|
+
const h = harness();
|
|
388
|
+
await h.run(scriptedRun(textTurn("run-1", "x")));
|
|
389
|
+
expect(existsSync(join(dir, "aex_fixture_0001.v3-events.json"))).toBe(true);
|
|
390
|
+
});
|
|
391
|
+
});
|