@stigmer/runner 3.15.3-dev.20260914100347 → 3.15.3-dev.20260916211208
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 +1 -0
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/approval-contract/types.d.ts +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +61 -7
- package/dist/__test-utils__/hermetic-activity.js +100 -9
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +22 -3
- package/dist/__test-utils__/model-registry-fixture.js +22 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +14 -11
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +61 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +1 -1
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +52 -14
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +46 -12
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +21 -28
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -11
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +70 -26
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +82 -32
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +8 -7
- package/dist/activities/execute-cursor/adapter.js +13 -9
- package/dist/activities/execute-cursor/adapter.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +10 -10
- package/dist/activities/execute-cursor/approval-policy.js +12 -23
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +35 -1
- package/dist/activities/execute-cursor/approval-state.js +65 -0
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/{message-translator.d.ts → boundary-rows.d.ts} +45 -341
- package/dist/activities/execute-cursor/boundary-rows.js +1018 -0
- package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.js +1 -1
- package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +33 -14
- package/dist/activities/execute-cursor/cursor-event-recorder.js +43 -21
- package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-cursor/prompt-builder.js +4 -4
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/sdk-warmup.d.ts +15 -6
- package/dist/activities/execute-cursor/sdk-warmup.js +15 -6
- package/dist/activities/execute-cursor/sdk-warmup.js.map +1 -1
- package/dist/activities/execute-cursor/service-tier.js +1 -2
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +38 -59
- package/dist/activities/execute-cursor/session-lifecycle.js +59 -96
- package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
- package/dist/activities/execute-cursor/session-store.d.ts +100 -0
- package/dist/activities/execute-cursor/session-store.js +157 -0
- package/dist/activities/execute-cursor/session-store.js.map +1 -0
- package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
- package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
- package/dist/activities/execute-cursor/tool-result.js +130 -0
- package/dist/activities/execute-cursor/tool-result.js.map +1 -0
- package/dist/activities/execute-cursor/translator.d.ts +178 -0
- package/dist/activities/execute-cursor/translator.js +485 -0
- package/dist/activities/execute-cursor/translator.js.map +1 -0
- package/dist/activities/execute-cursor/turn-boundary.d.ts +15 -5
- package/dist/activities/execute-cursor/turn-boundary.js +10 -14
- 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 +47 -34
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +2 -2
- package/dist/activities/execute-cursor/turn-setup.js +5 -5
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +23 -14
- package/dist/activities/execute-cursor/turn-stream.js +41 -28
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.d.ts +4 -4
- package/dist/activities/execute-cursor/turn.js +5 -5
- package/dist/activities/execute-cursor/usage-pricing.d.ts +2 -2
- package/dist/activities/execute-cursor/usage-pricing.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +16 -11
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -10
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +12 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +18 -4
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +10 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +24 -11
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +1 -1
- package/dist/activities/execute-deep-agent/adapter.js +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +19 -19
- package/dist/activities/execute-deep-agent/approval-file-change.js +16 -15
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +2 -2
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +2 -2
- package/dist/activities/execute-deep-agent/hitl.d.ts +2 -2
- package/dist/activities/execute-deep-agent/hitl.js +2 -2
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +13 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js +3 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-deep-agent/prompt-builder.js +6 -7
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +16 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +20 -33
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +3 -3
- package/dist/activities/execute-deep-agent/subagent-transformer.js +1 -1
- package/dist/activities/execute-deep-agent/translator.d.ts +134 -0
- package/dist/activities/execute-deep-agent/translator.js +418 -0
- package/dist/activities/execute-deep-agent/translator.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +13 -7
- package/dist/activities/execute-deep-agent/turn-settle.js +34 -45
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +8 -8
- package/dist/activities/execute-deep-agent/turn-setup.js +7 -7
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +13 -10
- package/dist/activities/execute-deep-agent/turn-stream.js +44 -41
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn.d.ts +3 -3
- package/dist/activities/execute-deep-agent/turn.js +3 -3
- package/dist/config.d.ts +2 -2
- package/dist/harness/approval-decisions.d.ts +1 -1
- package/dist/harness/approval-decisions.js +1 -1
- package/dist/harness/capabilities.d.ts +21 -11
- package/dist/harness/capabilities.js +2 -2
- package/dist/harness/capture.d.ts +4 -4
- package/dist/harness/capture.js +4 -4
- package/dist/harness/persist-chokepoint.d.ts +3 -3
- package/dist/harness/persist-chokepoint.js +3 -3
- package/dist/harness/registry.d.ts +2 -2
- package/dist/harness/registry.js +2 -2
- package/dist/harness/run-turn.d.ts +6 -4
- package/dist/harness/run-turn.js +31 -9
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/stop-controller.d.ts +1 -1
- package/dist/harness/stop-controller.js +1 -1
- package/dist/harness/terminal-table.d.ts +7 -7
- package/dist/harness/terminal-table.js +7 -7
- package/dist/harness/transcript/builder.d.ts +182 -0
- package/dist/harness/transcript/builder.js +693 -0
- package/dist/harness/transcript/builder.js.map +1 -0
- package/dist/harness/transcript/events.d.ts +218 -0
- package/dist/harness/transcript/events.js +50 -0
- package/dist/harness/transcript/events.js.map +1 -0
- package/dist/harness/transcript/state.d.ts +110 -0
- package/dist/harness/transcript/state.js +148 -0
- package/dist/harness/transcript/state.js.map +1 -0
- package/dist/harness/turn-context.d.ts +54 -38
- package/dist/harness/turn-context.js +42 -43
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +63 -22
- package/dist/harness/types.js +12 -11
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage-accumulator.d.ts +2 -2
- package/dist/harness/usage-accumulator.js +2 -2
- package/dist/harness-adapters.d.ts +5 -4
- package/dist/harness-adapters.js +5 -4
- package/dist/harness-adapters.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +6 -0
- package/dist/middleware/approval-gate.js +7 -57
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +3 -3
- package/dist/middleware/cost-advisory.js +3 -3
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/runner-manager.js +1 -1
- package/dist/runner-manager.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +53 -0
- package/dist/shared/approval-policy.js +76 -0
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/args-preview.d.ts +45 -22
- package/dist/shared/args-preview.js +51 -41
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +4 -4
- package/dist/shared/attachment-resolver.js +4 -4
- package/dist/shared/attachment-vision.d.ts +2 -1
- package/dist/shared/attachment-vision.js.map +1 -1
- package/dist/shared/attachment-zip.d.ts +2 -2
- package/dist/shared/attachment-zip.js +2 -2
- package/dist/shared/cost-guard.d.ts +2 -2
- package/dist/shared/cost-guard.js +2 -2
- package/dist/shared/exact-apply.d.ts +1 -1
- package/dist/shared/exact-apply.js +1 -1
- package/dist/shared/execution-context.d.ts +2 -2
- package/dist/shared/execution-context.js +2 -2
- package/dist/shared/extract-structured-output.d.ts +2 -2
- package/dist/shared/extract-structured-output.js +2 -2
- package/dist/shared/filereview/cas-touched.d.ts +2 -2
- package/dist/shared/filereview/cas-touched.js +2 -2
- package/dist/shared/heartbeat.d.ts +1 -1
- package/dist/shared/heartbeat.js +1 -1
- package/dist/shared/llm-backend.d.ts +0 -4
- package/dist/shared/llm-backend.js +0 -4
- package/dist/shared/llm-backend.js.map +1 -1
- package/dist/shared/model-error.d.ts +1 -2
- package/dist/shared/model-error.js +1 -2
- package/dist/shared/model-error.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +18 -24
- package/dist/shared/persist-decision.js +19 -11
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/prompt-sections.d.ts +4 -4
- package/dist/shared/prompt-sections.js +4 -4
- package/dist/shared/skill-resolver.d.ts +3 -3
- package/dist/shared/skill-resolver.js +3 -3
- package/dist/shared/status-offload.d.ts +1 -1
- package/dist/shared/status-offload.js +2 -2
- package/dist/shared/status-offload.js.map +1 -1
- package/dist/shared/streaming-scheduler.d.ts +2 -7
- package/dist/shared/streaming-scheduler.js +6 -14
- package/dist/shared/streaming-scheduler.js.map +1 -1
- package/dist/shared/subagent-rows.d.ts +2 -2
- package/dist/shared/subagent-rows.js +2 -2
- package/dist/shared/todos.d.ts +3 -3
- package/dist/shared/todos.js +3 -3
- package/dist/shared/tool-row.d.ts +19 -1
- package/dist/shared/tool-row.js +36 -2
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/worker-shutdown.d.ts +1 -1
- package/dist/shared/worker-shutdown.js +1 -1
- package/dist/shared/workspace/session-provision.d.ts +1 -1
- package/dist/shared/workspace/session-provision.js +1 -1
- package/dist/shared/workspace/sources/empty.d.ts +1 -1
- package/dist/shared/workspace/sources/empty.js +1 -2
- package/dist/shared/workspace/sources/empty.js.map +1 -1
- package/dist/shared/workspace/sources/git.js +4 -4
- package/dist/shared/workspace/sources/git.js.map +1 -1
- package/dist/shared/workspace/sources/local-path.js +6 -6
- package/dist/shared/workspace/sources/local-path.js.map +1 -1
- package/dist/shared/workspace/stigmer-link.d.ts +1 -1
- package/dist/shared/workspace/stigmer-link.js +1 -1
- package/dist/shared/workspace/types.d.ts +2 -5
- package/dist/shared/workspace/types.js +0 -6
- package/dist/shared/workspace/types.js.map +1 -1
- package/dist/shared/workspace/writeback-coordinator.d.ts +17 -4
- package/dist/shared/workspace/writeback-coordinator.js +7 -9
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/package.json +5 -5
- package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +70 -0
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +35 -1
- package/src/__test-utils__/approval-contract/contract.ts +1 -1
- package/src/__test-utils__/approval-contract/types.ts +1 -1
- package/src/__test-utils__/harness-boot-order-child.ts +1 -1
- package/src/__test-utils__/harness-contract/contract.ts +8 -8
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +52 -16
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +47 -43
- package/src/__test-utils__/hermetic-activity.ts +113 -9
- package/src/__test-utils__/model-registry-fixture.ts +31 -7
- package/src/__test-utils__/module-specifiers.ts +32 -3
- package/src/__tests__/harness-boot-order.test.ts +1 -1
- package/src/__tests__/harness-contract.test.ts +1 -1
- package/src/__tests__/runner-manager.test.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +32 -8
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +12 -10
- package/src/activities/execute-cursor/__test-utils__/fold.ts +116 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +72 -19
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +35 -29
- package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +94 -38
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/approval-state.test.ts +14 -21
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/cursor-baseurl-routing.test.ts +10 -8
- package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
- package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +24 -12
- package/src/activities/execute-cursor/__tests__/cursor-generate-image-live.test.ts +7 -2
- package/src/activities/execute-cursor/__tests__/cursor-hook-protocol-live.test.ts +163 -0
- package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +23 -20
- package/src/activities/execute-cursor/__tests__/cursor-transcript-live.test.ts +298 -0
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +4 -2
- package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.status.json +71 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +73 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +109 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +119 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +68 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +67 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +10 -7
- package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +146 -0
- package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +8 -5
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +6 -2
- package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +4 -1
- package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +6 -2
- package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +122 -0
- package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +276 -0
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +12 -9
- package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +196 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +145 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +4 -1
- package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +165 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +7 -4
- package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +138 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +130 -0
- package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +17 -2
- package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +43 -60
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +23 -28
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +5 -5
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +11 -13
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +8 -11
- package/src/activities/execute-cursor/__tests__/session-lifecycle.test.ts +86 -58
- package/src/activities/execute-cursor/__tests__/session-store.test.ts +220 -0
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +8 -22
- package/src/activities/execute-cursor/__tests__/translator.test.ts +594 -0
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +8 -5
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +87 -63
- package/src/activities/execute-cursor/adapter.ts +13 -9
- package/src/activities/execute-cursor/approval-policy.ts +12 -24
- package/src/activities/execute-cursor/approval-state.ts +66 -1
- package/src/activities/execute-cursor/boundary-rows.ts +1132 -0
- package/src/activities/execute-cursor/cursor-capabilities.ts +1 -1
- package/src/activities/execute-cursor/cursor-event-recorder.ts +57 -28
- package/src/activities/execute-cursor/fetch-interceptor.ts +1 -1
- package/src/activities/execute-cursor/http2-interceptor.ts +1 -1
- package/src/activities/execute-cursor/prompt-builder.ts +6 -6
- package/src/activities/execute-cursor/sdk-warmup.ts +15 -6
- package/src/activities/execute-cursor/service-tier.ts +1 -2
- package/src/activities/execute-cursor/session-lifecycle.ts +63 -109
- package/src/activities/execute-cursor/session-store.ts +187 -0
- package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
- package/src/activities/execute-cursor/tool-result.ts +128 -0
- package/src/activities/execute-cursor/translator.ts +541 -0
- package/src/activities/execute-cursor/turn-boundary.ts +21 -14
- package/src/activities/execute-cursor/turn-settle.ts +46 -34
- package/src/activities/execute-cursor/turn-setup.ts +5 -5
- package/src/activities/execute-cursor/turn-stream.ts +49 -46
- package/src/activities/execute-cursor/turn.ts +5 -5
- package/src/activities/execute-cursor/usage-pricing.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +23 -11
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +1 -1
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +2 -3
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +25 -4
- package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +25 -11
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +6 -17
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +25 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +2 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +4 -14
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +4 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +109 -76
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +3 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +92 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +9 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +7 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +10 -11
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +4 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +9 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +21 -13
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +7 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +28 -12
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +21 -21
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +35 -30
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +3 -4
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +12 -10
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +13 -3
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +26 -18
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/{subagent-tracker.test.ts → translator-subagents.test.ts} +76 -57
- package/src/activities/execute-deep-agent/__tests__/{v3-status-builder.test.ts → translator-through-builder.test.ts} +213 -299
- package/src/activities/execute-deep-agent/__tests__/translator.test.ts +505 -0
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +11 -29
- package/src/activities/execute-deep-agent/adapter.ts +1 -1
- package/src/activities/execute-deep-agent/approval-file-change.ts +20 -22
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +2 -2
- package/src/activities/execute-deep-agent/hitl.ts +2 -2
- package/src/activities/execute-deep-agent/inline-publisher.ts +16 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +6 -7
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +22 -31
- package/src/activities/execute-deep-agent/subagent-transformer.ts +3 -3
- package/src/activities/execute-deep-agent/translator.ts +463 -0
- package/src/activities/execute-deep-agent/turn-settle.ts +35 -43
- package/src/activities/execute-deep-agent/turn-setup.ts +8 -8
- package/src/activities/execute-deep-agent/turn-stream.ts +53 -51
- package/src/activities/execute-deep-agent/turn.ts +3 -3
- package/src/config.ts +2 -2
- package/src/harness/README.md +335 -0
- package/src/harness/__tests__/approval-decisions.test.ts +2 -2
- package/src/harness/__tests__/capture.test.ts +3 -3
- package/src/harness/__tests__/import-direction.test.ts +3 -2
- package/src/harness/__tests__/mount-skills.test.ts +4 -1
- package/src/harness/__tests__/readme-index.test.ts +339 -0
- package/src/harness/__tests__/run-turn.test.ts +131 -6
- package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
- package/src/harness/__tests__/transcript-writers.test.ts +191 -0
- package/src/harness/__tests__/turn-attachments-vision.test.ts +5 -2
- package/src/harness/__tests__/turn-context.test.ts +5 -5
- package/src/harness/approval-decisions.ts +1 -1
- package/src/harness/capabilities.ts +21 -11
- package/src/harness/capture.ts +4 -4
- package/src/harness/persist-chokepoint.ts +3 -3
- package/src/harness/registry.ts +2 -2
- package/src/harness/run-turn.ts +33 -9
- package/src/harness/stop-controller.ts +1 -1
- package/src/harness/terminal-table.ts +7 -7
- package/src/harness/transcript/__tests__/builder.test.ts +975 -0
- package/src/harness/transcript/__tests__/state.test.ts +143 -0
- package/src/harness/transcript/builder.ts +755 -0
- package/src/harness/transcript/events.ts +262 -0
- package/src/harness/transcript/state.ts +167 -0
- package/src/harness/turn-context.ts +61 -46
- package/src/harness/types.ts +64 -22
- package/src/harness/usage-accumulator.ts +2 -2
- package/src/harness-adapters.ts +5 -4
- package/src/middleware/__tests__/cost-advisory.test.ts +2 -2
- package/src/middleware/approval-gate.ts +7 -74
- package/src/middleware/cost-advisory.ts +3 -3
- package/src/middleware/index.ts +1 -1
- package/src/runner-manager.ts +1 -1
- package/src/shared/__tests__/approval-policy.test.ts +45 -0
- package/src/shared/__tests__/args-preview.test.ts +40 -20
- package/src/shared/__tests__/attachment-naming.test.ts +1 -1
- package/src/shared/__tests__/attachment-resolver.test.ts +5 -5
- package/src/shared/__tests__/attachment-zip.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +1 -1
- package/src/shared/__tests__/cost-guard.test.ts +1 -1
- package/src/shared/__tests__/exact-apply.test.ts +2 -1
- package/src/shared/__tests__/persist-decision.test.ts +19 -33
- package/src/shared/__tests__/prompt-sections.test.ts +1 -1
- package/src/shared/__tests__/stamp-flowed-rows.test.ts +1 -1
- package/src/shared/__tests__/status-offload.test.ts +1 -1
- package/src/shared/__tests__/streaming-scheduler.test.ts +8 -9
- package/src/shared/__tests__/todos.test.ts +1 -1
- package/src/shared/__tests__/tool-row.test.ts +1 -1
- package/src/shared/approval-policy.ts +95 -0
- package/src/shared/args-preview.ts +51 -42
- package/src/shared/attachment-resolver.ts +4 -4
- package/src/shared/attachment-vision.ts +2 -1
- package/src/shared/attachment-zip.ts +2 -2
- package/src/shared/cost-guard.ts +2 -2
- package/src/shared/exact-apply.ts +1 -1
- package/src/shared/execution-context.ts +2 -2
- package/src/shared/extract-structured-output.ts +2 -2
- package/src/shared/filereview/__tests__/capture.test.ts +9 -5
- package/src/shared/filereview/__tests__/git-substrate.test.ts +4 -1
- package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +3 -3
- package/src/shared/filereview/cas-touched.ts +2 -2
- package/src/shared/heartbeat.ts +1 -1
- package/src/shared/llm-backend.ts +0 -4
- package/src/shared/model-error.ts +1 -2
- package/src/shared/persist-decision.ts +19 -28
- package/src/shared/prompt-sections.ts +4 -4
- package/src/shared/skill-resolver.ts +3 -3
- package/src/shared/status-offload.ts +2 -2
- package/src/shared/streaming-scheduler.ts +8 -13
- package/src/shared/subagent-rows.ts +2 -2
- package/src/shared/todos.ts +3 -3
- package/src/shared/tool-row.ts +38 -2
- package/src/shared/worker-shutdown.ts +1 -1
- package/src/shared/workspace/__tests__/git-source.test.ts +3 -3
- package/src/shared/workspace/__tests__/provisioner.test.ts +5 -5
- package/src/shared/workspace/__tests__/session-provision.test.ts +2 -2
- package/src/shared/workspace/__tests__/writeback-coordinator.integration.test.ts +8 -9
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +25 -25
- package/src/shared/workspace/provisioner.ts +1 -1
- package/src/shared/workspace/session-provision.ts +1 -1
- package/src/shared/workspace/sources/empty.ts +2 -2
- package/src/shared/workspace/sources/git.ts +3 -4
- package/src/shared/workspace/sources/local-path.ts +5 -6
- package/src/shared/workspace/stigmer-link.ts +1 -1
- package/src/shared/workspace/types.ts +2 -5
- package/src/shared/workspace/writeback-coordinator.ts +23 -12
- package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
- package/dist/activities/execute-cursor/delta-enricher.js +0 -265
- package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
- package/dist/activities/execute-cursor/message-translator.js +0 -2040
- package/dist/activities/execute-cursor/message-translator.js.map +0 -1
- package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
- package/dist/activities/execute-cursor/todo-tracker.js +0 -80
- package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
- package/dist/activities/execute-deep-agent/execution-state.js +0 -68
- package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
- package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
- package/dist/activities/execute-deep-agent/v3-events.js +0 -35
- package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
- package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
- package/dist/shared/execution-status-writer.d.ts +0 -31
- package/dist/shared/execution-status-writer.js +0 -43
- package/dist/shared/execution-status-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
- package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
- package/src/activities/execute-cursor/delta-enricher.ts +0 -307
- package/src/activities/execute-cursor/message-translator.ts +0 -2319
- package/src/activities/execute-cursor/todo-tracker.ts +0 -91
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
- package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
- package/src/activities/execute-deep-agent/execution-state.ts +0 -78
- package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
- package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
- package/src/activities/execute-deep-agent/v3-events.ts +0 -153
- package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
- package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
- package/src/shared/execution-status-writer.ts +0 -56
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unit tests for
|
|
2
|
+
* Unit tests for the local agent's create/resume options and the
|
|
3
|
+
* transport-recovery wrapper (`session-lifecycle.ts`).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The SDK module is a `vi.fn` stub so the assertions read the exact options
|
|
6
|
+
* the adapter hands `Agent.create` / `Agent.resume`. The SDK's sqlite entry is
|
|
7
|
+
* NOT mocked here on purpose: `createAgent` opens the session's REAL
|
|
8
|
+
* `SqliteLocalAgentStore` (`node:sqlite`, no network) under a temp workspace
|
|
9
|
+
* volume, so this file is also where the store the runner ships with is
|
|
10
|
+
* proven to open, be reused, and dispose — the hermetic goldens double it.
|
|
11
|
+
* The store's keying and lifetime rules have their own arms in
|
|
12
|
+
* `session-store.test.ts`.
|
|
8
13
|
*/
|
|
9
14
|
|
|
10
15
|
import { describe, it, expect, afterEach, vi } from "vitest";
|
|
@@ -20,13 +25,15 @@ vi.mock("@cursor/sdk", () => ({
|
|
|
20
25
|
}));
|
|
21
26
|
|
|
22
27
|
import { Agent } from "@cursor/sdk";
|
|
28
|
+
import type { AgentOptions } from "@cursor/sdk";
|
|
29
|
+
import { SqliteLocalAgentStore } from "@cursor/sdk/sqlite";
|
|
23
30
|
import {
|
|
24
|
-
resolvePlatformOptions,
|
|
25
31
|
createAgent,
|
|
26
32
|
resumeAgent,
|
|
27
33
|
resolveAgentWithTransportRecovery,
|
|
28
34
|
} from "../session-lifecycle.js";
|
|
29
35
|
import type { CreateAgentOptions } from "../session-lifecycle.js";
|
|
36
|
+
import { releaseAllSessionStores } from "../session-store.js";
|
|
30
37
|
|
|
31
38
|
const tempRoots: string[] = [];
|
|
32
39
|
|
|
@@ -36,50 +43,25 @@ function freshWorkspaceRoot(): string {
|
|
|
36
43
|
return dir;
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
afterEach(() => {
|
|
46
|
+
afterEach(async () => {
|
|
47
|
+
// Release every store before its directory goes, so the sqlite handles are
|
|
48
|
+
// closed when the temp roots are removed (and no test inherits a store).
|
|
49
|
+
await releaseAllSessionStores();
|
|
40
50
|
for (const dir of tempRoots.splice(0)) {
|
|
41
51
|
rmSync(dir, { recursive: true, force: true });
|
|
42
52
|
}
|
|
43
53
|
});
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const opts = resolvePlatformOptions("ses-123", workspaceRootDir);
|
|
49
|
-
|
|
50
|
-
expect(opts.stateRoot).toBe(
|
|
51
|
-
join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-123"),
|
|
52
|
-
);
|
|
53
|
-
expect(opts.stateRoot.startsWith(workspaceRootDir)).toBe(true);
|
|
54
|
-
// Created eagerly to prevent ENOENT on first SDK write.
|
|
55
|
-
expect(existsSync(opts.stateRoot!)).toBe(true);
|
|
56
|
-
expect(opts.workspaceRef).toBe("stigmer-session:ses-123");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("isolates two sessions sharing one workspace volume into distinct stores", () => {
|
|
60
|
-
const workspaceRootDir = freshWorkspaceRoot();
|
|
61
|
-
const a = resolvePlatformOptions("ses-aaa", workspaceRootDir);
|
|
62
|
-
const b = resolvePlatformOptions("ses-bbb", workspaceRootDir);
|
|
63
|
-
|
|
64
|
-
expect(a.stateRoot).not.toBe(b.stateRoot);
|
|
65
|
-
expect(a.workspaceRef).not.toBe(b.workspaceRef);
|
|
66
|
-
// Both live under the same shared volume but in session-keyed subdirs.
|
|
67
|
-
expect(a.stateRoot!.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
|
|
68
|
-
expect(b.stateRoot!.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("throws on an empty sessionId (would collide across sessions on a shared volume)", () => {
|
|
72
|
-
const workspaceRootDir = freshWorkspaceRoot();
|
|
73
|
-
expect(() => resolvePlatformOptions("", workspaceRootDir)).toThrow(/sessionId is required/);
|
|
74
|
-
});
|
|
55
|
+
function lastCreateOptions(): AgentOptions {
|
|
56
|
+
return vi.mocked(Agent.create).mock.calls.at(-1)![0];
|
|
57
|
+
}
|
|
75
58
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
59
|
+
function lastResumeCall(): [string, Partial<AgentOptions> | undefined] {
|
|
60
|
+
return vi.mocked(Agent.resume).mock.calls.at(-1)! as [string, Partial<AgentOptions> | undefined];
|
|
61
|
+
}
|
|
80
62
|
|
|
81
63
|
// ---------------------------------------------------------------------------
|
|
82
|
-
//
|
|
64
|
+
// The local options across create/resume
|
|
83
65
|
//
|
|
84
66
|
// Regression: Agent.resume() does not persist local.cwd. When resumeAgent()
|
|
85
67
|
// omitted it, the SDK fell back to process.cwd() — re-rooting the resumed
|
|
@@ -87,17 +69,33 @@ describe("resolvePlatformOptions", () => {
|
|
|
87
69
|
// setting source (the .cursor/hooks.json carrying the HITL approval hook)
|
|
88
70
|
// from that wrong directory. Result: on every resumed turn, file edits and
|
|
89
71
|
// shell commands ran unguarded with no approval card (observed in production
|
|
90
|
-
// execution aex_01ktr5na07f5xtmn0dz3mfjtdp).
|
|
72
|
+
// execution aex_01ktr5na07f5xtmn0dz3mfjtdp). The same rule now covers the
|
|
73
|
+
// store (#1053): a resume without it would look the agent up in a default
|
|
74
|
+
// store derived from cwd, not the one the session's records are in.
|
|
91
75
|
// ---------------------------------------------------------------------------
|
|
92
76
|
|
|
93
|
-
describe("
|
|
77
|
+
describe("local options on create/resume", () => {
|
|
94
78
|
const baseOptions = {
|
|
95
79
|
apiKey: "key",
|
|
96
80
|
sessionId: "ses-cwd-test",
|
|
97
81
|
model: "gpt-test",
|
|
98
82
|
};
|
|
99
83
|
|
|
100
|
-
it("createAgent passes the single workspace dir as local.cwd", async () => {
|
|
84
|
+
it("createAgent passes the single workspace dir as local.cwd, with no dirs", async () => {
|
|
85
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
86
|
+
await createAgent({
|
|
87
|
+
...baseOptions,
|
|
88
|
+
workspaceDirs: ["/work/repo-a"],
|
|
89
|
+
workspaceRootDir,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { local } = lastCreateOptions();
|
|
93
|
+
expect(local?.cwd).toBe("/work/repo-a");
|
|
94
|
+
expect(local).not.toHaveProperty("dirs");
|
|
95
|
+
expect(local?.settingSources).toContain("project");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("createAgent opens the session's real SQLite store under the workspace volume and passes it as local.store", async () => {
|
|
101
99
|
const workspaceRootDir = freshWorkspaceRoot();
|
|
102
100
|
await createAgent({
|
|
103
101
|
...baseOptions,
|
|
@@ -105,13 +103,37 @@ describe("workspace binding on create/resume", () => {
|
|
|
105
103
|
workspaceRootDir,
|
|
106
104
|
});
|
|
107
105
|
|
|
108
|
-
const
|
|
109
|
-
expect(
|
|
110
|
-
|
|
106
|
+
const store = lastCreateOptions().local?.store;
|
|
107
|
+
expect(store).toBeInstanceOf(SqliteLocalAgentStore);
|
|
108
|
+
const sqlite = store as SqliteLocalAgentStore;
|
|
109
|
+
expect(sqlite.workspaceRef).toBe("stigmer-session:ses-cwd-test");
|
|
110
|
+
expect(sqlite.stateRoot).toBe(join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-cwd-test"));
|
|
111
|
+
// The SDK's layout lands where the runner said, not under $HOME.
|
|
112
|
+
expect(existsSync(sqlite.stateRoot)).toBe(true);
|
|
111
113
|
});
|
|
112
114
|
|
|
113
|
-
it("
|
|
115
|
+
it("createAgent pins the SDK's own retries off (the runner is the retry authority)", async () => {
|
|
114
116
|
const workspaceRootDir = freshWorkspaceRoot();
|
|
117
|
+
await createAgent({
|
|
118
|
+
...baseOptions,
|
|
119
|
+
workspaceDirs: ["/work/repo-a"],
|
|
120
|
+
workspaceRootDir,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// 1.0.31 defaults this to true for headless embedders; an absent field
|
|
124
|
+
// would silently stack the SDK's transport retries under the runner's.
|
|
125
|
+
expect(lastCreateOptions().local?.enableAgentRetries).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("resumeAgent re-supplies cwd, settingSources, store and the retry pin (nothing under local survives Agent.resume)", async () => {
|
|
129
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
130
|
+
await createAgent({
|
|
131
|
+
...baseOptions,
|
|
132
|
+
workspaceDirs: ["/work/repo-a"],
|
|
133
|
+
workspaceRootDir,
|
|
134
|
+
});
|
|
135
|
+
const createdWith = lastCreateOptions().local?.store;
|
|
136
|
+
|
|
115
137
|
await resumeAgent({
|
|
116
138
|
...baseOptions,
|
|
117
139
|
agentId: "agent-123",
|
|
@@ -119,25 +141,31 @@ describe("workspace binding on create/resume", () => {
|
|
|
119
141
|
workspaceRootDir,
|
|
120
142
|
});
|
|
121
143
|
|
|
122
|
-
const [agentId, callOptions] =
|
|
144
|
+
const [agentId, callOptions] = lastResumeCall();
|
|
123
145
|
expect(agentId).toBe("agent-123");
|
|
124
|
-
// The load-bearing
|
|
125
|
-
// process.cwd() and the project HITL hook never loads on resumed turns
|
|
126
|
-
|
|
127
|
-
expect(callOptions
|
|
146
|
+
// The load-bearing assertions: without cwd the SDK re-roots the agent at
|
|
147
|
+
// process.cwd() and the project HITL hook never loads on resumed turns;
|
|
148
|
+
// without the SAME store it looks the agent up somewhere else.
|
|
149
|
+
expect(callOptions?.local?.cwd).toBe("/work/repo-a");
|
|
150
|
+
expect(callOptions?.local?.settingSources).toContain("project");
|
|
151
|
+
expect(callOptions?.local?.store).toBe(createdWith);
|
|
152
|
+
expect(callOptions?.local?.enableAgentRetries).toBe(false);
|
|
128
153
|
});
|
|
129
154
|
|
|
130
|
-
it("
|
|
155
|
+
it("passes a multi-root workspace as cwd (the first dir) plus dirs (the rest)", async () => {
|
|
131
156
|
const workspaceRootDir = freshWorkspaceRoot();
|
|
132
157
|
await resumeAgent({
|
|
133
158
|
...baseOptions,
|
|
134
159
|
agentId: "agent-456",
|
|
135
|
-
workspaceDirs: ["/work/repo-a", "/work/repo-b"],
|
|
160
|
+
workspaceDirs: ["/work/repo-a", "/work/repo-b", "/work/repo-c"],
|
|
136
161
|
workspaceRootDir,
|
|
137
162
|
});
|
|
138
163
|
|
|
139
|
-
const callOptions =
|
|
140
|
-
|
|
164
|
+
const [, callOptions] = lastResumeCall();
|
|
165
|
+
// The SDK merges cwd-first with duplicates dropped, so this is the array
|
|
166
|
+
// the SDK took whole at 1.0.13, in the same order.
|
|
167
|
+
expect(callOptions?.local?.cwd).toBe("/work/repo-a");
|
|
168
|
+
expect(callOptions?.local?.dirs).toEqual(["/work/repo-b", "/work/repo-c"]);
|
|
141
169
|
});
|
|
142
170
|
});
|
|
143
171
|
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for `session-store.ts`: where a session's Cursor SDK store lives,
|
|
3
|
+
* and the lifetime the runner owns for it (stigmer/stigmer#1053).
|
|
4
|
+
*
|
|
5
|
+
* The location rules are correctness-critical: the state root is keyed by
|
|
6
|
+
* sessionId and rooted at the durable workspace volume so native
|
|
7
|
+
* Agent.resume() survives restart/snapshot-restore and so sessions that share
|
|
8
|
+
* one volume (a workflow sandbox's child agent executions) never collide.
|
|
9
|
+
*
|
|
10
|
+
* The lifetime rules are what a revert of the adapter's release hooks would
|
|
11
|
+
* break: one open per session however many activities ask, the SAME instance
|
|
12
|
+
* on every ask, a release that disposes and forgets so the next ask reopens, a
|
|
13
|
+
* failed open that is not remembered, and a re-acquire under a different root
|
|
14
|
+
* that releases the store it held. `SessionStores` takes the opener, so these
|
|
15
|
+
* run against a recording fake and no SQLite file.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
19
|
+
import { mkdtempSync, rmSync, existsSync } from "node:fs";
|
|
20
|
+
import { tmpdir } from "node:os";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
import { SessionStores, resolveSessionStoreLocation, type ReleasableStore, type SessionStoreLocation } from "../session-store.js";
|
|
24
|
+
|
|
25
|
+
const tempRoots: string[] = [];
|
|
26
|
+
|
|
27
|
+
function freshWorkspaceRoot(): string {
|
|
28
|
+
const dir = mkdtempSync(join(tmpdir(), "stigmer-session-store-test-"));
|
|
29
|
+
tempRoots.push(dir);
|
|
30
|
+
return dir;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
for (const dir of tempRoots.splice(0)) {
|
|
35
|
+
rmSync(dir, { recursive: true, force: true });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("resolveSessionStoreLocation", () => {
|
|
40
|
+
it("derives the state root under the workspace volume (not $HOME), created eagerly", () => {
|
|
41
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
42
|
+
const location = resolveSessionStoreLocation("ses-123", workspaceRootDir);
|
|
43
|
+
|
|
44
|
+
expect(location.stateRoot).toBe(join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-123"));
|
|
45
|
+
expect(location.stateRoot.startsWith(workspaceRootDir)).toBe(true);
|
|
46
|
+
// Created eagerly to prevent ENOENT on the SDK's first write.
|
|
47
|
+
expect(existsSync(location.stateRoot)).toBe(true);
|
|
48
|
+
expect(location.workspaceRef).toBe("stigmer-session:ses-123");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("isolates two sessions sharing one workspace volume into distinct stores", () => {
|
|
52
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
53
|
+
const a = resolveSessionStoreLocation("ses-aaa", workspaceRootDir);
|
|
54
|
+
const b = resolveSessionStoreLocation("ses-bbb", workspaceRootDir);
|
|
55
|
+
|
|
56
|
+
expect(a.stateRoot).not.toBe(b.stateRoot);
|
|
57
|
+
expect(a.workspaceRef).not.toBe(b.workspaceRef);
|
|
58
|
+
expect(a.stateRoot.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
|
|
59
|
+
expect(b.stateRoot.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("throws on an empty sessionId (would collide across sessions on a shared volume)", () => {
|
|
63
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
64
|
+
expect(() => resolveSessionStoreLocation("", workspaceRootDir)).toThrow(/sessionId is required/);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("throws on an empty workspaceRootDir (state must live on the durable volume)", () => {
|
|
68
|
+
expect(() => resolveSessionStoreLocation("ses-123", "")).toThrow(/workspaceRootDir is required/);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// The lifetime
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
class FakeStore implements ReleasableStore {
|
|
77
|
+
disposeCalls = 0;
|
|
78
|
+
constructor(readonly location: SessionStoreLocation) {}
|
|
79
|
+
get stateRoot(): string {
|
|
80
|
+
return this.location.stateRoot;
|
|
81
|
+
}
|
|
82
|
+
async dispose(): Promise<void> {
|
|
83
|
+
this.disposeCalls++;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A recording opener; `failNext` makes the next open reject once. */
|
|
88
|
+
function recordingOpener() {
|
|
89
|
+
const opened: FakeStore[] = [];
|
|
90
|
+
let failNext: Error | undefined;
|
|
91
|
+
const open = async (location: SessionStoreLocation): Promise<FakeStore> => {
|
|
92
|
+
if (failNext) {
|
|
93
|
+
const err = failNext;
|
|
94
|
+
failNext = undefined;
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
const store = new FakeStore(location);
|
|
98
|
+
opened.push(store);
|
|
99
|
+
return store;
|
|
100
|
+
};
|
|
101
|
+
return { open, opened, fail: (err: Error) => (failNext = err) };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
describe("SessionStores", () => {
|
|
105
|
+
it("opens once per session and hands the same instance to every later acquire, concurrent ones included", async () => {
|
|
106
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
107
|
+
const { open, opened } = recordingOpener();
|
|
108
|
+
const stores = new SessionStores(open);
|
|
109
|
+
|
|
110
|
+
// Two activities racing on one session (the agent cache's documented race).
|
|
111
|
+
const [a, b] = await Promise.all([
|
|
112
|
+
stores.acquire("ses-1", workspaceRootDir),
|
|
113
|
+
stores.acquire("ses-1", workspaceRootDir),
|
|
114
|
+
]);
|
|
115
|
+
const c = await stores.acquire("ses-1", workspaceRootDir);
|
|
116
|
+
|
|
117
|
+
expect(opened).toHaveLength(1);
|
|
118
|
+
expect(a).toBe(b);
|
|
119
|
+
expect(b).toBe(c);
|
|
120
|
+
expect(a.location.workspaceRef).toBe("stigmer-session:ses-1");
|
|
121
|
+
expect(stores.size).toBe(1);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("keeps one store per session, not one per process", async () => {
|
|
125
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
126
|
+
const { open, opened } = recordingOpener();
|
|
127
|
+
const stores = new SessionStores(open);
|
|
128
|
+
|
|
129
|
+
const a = await stores.acquire("ses-a", workspaceRootDir);
|
|
130
|
+
const b = await stores.acquire("ses-b", workspaceRootDir);
|
|
131
|
+
|
|
132
|
+
expect(opened).toHaveLength(2);
|
|
133
|
+
expect(a).not.toBe(b);
|
|
134
|
+
expect(stores.size).toBe(2);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("release disposes the session's store and forgets it, so a later acquire reopens", async () => {
|
|
138
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
139
|
+
const { open, opened } = recordingOpener();
|
|
140
|
+
const stores = new SessionStores(open);
|
|
141
|
+
|
|
142
|
+
const first = await stores.acquire("ses-1", workspaceRootDir);
|
|
143
|
+
await stores.release("ses-1");
|
|
144
|
+
|
|
145
|
+
expect(first.disposeCalls).toBe(1);
|
|
146
|
+
expect(stores.size).toBe(0);
|
|
147
|
+
|
|
148
|
+
const second = await stores.acquire("ses-1", workspaceRootDir);
|
|
149
|
+
expect(second).not.toBe(first);
|
|
150
|
+
expect(opened).toHaveLength(2);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("release of a session with no store is a no-op", async () => {
|
|
154
|
+
const { open, opened } = recordingOpener();
|
|
155
|
+
const stores = new SessionStores(open);
|
|
156
|
+
|
|
157
|
+
await expect(stores.release("ses-unknown")).resolves.toBeUndefined();
|
|
158
|
+
expect(opened).toHaveLength(0);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("releaseAll disposes every held store and empties the map (worker shutdown)", async () => {
|
|
162
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
163
|
+
const { open, opened } = recordingOpener();
|
|
164
|
+
const stores = new SessionStores(open);
|
|
165
|
+
|
|
166
|
+
await stores.acquire("ses-a", workspaceRootDir);
|
|
167
|
+
await stores.acquire("ses-b", workspaceRootDir);
|
|
168
|
+
await stores.releaseAll();
|
|
169
|
+
|
|
170
|
+
expect(opened.map((s) => s.disposeCalls)).toEqual([1, 1]);
|
|
171
|
+
expect(stores.size).toBe(0);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("does not remember a failed open: the next acquire retries", async () => {
|
|
175
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
176
|
+
const { open, opened, fail } = recordingOpener();
|
|
177
|
+
const stores = new SessionStores(open);
|
|
178
|
+
|
|
179
|
+
fail(new Error("disk full"));
|
|
180
|
+
await expect(stores.acquire("ses-1", workspaceRootDir)).rejects.toThrow("disk full");
|
|
181
|
+
expect(stores.size).toBe(0);
|
|
182
|
+
|
|
183
|
+
const store = await stores.acquire("ses-1", workspaceRootDir);
|
|
184
|
+
expect(opened).toEqual([store]);
|
|
185
|
+
expect(stores.size).toBe(1);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("a re-acquire under a different workspace volume releases the held store and opens the new one", async () => {
|
|
189
|
+
const rootA = freshWorkspaceRoot();
|
|
190
|
+
const rootB = freshWorkspaceRoot();
|
|
191
|
+
const { open, opened } = recordingOpener();
|
|
192
|
+
const stores = new SessionStores(open);
|
|
193
|
+
|
|
194
|
+
const onA = await stores.acquire("ses-1", rootA);
|
|
195
|
+
const onB = await stores.acquire("ses-1", rootB);
|
|
196
|
+
|
|
197
|
+
// The handle for the old binding can never serve the new one (the same
|
|
198
|
+
// rule the agent cache applies to a fingerprint mismatch).
|
|
199
|
+
expect(onB).not.toBe(onA);
|
|
200
|
+
expect(onA.disposeCalls).toBe(1);
|
|
201
|
+
expect(onB.stateRoot.startsWith(rootB)).toBe(true);
|
|
202
|
+
expect(opened).toHaveLength(2);
|
|
203
|
+
expect(stores.size).toBe(1);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("a dispose that throws is swallowed: the store is forgotten either way", async () => {
|
|
207
|
+
const workspaceRootDir = freshWorkspaceRoot();
|
|
208
|
+
const stores = new SessionStores(async (location) => {
|
|
209
|
+
const store = new FakeStore(location);
|
|
210
|
+
store.dispose = async () => {
|
|
211
|
+
throw new Error("handle already closed");
|
|
212
|
+
};
|
|
213
|
+
return store;
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
await stores.acquire("ses-1", workspaceRootDir);
|
|
217
|
+
await expect(stores.release("ses-1")).resolves.toBeUndefined();
|
|
218
|
+
expect(stores.size).toBe(0);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* shape) is guarded in shared/__tests__/status-offload.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { describe, it, expect
|
|
26
|
+
import { describe, it, expect } from "vitest";
|
|
27
27
|
import { create } from "@bufbuild/protobuf";
|
|
28
28
|
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
29
29
|
import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
@@ -33,13 +33,8 @@ import {
|
|
|
33
33
|
offloadOversizedToolOutputs,
|
|
34
34
|
detectImagePayload,
|
|
35
35
|
} from "../../../shared/status-offload.js";
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
canonicalizeImageResult,
|
|
39
|
-
buildToolCallProto,
|
|
40
|
-
MessageAccumulator,
|
|
41
|
-
} from "../message-translator.js";
|
|
42
|
-
import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
36
|
+
import { toResultString, canonicalizeImageResult } from "../tool-result.js";
|
|
37
|
+
import { foldCursorEvents } from "../__test-utils__/fold.js";
|
|
43
38
|
|
|
44
39
|
// PNG signature + a little payload. PNG_BYTES is how the Cursor SDK delivers
|
|
45
40
|
// image data at runtime (Node Buffer-JSON); PNG_BASE64 is its base64 form, used
|
|
@@ -143,7 +138,7 @@ describe("toResultString", () => {
|
|
|
143
138
|
});
|
|
144
139
|
});
|
|
145
140
|
|
|
146
|
-
describe("
|
|
141
|
+
describe("stream row image normalization (through the translator and the builder)", () => {
|
|
147
142
|
it("produces a result the shared offload detector recognizes as an image", () => {
|
|
148
143
|
const event = {
|
|
149
144
|
type: "tool_call",
|
|
@@ -156,7 +151,7 @@ describe("buildToolCallProto image normalization", () => {
|
|
|
156
151
|
result: cursorImageEnvelope(),
|
|
157
152
|
} as unknown as Extract<SDKMessage, { type: "tool_call" }>;
|
|
158
153
|
|
|
159
|
-
const tc =
|
|
154
|
+
const tc = foldCursorEvents([event]).rows()[0];
|
|
160
155
|
expect(tc.name).toBe("get_app_state");
|
|
161
156
|
const img = detectImagePayload(tc.result);
|
|
162
157
|
expect(img).not.toBeNull();
|
|
@@ -188,7 +183,7 @@ describe("cursor image flows through the persist-time offload", () => {
|
|
|
188
183
|
result: cursorImageEnvelope(),
|
|
189
184
|
} as unknown as Extract<SDKMessage, { type: "tool_call" }>;
|
|
190
185
|
|
|
191
|
-
const tc =
|
|
186
|
+
const tc = foldCursorEvents([event]).rows()[0];
|
|
192
187
|
const status = create(AgentExecutionStatusSchema, {
|
|
193
188
|
messages: [create(AgentMessageSchema, { toolCalls: [tc] })],
|
|
194
189
|
});
|
|
@@ -207,11 +202,8 @@ describe("cursor image flows through the persist-time offload", () => {
|
|
|
207
202
|
});
|
|
208
203
|
});
|
|
209
204
|
|
|
210
|
-
describe("sub-agent image normalization (
|
|
205
|
+
describe("sub-agent image normalization (sub-agent-steps)", () => {
|
|
211
206
|
it("normalizes a screenshot returned inside a sub-agent toolCall step", () => {
|
|
212
|
-
const messages: AgentMessage[] = [];
|
|
213
|
-
const acc = new MessageAccumulator(messages);
|
|
214
|
-
|
|
215
207
|
const running = {
|
|
216
208
|
type: "tool_call",
|
|
217
209
|
agent_id: "a1",
|
|
@@ -221,9 +213,6 @@ describe("sub-agent image normalization (extractConversationSteps)", () => {
|
|
|
221
213
|
status: "running",
|
|
222
214
|
args: { description: "screenshot", prompt: "capture" },
|
|
223
215
|
} as unknown as Extract<SDKMessage, { type: "tool_call" }>;
|
|
224
|
-
acc.processEvent(running);
|
|
225
|
-
acc.trackSubAgentExecution(running);
|
|
226
|
-
|
|
227
216
|
const completed = {
|
|
228
217
|
type: "tool_call",
|
|
229
218
|
agent_id: "a1",
|
|
@@ -254,10 +243,7 @@ describe("sub-agent image normalization (extractConversationSteps)", () => {
|
|
|
254
243
|
},
|
|
255
244
|
} as unknown as Extract<SDKMessage, { type: "tool_call" }>;
|
|
256
245
|
|
|
257
|
-
|
|
258
|
-
acc.trackSubAgentExecution(completed);
|
|
259
|
-
|
|
260
|
-
const sub = acc.subAgentExecutions[0];
|
|
246
|
+
const sub = foldCursorEvents([running, completed]).status.subAgentExecutions[0];
|
|
261
247
|
const subToolResult = sub.messages[0].toolCalls[0].result;
|
|
262
248
|
const img = detectImagePayload(subToolResult);
|
|
263
249
|
expect(img?.base64).toBe(PNG_BASE64);
|