@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
|
@@ -5,14 +5,18 @@
|
|
|
5
5
|
* sub-agent tracking, the first-denial early stop — and the loop's side of the adapter contract: progress reported per event
|
|
6
6
|
* and per delta, usage reported priced, the persist awaited, and the runtime's
|
|
7
7
|
* stop signal honoured at every event boundary and inside a blocked pull by
|
|
8
|
-
* cancelling the SDK run. Since
|
|
8
|
+
* cancelling the SDK run. Since #1070 the loop no longer decides WHY it
|
|
9
9
|
* stopped (stall, cost cap, pause, platform stop are the runtime's evidence;
|
|
10
10
|
* `harness/__tests__/run-turn.test.ts` proves that table); it reports
|
|
11
11
|
* `completed`, `first-denial` or `interrupted`.
|
|
12
12
|
*
|
|
13
13
|
* The loop is driven with a structural `mockRun` (an async-iterable `.stream()`)
|
|
14
14
|
* and the kit's `RecordingTurnSink`, so it runs without the live Cursor SDK or
|
|
15
|
-
* Temporal — mirroring the deep-agent `streaming.test.ts` pattern.
|
|
15
|
+
* Temporal — mirroring the deep-agent `streaming.test.ts` pattern. The
|
|
16
|
+
* transcript side is the REAL pair the loop runs in production — the Cursor
|
|
17
|
+
* translator into the shared `TranscriptBuilder` over `sink.status` (#1097;
|
|
18
|
+
* until then a stubbed accumulator counted calls) — so what these arms read
|
|
19
|
+
* back are rows, not mock invocations.
|
|
16
20
|
*/
|
|
17
21
|
|
|
18
22
|
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
@@ -20,7 +24,11 @@ import { mkdtemp, writeFile, rm } from "node:fs/promises";
|
|
|
20
24
|
import { tmpdir } from "node:os";
|
|
21
25
|
import { join } from "node:path";
|
|
22
26
|
import type { SDKMessage } from "@cursor/sdk";
|
|
27
|
+
import { ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
23
28
|
import { RecordingTurnSink } from "../../../__test-utils__/harness-contract/recording-sink.js";
|
|
29
|
+
import type { TranscriptBuilder } from "../../../harness/transcript/builder.js";
|
|
30
|
+
import { sdkEvents } from "../__test-utils__/scripted-agent.js";
|
|
31
|
+
import { CursorTranslator } from "../translator.js";
|
|
24
32
|
import {
|
|
25
33
|
consumeCursorTurnStream,
|
|
26
34
|
makeCursorTurnOnDelta,
|
|
@@ -30,10 +38,11 @@ import {
|
|
|
30
38
|
type TurnStreamState,
|
|
31
39
|
} from "../turn-stream.js";
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
/** The SDK's real event shapes, bound to one run, so the translator folds them as production would. */
|
|
42
|
+
const sdk = sdkEvents("agent-test", "run-test");
|
|
43
|
+
/** A `status` event whose `message` is deliberately NOT a string — the oss#299 shape the loop must not crash on. */
|
|
44
|
+
function statusWithStructuredMessage(): SDKMessage {
|
|
45
|
+
return { type: "status", agent_id: "agent-test", run_id: "run-test", status: "ERROR", message: { code: 14 } } as unknown as SDKMessage;
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
async function* asyncIter(events: SDKMessage[]): AsyncIterable<SDKMessage> {
|
|
@@ -52,27 +61,8 @@ function mockRun(events: SDKMessage[]): MockRun {
|
|
|
52
61
|
};
|
|
53
62
|
}
|
|
54
63
|
|
|
55
|
-
function
|
|
56
|
-
return {
|
|
57
|
-
processEvent: vi.fn(),
|
|
58
|
-
trackSubAgentExecution: vi.fn(),
|
|
59
|
-
finalize: vi.fn(),
|
|
60
|
-
markPersisted: vi.fn(),
|
|
61
|
-
cancelInProgressSubAgents: vi.fn(),
|
|
62
|
-
isDirty: true,
|
|
63
|
-
subAgentExecutions: [],
|
|
64
|
-
...overrides,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function stubEnricher() {
|
|
69
|
-
return {
|
|
70
|
-
processDelta: vi.fn(),
|
|
71
|
-
applyEnrichments: vi.fn(),
|
|
72
|
-
finalize: vi.fn(),
|
|
73
|
-
markPersisted: vi.fn(),
|
|
74
|
-
isDirty: false,
|
|
75
|
-
};
|
|
64
|
+
function translatorFor(sink: RecordingTurnSink): CursorTranslator {
|
|
65
|
+
return new CursorTranslator({ policies: new Map(), leases: { global: false, categories: new Set() }, seeded: sink.status.messages });
|
|
76
66
|
}
|
|
77
67
|
|
|
78
68
|
/** Prices nothing: hands the counts back as a delta with a stated cost, so the sink sees a priced delta. */
|
|
@@ -84,71 +74,104 @@ interface BuiltDeps {
|
|
|
84
74
|
deps: CursorTurnStreamDeps;
|
|
85
75
|
state: TurnStreamState;
|
|
86
76
|
sink: RecordingTurnSink;
|
|
87
|
-
|
|
77
|
+
transcript: TranscriptBuilder;
|
|
88
78
|
}
|
|
89
79
|
|
|
90
80
|
function buildDeps(overrides: Partial<CursorTurnStreamDeps> = {}): BuiltDeps {
|
|
91
81
|
const state = overrides.state ?? newTurnStreamState();
|
|
92
82
|
const sink = (overrides.sink as RecordingTurnSink | undefined) ?? new RecordingTurnSink();
|
|
93
|
-
|
|
83
|
+
// The builder is the sink's, as the runtime hands it (#1097).
|
|
84
|
+
const transcript = sink.transcript;
|
|
94
85
|
|
|
95
86
|
const deps = {
|
|
96
87
|
// TurnOnDeltaDeps
|
|
97
88
|
sink,
|
|
98
89
|
usagePricer: stubUsagePricer(),
|
|
99
|
-
|
|
90
|
+
translator: translatorFor(sink),
|
|
91
|
+
eventRecorder: undefined,
|
|
100
92
|
promptEstimatedTokens: 100,
|
|
101
93
|
executionId: "exec-test",
|
|
102
94
|
state,
|
|
103
95
|
// CursorTurnStreamDeps
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
eventRecorder: undefined,
|
|
107
|
-
// contentDirty (accumulator.isDirty) forces the persist, so shouldSendUpdate
|
|
108
|
-
// is never consulted; markUpdateSent must still exist.
|
|
96
|
+
// A tool row's start forces the persist (the builder's flag), so a text-only
|
|
97
|
+
// stream rides this scheduler, which never says yes; markUpdateSent must exist.
|
|
109
98
|
scheduler: { shouldSendUpdate: () => false, markUpdateSent: vi.fn() },
|
|
110
99
|
hitlDir: undefined,
|
|
111
100
|
...overrides,
|
|
112
101
|
} as unknown as CursorTurnStreamDeps;
|
|
113
102
|
|
|
114
|
-
return { deps, state, sink,
|
|
103
|
+
return { deps, state, sink, transcript };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Every root row the loop folded into the sink's status. */
|
|
107
|
+
function rows(sink: RecordingTurnSink) {
|
|
108
|
+
return sink.status.messages.flatMap((m) => m.toolCalls);
|
|
115
109
|
}
|
|
116
110
|
|
|
117
111
|
describe("consumeCursorTurnStream", () => {
|
|
118
|
-
it("
|
|
119
|
-
const { deps, state, sink
|
|
112
|
+
it("folds every event into the sink's status through the translator and the builder, persists live, and returns 'completed' on a natural end", async () => {
|
|
113
|
+
const { deps, state, sink } = buildDeps();
|
|
120
114
|
|
|
121
|
-
const reason = await consumeCursorTurnStream(
|
|
115
|
+
const reason = await consumeCursorTurnStream(
|
|
116
|
+
mockRun([sdk.assistant("Reading."), sdk.toolCall("c1", "read", "running", { path: "a" }), sdk.toolCall("c1", "read", "completed", { path: "a" }, "text")]),
|
|
117
|
+
deps,
|
|
118
|
+
);
|
|
122
119
|
|
|
123
120
|
expect(reason).toBe("completed");
|
|
124
|
-
expect(
|
|
121
|
+
expect(sink.status.messages.map((m) => [m.content, m.toolCalls.map((tc) => tc.id)])).toEqual([["Reading.", ["c1"]]]);
|
|
122
|
+
expect(rows(sink)[0].result).toBe("text");
|
|
125
123
|
// The #1 retry gap: the bare loop never persisted mid-stream. This proves the
|
|
126
|
-
// shared loop persists live — through the runtime's chokepoint
|
|
127
|
-
|
|
128
|
-
expect(
|
|
124
|
+
// shared loop persists live — through the runtime's chokepoint — on the
|
|
125
|
+
// builder's discrete-change flag (a row's start and its finish).
|
|
126
|
+
expect(sink.persistRequests).toBe(2);
|
|
127
|
+
expect(sink.transcript.dirty, "the flag is cleared after each persist").toBe(false);
|
|
128
|
+
expect(state.eventCount).toBe(3);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("drains the delta channel's queued facts after the stream event, never before it — and the delta's completion instant stands", async () => {
|
|
132
|
+
const { deps, sink } = buildDeps();
|
|
133
|
+
const onDelta = makeCursorTurnOnDelta(deps);
|
|
134
|
+
const withDeltaBetween: StreamableRun = {
|
|
135
|
+
stream: async function* () {
|
|
136
|
+
yield sdk.toolCall("sh-1", "shell", "running", { command: "make" });
|
|
137
|
+
onDelta({ update: { type: "shell-output-delta", event: { callId: "sh-1", type: "stdout", data: "building\n" } } });
|
|
138
|
+
onDelta({ update: { type: "tool-call-completed", callId: "sh-1", modelCallId: "m", toolCall: { type: "shell", args: { command: "make" }, result: { status: "success", value: { exitCode: 0, signal: "", stdout: "building\n", stderr: "", executionTime: 1 } } } } });
|
|
139
|
+
yield sdk.assistant("Built.");
|
|
140
|
+
},
|
|
141
|
+
supports: () => true,
|
|
142
|
+
cancel: async () => {},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
await consumeCursorTurnStream(withDeltaBetween, deps);
|
|
146
|
+
|
|
147
|
+
const row = rows(sink)[0];
|
|
148
|
+
expect(row.result, "the output reached the row at the next stream event").toBe("building\n");
|
|
149
|
+
expect(row.status).toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
|
|
150
|
+
expect(row.completedAt, "stamped at the delta's observed instant").not.toBe("");
|
|
129
151
|
});
|
|
130
152
|
|
|
131
153
|
it("reports progress per event, naming the tool of a tool_call event (the stall copy's `last tool`)", async () => {
|
|
132
154
|
const { deps, sink } = buildDeps();
|
|
133
155
|
|
|
134
|
-
await consumeCursorTurnStream(mockRun([
|
|
156
|
+
await consumeCursorTurnStream(mockRun([sdk.assistant("Go."), sdk.toolCall("c1", "shell", "running", { command: "ls" })]), deps);
|
|
135
157
|
|
|
136
158
|
const marks = sink.events.filter((e) => e.kind === "activity");
|
|
137
159
|
expect(marks.map((m) => (m.kind === "activity" ? m.detail : undefined))).toEqual([undefined, "shell"]);
|
|
138
160
|
});
|
|
139
161
|
|
|
140
162
|
it("tracks a sub-agent delegation (the 'task' tool call) — dropped by the old bare retry loop", async () => {
|
|
141
|
-
const { deps,
|
|
163
|
+
const { deps, sink } = buildDeps();
|
|
142
164
|
|
|
143
|
-
await consumeCursorTurnStream(mockRun([
|
|
165
|
+
await consumeCursorTurnStream(mockRun([sdk.toolCall("t1", "task", "running", { subagentType: "helper", description: "Look", prompt: "Look at it" })]), deps);
|
|
144
166
|
|
|
145
|
-
expect(
|
|
167
|
+
expect(sink.status.subAgentExecutions.map((s) => [s.id, s.name])).toEqual([["t1", "helper"]]);
|
|
168
|
+
expect(rows(sink).map((tc) => tc.id)).toEqual(["t1"]);
|
|
146
169
|
});
|
|
147
170
|
|
|
148
171
|
it("captures a stream ERROR status message onto state.streamErrorMessage", async () => {
|
|
149
172
|
const { deps, state } = buildDeps();
|
|
150
173
|
|
|
151
|
-
await consumeCursorTurnStream(mockRun([
|
|
174
|
+
await consumeCursorTurnStream(mockRun([sdk.status("ERROR", "boom")]), deps);
|
|
152
175
|
|
|
153
176
|
expect(state.streamErrorMessage).toBe("boom");
|
|
154
177
|
});
|
|
@@ -158,7 +181,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
158
181
|
// crash classifyText downstream (.toLowerCase() on a non-string).
|
|
159
182
|
const { deps, state } = buildDeps();
|
|
160
183
|
|
|
161
|
-
await consumeCursorTurnStream(mockRun([
|
|
184
|
+
await consumeCursorTurnStream(mockRun([statusWithStructuredMessage()]), deps);
|
|
162
185
|
|
|
163
186
|
expect(state.streamErrorMessage).toBeUndefined();
|
|
164
187
|
});
|
|
@@ -174,7 +197,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
174
197
|
hitlDir = await mkdtemp(join(tmpdir(), "turn-stream-denial-"));
|
|
175
198
|
await writeFile(join(hitlDir, "denials.jsonl"), JSON.stringify({ toolName: "shell", token: "tok-1" }) + "\n", "utf-8");
|
|
176
199
|
const { deps, state } = buildDeps({ hitlDir });
|
|
177
|
-
const run = mockRun([
|
|
200
|
+
const run = mockRun([sdk.toolCall("c1", "shell", "running", { command: "rm -rf build" })]);
|
|
178
201
|
|
|
179
202
|
const reason = await consumeCursorTurnStream(run, deps);
|
|
180
203
|
|
|
@@ -189,7 +212,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
189
212
|
await writeFile(join(hitlDir, "denials.jsonl"), "", "utf-8");
|
|
190
213
|
const { deps, state } = buildDeps({ hitlDir });
|
|
191
214
|
|
|
192
|
-
const reason = await consumeCursorTurnStream(mockRun([
|
|
215
|
+
const reason = await consumeCursorTurnStream(mockRun([sdk.toolCall("c1", "shell", "running", { command: "ls" })]), deps);
|
|
193
216
|
|
|
194
217
|
expect(reason).toBe("completed");
|
|
195
218
|
expect(state.firstDenialDetected).toBe(false);
|
|
@@ -200,25 +223,25 @@ describe("consumeCursorTurnStream", () => {
|
|
|
200
223
|
it("a signal aborted before the stream starts: the run is cancelled and nothing is processed", async () => {
|
|
201
224
|
const sink = new RecordingTurnSink();
|
|
202
225
|
sink.abort("cost-cap");
|
|
203
|
-
const { deps
|
|
204
|
-
const run = mockRun([
|
|
226
|
+
const { deps } = buildDeps({ sink });
|
|
227
|
+
const run = mockRun([sdk.assistant("never folded")]);
|
|
205
228
|
|
|
206
229
|
const reason = await consumeCursorTurnStream(run, deps);
|
|
207
230
|
|
|
208
231
|
expect(reason).toBe("interrupted");
|
|
209
232
|
expect(run.cancel).toHaveBeenCalledTimes(1);
|
|
210
|
-
expect(
|
|
233
|
+
expect(sink.status.messages).toHaveLength(0);
|
|
211
234
|
});
|
|
212
235
|
|
|
213
236
|
it("an abort between events: the run is cancelled at once and the next event is never processed", async () => {
|
|
214
237
|
const sink = new RecordingTurnSink();
|
|
215
|
-
const { deps
|
|
238
|
+
const { deps } = buildDeps({ sink });
|
|
216
239
|
// The realistic shape: the runtime aborts (a turn-ended delta crossed the
|
|
217
240
|
// cap, a STOP came back from a persist) while the loop is between events.
|
|
218
241
|
async function* gen(): AsyncIterable<SDKMessage> {
|
|
219
|
-
yield
|
|
242
|
+
yield sdk.assistant("first");
|
|
220
243
|
sink.abort("platform-stop");
|
|
221
|
-
yield
|
|
244
|
+
yield sdk.assistant(" second");
|
|
222
245
|
}
|
|
223
246
|
const run: MockRun = { stream: () => gen(), supports: () => true, cancel: vi.fn(async () => {}) };
|
|
224
247
|
|
|
@@ -226,8 +249,8 @@ describe("consumeCursorTurnStream", () => {
|
|
|
226
249
|
|
|
227
250
|
expect(reason).toBe("interrupted");
|
|
228
251
|
expect(run.cancel).toHaveBeenCalledTimes(1);
|
|
229
|
-
// Event 1 was
|
|
230
|
-
expect(
|
|
252
|
+
// Event 1 was folded; event 2 hit the boundary check.
|
|
253
|
+
expect(sink.status.messages.map((m) => m.content)).toEqual(["first"]);
|
|
231
254
|
});
|
|
232
255
|
|
|
233
256
|
it("an abort while the pull is blocked (a wedged stream): the cancel is what unblocks it", async () => {
|
|
@@ -238,7 +261,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
238
261
|
// watchdog aborts.
|
|
239
262
|
let unblock: (() => void) | undefined;
|
|
240
263
|
async function* gen(): AsyncIterable<SDKMessage> {
|
|
241
|
-
yield
|
|
264
|
+
yield sdk.assistant("first");
|
|
242
265
|
await new Promise<void>((resolve) => {
|
|
243
266
|
unblock = resolve;
|
|
244
267
|
});
|
|
@@ -266,7 +289,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
266
289
|
// The break exits the for-await, which invokes the iterator's return();
|
|
267
290
|
// a cancelled SDK run can reject there. The catch must exempt a stopped
|
|
268
291
|
// turn's teardown exactly like the first-denial teardown.
|
|
269
|
-
const events = [
|
|
292
|
+
const events = [sdk.assistant("first")];
|
|
270
293
|
let i = 0;
|
|
271
294
|
const run: MockRun = {
|
|
272
295
|
stream: () => ({
|
|
@@ -293,7 +316,7 @@ describe("consumeCursorTurnStream", () => {
|
|
|
293
316
|
it("rethrows a genuine stream failure when nothing stopped the turn", async () => {
|
|
294
317
|
const { deps } = buildDeps();
|
|
295
318
|
async function* gen(): AsyncIterable<SDKMessage> {
|
|
296
|
-
yield
|
|
319
|
+
yield sdk.assistant("first");
|
|
297
320
|
throw new Error("transport reset");
|
|
298
321
|
}
|
|
299
322
|
const run: MockRun = { stream: () => gen(), supports: () => true, cancel: vi.fn(async () => {}) };
|
|
@@ -311,7 +334,8 @@ describe("makeCursorTurnOnDelta", () => {
|
|
|
311
334
|
const onDelta = makeCursorTurnOnDelta({
|
|
312
335
|
sink,
|
|
313
336
|
usagePricer: usagePricer as never,
|
|
314
|
-
|
|
337
|
+
translator: translatorFor(sink),
|
|
338
|
+
eventRecorder: undefined,
|
|
315
339
|
promptEstimatedTokens: 10,
|
|
316
340
|
executionId: "e",
|
|
317
341
|
state,
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* module boots, releases, and delegates.
|
|
6
6
|
*
|
|
7
7
|
* What this adapter owns: the proxy interceptors and the parked-agent cache
|
|
8
|
-
* (worker lifetime), the parked agent per session (session
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* (worker lifetime), the parked agent and the SDK store per session (session
|
|
9
|
+
* lifetime; `agent-session-cache.ts`, `session-store.ts`), and one engine turn
|
|
10
|
+
* (`runTurn`, through `turn.ts`). Everything else about a turn is the
|
|
11
|
+
* runtime's (`harness/run-turn.ts`).
|
|
11
12
|
*
|
|
12
13
|
* THIS MODULE'S STATIC GRAPH IS SDK-FREE, ON PURPOSE. The composition roots
|
|
13
14
|
* import it (through `src/harness-adapters.ts`) BEFORE they boot it, and
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
* The interceptors read the proxy credential from `Config.proxyTokenRef` per
|
|
28
29
|
* request; which credential that is (the static root's control-plane token,
|
|
29
30
|
* the manager's minted runner token) is the root's decision, not this
|
|
30
|
-
* module's
|
|
31
|
+
* module's.
|
|
31
32
|
*
|
|
32
33
|
* What this adapter never does: throw out of `runTurn` (an SDK failure is
|
|
33
34
|
* `failed` with the classifier's sentence; an unexpected exception is
|
|
@@ -39,14 +40,14 @@
|
|
|
39
40
|
*
|
|
40
41
|
* The turn boundary (`turn-boundary.ts`) runs inside `turn.ts` and reads
|
|
41
42
|
* this harness's deny-and-retry evidence — the denial ledger — into WAITING
|
|
42
|
-
* rows and settled rows. The file-review capture is NOT here since
|
|
43
|
+
* rows and settled rows. The file-review capture is NOT here since #1096:
|
|
43
44
|
* the runtime pins the baseline before this adapter runs and captures the
|
|
44
45
|
* whole turn's tree after it returns (`harness/capture.ts`); what this
|
|
45
46
|
* adapter contributes is the hook sidecar it binds as the runtime's CAS
|
|
46
47
|
* observations (`turn-setup.ts` `installGate`).
|
|
47
48
|
*
|
|
48
|
-
* Extracted from `index.ts` `createCursorActivities`
|
|
49
|
-
* the turn body
|
|
49
|
+
* Extracted from `index.ts` `createCursorActivities` in #1070, which also
|
|
50
|
+
* split it from the turn body. The seventeen hermetic goldens under
|
|
50
51
|
* `__tests__/hermetic/` pin the result byte for byte.
|
|
51
52
|
*/
|
|
52
53
|
|
|
@@ -57,6 +58,7 @@ import { closeAllCachedAgents, evictSessionAgent } from "./agent-session-cache.j
|
|
|
57
58
|
import { CURSOR_CAPABILITIES } from "./cursor-capabilities.js";
|
|
58
59
|
import { installFetchInterceptor } from "./fetch-interceptor.js";
|
|
59
60
|
import { assertHttp2ConnectPatched, installHttp2Interceptor } from "./http2-interceptor.js";
|
|
61
|
+
import { releaseAllSessionStores, releaseSessionStore } from "./session-store.js";
|
|
60
62
|
import type { CursorAdapterConfig } from "./turn-setup.js";
|
|
61
63
|
|
|
62
64
|
/** The config slice this adapter reads per turn, taken at `boot`; a whole `Config` satisfies it. */
|
|
@@ -120,14 +122,16 @@ export function createCursorAdapter(): HarnessAdapter {
|
|
|
120
122
|
booted = { config: resolveCursorConfig(bootConfig), runCursorTurn };
|
|
121
123
|
},
|
|
122
124
|
|
|
123
|
-
/** Close every parked agent (their executor leases and MCP subprocesses). */
|
|
125
|
+
/** Close every parked agent (their executor leases and MCP subprocesses), then every session's SDK store. */
|
|
124
126
|
async shutdown(): Promise<void> {
|
|
125
127
|
closeAllCachedAgents();
|
|
128
|
+
await releaseAllSessionStores();
|
|
126
129
|
},
|
|
127
130
|
|
|
128
|
-
/** The session is done on this host: close the agent parked for it, if any (#215). */
|
|
131
|
+
/** The session is done on this host: close the agent parked for it, if any (#215), then its SDK store (#1053). */
|
|
129
132
|
async releaseSession(sessionId: string): Promise<void> {
|
|
130
133
|
evictSessionAgent(sessionId);
|
|
134
|
+
await releaseSessionStore(sessionId);
|
|
131
135
|
},
|
|
132
136
|
|
|
133
137
|
async runTurn(input: TurnInput, sink: TurnSink): Promise<TurnOutcome> {
|
|
@@ -29,6 +29,7 @@ export {
|
|
|
29
29
|
resolveApprovalMessage,
|
|
30
30
|
POLICY_ENGINE_VERSION,
|
|
31
31
|
} from "../../shared/approval-policy.js";
|
|
32
|
+
import { CATEGORY_APPROVAL_MESSAGE } from "../../shared/approval-policy.js";
|
|
32
33
|
export type { MergedToolPolicy, PolicySource } from "../../shared/approval-policy.js";
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -72,30 +73,15 @@ export type ApprovalCategory = ToolApprovalCategory;
|
|
|
72
73
|
export const approvalCategory = toolApprovalCategory;
|
|
73
74
|
|
|
74
75
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* the
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
76
|
+
* The salient argument fields — the resource a built-in acts on — are the
|
|
77
|
+
* platform's one list, `shared/args-preview.ts` `SALIENT_ARG_FIELDS` (moved
|
|
78
|
+
* there in #1097: the transcript builder previews every row over it for
|
|
79
|
+
* both harnesses). Re-exported here for this harness's identity code and the
|
|
80
|
+
* generated hook script, which inject it so the runner and the hook never
|
|
81
|
+
* disagree on which field to match.
|
|
81
82
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
delete: "Delete: {{args.path}}",
|
|
85
|
-
shell: "Run command: {{args.command}}",
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Top-level tool-argument fields, in priority order, that identify the specific
|
|
90
|
-
* resource a built-in tool acts on. The list deliberately spans BOTH taxonomies'
|
|
91
|
-
* arg shapes: the hook input names a file `file_path` and the stream names it
|
|
92
|
-
* `path`; both name a shell command `command`. Extracting the same resource
|
|
93
|
-
* VALUE on both sides (the absolute path / the command string) is what lets the
|
|
94
|
-
* hook-recorded denial token equal the stream-computed token. Authored here once
|
|
95
|
-
* and injected into the generated preToolUse hook script so the runner and the
|
|
96
|
-
* hook never disagree on which field to match.
|
|
97
|
-
*/
|
|
98
|
-
export const SALIENT_ARG_FIELDS = ["file_path", "path", "target_notebook", "command"] as const;
|
|
83
|
+
export { SALIENT_ARG_FIELDS } from "../../shared/args-preview.js";
|
|
84
|
+
import { SALIENT_ARG_FIELDS } from "../../shared/args-preview.js";
|
|
99
85
|
|
|
100
86
|
/**
|
|
101
87
|
* Check whether a built-in (non-MCP) Cursor tool requires user approval.
|
|
@@ -152,7 +138,9 @@ export function getBuiltInGatedCategories(): Array<[string, ApprovalCategory]> {
|
|
|
152
138
|
* Approval-message template for a gated built-in tool (either taxonomy), or
|
|
153
139
|
* undefined when the tool is not gated. Resolved via {@link approvalCategory}
|
|
154
140
|
* so stream-side names (`edit`/`shell`/`delete`) and hook-side names
|
|
155
|
-
* (`Write`/`Shell`/`Delete`) both map to the same template
|
|
141
|
+
* (`Write`/`Shell`/`Delete`) both map to the same template — the platform's
|
|
142
|
+
* ONE table, `shared/approval-policy.ts` `CATEGORY_APPROVAL_MESSAGE`, shared
|
|
143
|
+
* with the native gate since #1097. Callers resolve the
|
|
156
144
|
* placeholders against the tool args via resolveApprovalMessage.
|
|
157
145
|
*/
|
|
158
146
|
export function getBuiltInApprovalMessage(toolName: string): string | undefined {
|
|
@@ -87,7 +87,7 @@ import { create } from "@bufbuild/protobuf";
|
|
|
87
87
|
import { ApprovalAction, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
88
88
|
import { PendingApprovalSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
89
89
|
import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
90
|
-
import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
90
|
+
import type { AgentMessage, ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
91
91
|
import type { MergedToolPolicy, ApprovalCategory } from "./approval-policy.js";
|
|
92
92
|
import { extractArgKey, approvalCategory, POLICY_ENGINE_VERSION } from "./approval-policy.js";
|
|
93
93
|
import { contentDigest } from "../../shared/file-tools.js";
|
|
@@ -286,6 +286,71 @@ export function primaryToken(key: string, salient: string, contentDigest: string
|
|
|
286
286
|
return contentDigest ? contentToken(key, salient, contentDigest) : grantToken(key, salient);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Compute a streamed tool call's identity token in the same canonical space the
|
|
291
|
+
* preToolUse hook records denials in (see {@link toolIdentity} / primaryToken).
|
|
292
|
+
* The token keys on the cross-taxonomy category + salient resource PLUS, for a
|
|
293
|
+
* file edit/write, the {@link contentDigest} of the edit content — so a stream
|
|
294
|
+
* `edit` correlates to the hook's `Write` deny for the same path AND content,
|
|
295
|
+
* and an approval of one edit does not match a DIFFERENT edit to the same file.
|
|
296
|
+
*
|
|
297
|
+
* The digest is read from the persisted `approval_content_digest` field when
|
|
298
|
+
* present (a seeded gate carries it, stable even if `args` was elided), and is
|
|
299
|
+
* recomputed from the call's args otherwise (a freshly-streamed call). For a
|
|
300
|
+
* shell/delete/MCP call (no content) it falls back to the coarse token, exactly
|
|
301
|
+
* as before — so those identities are unchanged.
|
|
302
|
+
*
|
|
303
|
+
* Exported so the resume-grant round-trip can be locked against it: the grant a
|
|
304
|
+
* resume mints for an approved tool (buildApprovalGrants -> primaryToken) must
|
|
305
|
+
* equal THIS denial/overlay identity, or the re-issued call is re-gated forever
|
|
306
|
+
* (the dual-path drift the approval-state round-trip suite guards against).
|
|
307
|
+
*/
|
|
308
|
+
export function toolCallIdentityToken(tc: ToolCall): string {
|
|
309
|
+
const id = toolIdentity(tc.name, tc.mcpServerSlug, toolCallArgs(tc));
|
|
310
|
+
const digest = tc.approvalContentDigest || contentDigest(toolCallArgs(tc));
|
|
311
|
+
return primaryToken(id.key, id.salient, digest);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Decode a primary token back into its (key, salient, digest) for the synthesis
|
|
316
|
+
* fallback. The token is `base64(key \n salient)` (coarse) or
|
|
317
|
+
* `base64(key \n salient \n digest)` (content-exact); the digest is the optional
|
|
318
|
+
* third segment. salient never contains a newline (a path or shell command), so
|
|
319
|
+
* splitting on the first two newlines is unambiguous.
|
|
320
|
+
*/
|
|
321
|
+
export function decodeIdentityToken(
|
|
322
|
+
token: string,
|
|
323
|
+
): { key: string; salient: string; digest: string } | undefined {
|
|
324
|
+
try {
|
|
325
|
+
const decoded = Buffer.from(token, "base64").toString("utf-8");
|
|
326
|
+
const first = decoded.indexOf("\n");
|
|
327
|
+
if (first < 0) return undefined;
|
|
328
|
+
const key = decoded.slice(0, first);
|
|
329
|
+
const rest = decoded.slice(first + 1);
|
|
330
|
+
const second = rest.indexOf("\n");
|
|
331
|
+
if (second < 0) return { key, salient: rest, digest: "" };
|
|
332
|
+
return { key, salient: rest.slice(0, second), digest: rest.slice(second + 1) };
|
|
333
|
+
} catch {
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** Best-effort args record for a tool call (proto struct, else parsed preview). */
|
|
339
|
+
export function toolCallArgs(tc: ToolCall): Record<string, unknown> {
|
|
340
|
+
if (tc.args && typeof tc.args === "object") {
|
|
341
|
+
return tc.args as Record<string, unknown>;
|
|
342
|
+
}
|
|
343
|
+
if (tc.argsPreview) {
|
|
344
|
+
try {
|
|
345
|
+
const parsed = JSON.parse(tc.argsPreview);
|
|
346
|
+
if (parsed && typeof parsed === "object") return parsed as Record<string, unknown>;
|
|
347
|
+
} catch {
|
|
348
|
+
// fall through
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return {};
|
|
352
|
+
}
|
|
353
|
+
|
|
289
354
|
/**
|
|
290
355
|
* The shared HMAC coarse fingerprint of an approval grant.
|
|
291
356
|
*
|