@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
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
resolveApprovalMessage,
|
|
14
14
|
deriveActiveLeases,
|
|
15
15
|
resolveApprovalProvenance,
|
|
16
|
+
resolveToolApproval,
|
|
16
17
|
toProtoPolicySource,
|
|
17
18
|
type ActiveLeases,
|
|
18
19
|
type MergedToolPolicy,
|
|
@@ -510,6 +511,50 @@ describe("resolveApprovalProvenance", () => {
|
|
|
510
511
|
// cases assert the mapping is total and that undefined collapses to UNSPECIFIED.
|
|
511
512
|
// ---------------------------------------------------------------------------
|
|
512
513
|
|
|
514
|
+
describe("resolveToolApproval — THE gate decision, shared by the gate and the translators", () => {
|
|
515
|
+
const NO_CATEGORIES: ReadonlySet<ToolApprovalCategory> = new Set();
|
|
516
|
+
const gated: ReadonlyMap<string, MergedToolPolicy> = new Map([
|
|
517
|
+
["github/create_issue", { toolName: "create_issue", mcpServerSlug: "github", requiresApproval: true, approvalMessage: "Create issue '{{args.title}}'?", source: "agent_override" }],
|
|
518
|
+
]);
|
|
519
|
+
|
|
520
|
+
it("an MCP tool with a gating policy waits, with the policy's message resolved and its layer as source", () => {
|
|
521
|
+
expect(resolveToolApproval("create_issue", "github", { title: "Fix crash" }, gated, NO_CATEGORIES)).toEqual({
|
|
522
|
+
requiresApproval: true,
|
|
523
|
+
message: "Create issue 'Fix crash'?",
|
|
524
|
+
source: "agent_override",
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it("an MCP tool absent from the policy map runs — the classifier cleared it (fail-open), source classifier_default", () => {
|
|
529
|
+
expect(resolveToolApproval("list_issues", "github", {}, gated, NO_CATEGORIES)).toEqual({
|
|
530
|
+
requiresApproval: false,
|
|
531
|
+
message: "",
|
|
532
|
+
source: "classifier_default",
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it("a mutating built-in waits with its category's message (fail-closed), source builtin_category", () => {
|
|
537
|
+
expect(resolveToolApproval("execute", "", { command: "rm -rf build" }, new Map(), NO_CATEGORIES)).toEqual({
|
|
538
|
+
requiresApproval: true,
|
|
539
|
+
message: "Run command: rm -rf build",
|
|
540
|
+
source: "builtin_category",
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it("a mutating built-in whose category is leased runs, source approval_lease", () => {
|
|
545
|
+
expect(resolveToolApproval("execute", "", { command: "ls" }, new Map(), new Set<ToolApprovalCategory>(["shell"]))).toEqual({
|
|
546
|
+
requiresApproval: false,
|
|
547
|
+
message: "",
|
|
548
|
+
source: "approval_lease",
|
|
549
|
+
});
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
it("a read-only or unclassified built-in runs (fail-open)", () => {
|
|
553
|
+
expect(resolveToolApproval("read_file", "", { path: "/x" }, new Map(), NO_CATEGORIES).requiresApproval).toBe(false);
|
|
554
|
+
expect(resolveToolApproval("think", "", {}, new Map(), NO_CATEGORIES).requiresApproval).toBe(false);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
513
558
|
describe("toProtoPolicySource", () => {
|
|
514
559
|
it("maps undefined (no governing layer) to UNSPECIFIED", () => {
|
|
515
560
|
expect(toProtoPolicySource(undefined)).toBe(ApprovalPolicySource.UNSPECIFIED);
|
|
@@ -1,38 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unit tests for the shared args-preview
|
|
2
|
+
* Unit tests for the shared args-preview builder — the ONE preview rule every
|
|
3
|
+
* tool row carries since #1097.
|
|
3
4
|
*
|
|
4
5
|
* The Cursor gate path depends on {@link buildElidedArgsPreview} producing a
|
|
5
6
|
* SMALL, ALWAYS-VALID, salient-preserving preview: the resumed turn re-parses it
|
|
6
7
|
* to rebuild an approval grant's identity, and the persist-time size backstop
|
|
7
8
|
* would replace an oversized preview with an unparseable marker. These pin those
|
|
8
9
|
* invariants so a large write can never silently break the resume round-trip.
|
|
10
|
+
* (The native harness's whole-string-truncating `sanitizeArgsPreview` and its
|
|
11
|
+
* two arms went with it: a preview that could truncate to invalid JSON has no
|
|
12
|
+
* caller left.)
|
|
9
13
|
*/
|
|
10
14
|
|
|
11
15
|
import { describe, it, expect } from "vitest";
|
|
12
|
-
import {
|
|
13
|
-
buildElidedArgsPreview,
|
|
14
|
-
sanitizeArgsPreview,
|
|
15
|
-
MAX_ARGS_PREVIEW_LENGTH,
|
|
16
|
-
} from "../args-preview.js";
|
|
16
|
+
import { buildElidedArgsPreview, redactSensitiveArgs, SALIENT_ARG_FIELDS } from "../args-preview.js";
|
|
17
17
|
|
|
18
|
-
describe("
|
|
19
|
-
it("
|
|
20
|
-
|
|
21
|
-
expect(out.api_key).toBe("[REDACTED]");
|
|
22
|
-
expect(out.path).toBe("a.txt");
|
|
18
|
+
describe("SALIENT_ARG_FIELDS", () => {
|
|
19
|
+
it("spans both harnesses' shapes for a file and a shell command, in priority order", () => {
|
|
20
|
+
expect([...SALIENT_ARG_FIELDS]).toEqual(["file_path", "path", "target_notebook", "command"]);
|
|
23
21
|
});
|
|
22
|
+
});
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
expect(
|
|
28
|
-
expect(preview.endsWith("…")).toBe(true);
|
|
24
|
+
describe("redactSensitiveArgs", () => {
|
|
25
|
+
it("redacts secret keys case-insensitively and keeps everything else verbatim", () => {
|
|
26
|
+
expect(redactSensitiveArgs({ Api_Key: "sk-123", path: "a.txt", n: 1 })).toEqual({ Api_Key: "[REDACTED]", path: "a.txt", n: 1 });
|
|
29
27
|
});
|
|
30
28
|
});
|
|
31
29
|
|
|
32
|
-
describe("buildElidedArgsPreview
|
|
33
|
-
const SALIENT =
|
|
30
|
+
describe("buildElidedArgsPreview", () => {
|
|
31
|
+
const SALIENT = SALIENT_ARG_FIELDS;
|
|
32
|
+
|
|
33
|
+
it("is exactly JSON.stringify(args) for short, secret-free args (what every native row now carries)", () => {
|
|
34
|
+
expect(buildElidedArgsPreview({ path: "/x", n: 2 }, SALIENT)).toBe(JSON.stringify({ path: "/x", n: 2 }));
|
|
35
|
+
});
|
|
34
36
|
|
|
35
|
-
it("
|
|
37
|
+
it("yields an empty string for unserializable args instead of throwing", () => {
|
|
38
|
+
const cyclic: Record<string, unknown> = {};
|
|
39
|
+
cyclic.self = cyclic;
|
|
40
|
+
expect(buildElidedArgsPreview(cyclic, SALIENT)).toBe("");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("stays valid JSON and small for a large write, leaving the content value out", () => {
|
|
36
44
|
const content = "line\n".repeat(100_000); // ~500 KB
|
|
37
45
|
const preview = buildElidedArgsPreview(
|
|
38
46
|
{ path: "src/big.ts", contents: content },
|
|
@@ -43,9 +51,21 @@ describe("buildElidedArgsPreview (cursor gate)", () => {
|
|
|
43
51
|
const parsed = JSON.parse(preview) as Record<string, unknown>;
|
|
44
52
|
// Bounded — nowhere near the raw content size.
|
|
45
53
|
expect(preview.length).toBeLessThan(1_000);
|
|
46
|
-
// The salient path survives verbatim (grant identity)
|
|
54
|
+
// The salient path survives verbatim (grant identity); the content is not
|
|
55
|
+
// in the preview at all — never an in-band marker a reader could mistake
|
|
56
|
+
// for the file (stigmer#1107): a surface that needs it reads the row's args.
|
|
47
57
|
expect(parsed.path).toBe("src/big.ts");
|
|
48
|
-
expect(parsed
|
|
58
|
+
expect("contents" in parsed).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("a value at the cap is carried whole; one character over is left out", () => {
|
|
62
|
+
const atCap = "a".repeat(200);
|
|
63
|
+
const overCap = "a".repeat(201);
|
|
64
|
+
const parsed = JSON.parse(
|
|
65
|
+
buildElidedArgsPreview({ path: "x", note: atCap, essay: overCap }, SALIENT),
|
|
66
|
+
) as Record<string, unknown>;
|
|
67
|
+
expect(parsed.note).toBe(atCap);
|
|
68
|
+
expect("essay" in parsed).toBe(false);
|
|
49
69
|
});
|
|
50
70
|
|
|
51
71
|
it("never elides a salient field, even a very long shell command", () => {
|
|
@@ -129,7 +129,7 @@ describe("cross-harness naming parity", () => {
|
|
|
129
129
|
makeAttachment("Makefile", "attachments/01D/Makefile"),
|
|
130
130
|
];
|
|
131
131
|
|
|
132
|
-
// One attachment pipeline serves both harnesses since
|
|
132
|
+
// One attachment pipeline serves both harnesses since #1096;
|
|
133
133
|
// the names it lands are the ones the React SDK's table above predicts.
|
|
134
134
|
const resolved = await resolveAttachments(attachments, {
|
|
135
135
|
sessionId,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for the attachment resolver — the turn runtime's attachment phase,
|
|
3
|
-
* the one pipeline for both harnesses since
|
|
3
|
+
* the one pipeline for both harnesses since #1096 (the native twin,
|
|
4
4
|
* `attachment-injector.ts`, retired then; its ZIP guards moved to
|
|
5
|
-
* `attachment-zip.ts`
|
|
5
|
+
* `attachment-zip.ts` in the same PR).
|
|
6
6
|
*
|
|
7
7
|
* The load-bearing behaviors: storage-key attachments materialize under the
|
|
8
8
|
* platform inputs dir (the universal path — every server-created attachment
|
|
9
9
|
* carries a storage key), the workspace `.stigmer` symlink exists even when
|
|
10
10
|
* the agent has no skills, and any attachment that cannot be materialized
|
|
11
11
|
* fails the resolution loudly (the silent-skip regression behind "plan file
|
|
12
|
-
* wasn't found"). Since
|
|
12
|
+
* wasn't found"). Since #1096 the resolver is the one
|
|
13
13
|
* attachment pipeline for every harness, so it also pins the two behaviors
|
|
14
14
|
* lifted from the native injector: `extract` archives land under their mount
|
|
15
15
|
* directory through the shared #567 guards, and an explicit `mountPath` is
|
|
@@ -279,7 +279,7 @@ describe("resolveAttachments", () => {
|
|
|
279
279
|
|
|
280
280
|
// ── Explicit mountPath: honoured inside the inputs namespace, refused outside ──
|
|
281
281
|
|
|
282
|
-
describe("mountPath
|
|
282
|
+
describe("mountPath", () => {
|
|
283
283
|
it("places a file at its explicit `inputs/…` path, in every spelling the producers use", async () => {
|
|
284
284
|
const { storage } = makeInMemoryArtifactStorage();
|
|
285
285
|
await storage.upload("k/a", Buffer.from("A"), "text/plain");
|
|
@@ -364,7 +364,7 @@ describe("resolveAttachments", () => {
|
|
|
364
364
|
|
|
365
365
|
// ── Archives: `extract` lands the entries under the mount directory ──────
|
|
366
366
|
|
|
367
|
-
describe("extract
|
|
367
|
+
describe("extract", () => {
|
|
368
368
|
const archive = () =>
|
|
369
369
|
Buffer.from(
|
|
370
370
|
buildZip([
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* (`shared/attachment-zip.ts`): the manifest checks (paths, traversal, null
|
|
4
4
|
* bytes, duplicates, methods, emptiness, count and declared-size caps) and
|
|
5
5
|
* the central-directory parsing that issue #567 made authoritative. Moved
|
|
6
|
-
* from the native injector's test file
|
|
6
|
+
* from the native injector's test file in #1096 with the code; every
|
|
7
7
|
* archive comes from the shared real-shape builder
|
|
8
8
|
* (@stigmer/zip-structure/testing). The write of an admitted entry is each
|
|
9
9
|
* caller's and is pinned in that caller's tests (`attachment-resolver.test.ts`).
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`resolveAgentBlueprint`). Union, deduplicated by slug, the session's ref
|
|
5
5
|
* winning a collision (it may pin a different version).
|
|
6
6
|
*
|
|
7
|
-
* Carried from `skill-writer.test.ts`
|
|
7
|
+
* Carried from `skill-writer.test.ts` in #1096, when the native
|
|
8
8
|
* orchestrator's byte-twin of this function was deleted with its module;
|
|
9
9
|
* until then the runtime's copy was tested only through the twin.
|
|
10
10
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for the max_cost_usd hard-stop guard (cost-guard.ts), which the
|
|
3
|
-
* Cursor activity
|
|
3
|
+
* Cursor activity called until the turn runtime took it over in #1070.
|
|
4
4
|
*
|
|
5
5
|
* The guard is the cursor-side analog of the native cost-cap middleware
|
|
6
6
|
* (middleware/cost-cap.ts): same proto semantics (0/unset = no cap), same
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @regression file-hitl-phase0 — pins
|
|
2
|
+
* @regression file-hitl-phase0 — pins exact-apply: the runner applies the exact
|
|
3
|
+
* approved whole-file bytes, never model-regenerated ones.
|
|
3
4
|
*
|
|
4
5
|
* Unit tests for resume-time exact-apply (the HITL "what you approve is what gets
|
|
5
6
|
* applied" guarantee for the Cursor deny-only harness).
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for the streaming persist decision (issue #179), the shared
|
|
3
|
-
* cadence rule
|
|
4
|
-
* takes over in S2 M3.
|
|
3
|
+
* cadence rule both adapters' stream loops read.
|
|
5
4
|
*
|
|
6
|
-
* Validates the converged cadence: discrete
|
|
5
|
+
* Validates the converged cadence: a discrete transcript change persists
|
|
7
6
|
* immediately, while high-frequency token deltas ride the shared
|
|
8
7
|
* StreamingUpdateScheduler's time cadence (rather than the old, time-blind
|
|
9
|
-
* `eventCount % 20` gate that starved short turns).
|
|
8
|
+
* `eventCount % 20` gate that starved short turns). The signal is the one
|
|
9
|
+
* transcript builder's `dirty` flag (since #1097); until then three
|
|
10
|
+
* Cursor-named flags, two of them constant `false` on both loops.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import { describe, it, expect } from "vitest";
|
|
@@ -22,65 +23,50 @@ const CONFIG: StreamingConfig = {
|
|
|
22
23
|
burstThreshold: 50,
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
const NO_FORCE = {
|
|
26
|
-
deltaEnricherDirty: false,
|
|
27
|
-
todosDirty: false,
|
|
28
|
-
contentDirty: false,
|
|
29
|
-
} as const;
|
|
30
|
-
|
|
31
26
|
describe("shouldPersistStreamingStatus", () => {
|
|
32
27
|
it("persists on the first event via the scheduler (kills the opaque-wait at turn start)", () => {
|
|
33
28
|
const scheduler = new StreamingUpdateScheduler(CONFIG, 0);
|
|
34
|
-
expect(shouldPersistStreamingStatus(
|
|
29
|
+
expect(shouldPersistStreamingStatus(false, scheduler, 1, 0)).toBe(true);
|
|
35
30
|
});
|
|
36
31
|
|
|
37
|
-
it("does not persist a sub-500ms token delta
|
|
32
|
+
it("does not persist a sub-500ms token delta while the transcript is clean", () => {
|
|
38
33
|
const scheduler = new StreamingUpdateScheduler(CONFIG, 0);
|
|
39
34
|
scheduler.markUpdateSent(1, 0); // first flush already sent
|
|
40
35
|
|
|
41
36
|
// 100ms later, one more delta event — too soon for the time cadence.
|
|
42
|
-
expect(shouldPersistStreamingStatus(
|
|
37
|
+
expect(shouldPersistStreamingStatus(false, scheduler, 2, 100)).toBe(false);
|
|
43
38
|
});
|
|
44
39
|
|
|
45
40
|
it("persists a token delta once the 500ms cadence elapses", () => {
|
|
46
41
|
const scheduler = new StreamingUpdateScheduler(CONFIG, 0);
|
|
47
42
|
scheduler.markUpdateSent(1, 0);
|
|
48
43
|
|
|
49
|
-
expect(shouldPersistStreamingStatus(
|
|
44
|
+
expect(shouldPersistStreamingStatus(false, scheduler, 2, 500)).toBe(true);
|
|
50
45
|
});
|
|
51
46
|
|
|
52
|
-
it
|
|
53
|
-
["contentDirty (tool call / sub-agent)", { ...NO_FORCE, contentDirty: true }],
|
|
54
|
-
["todosDirty", { ...NO_FORCE, todosDirty: true }],
|
|
55
|
-
["deltaEnricherDirty (shell output)", { ...NO_FORCE, deltaEnricherDirty: true }],
|
|
56
|
-
])("force-flushes immediately on %s, bypassing the time cadence", (_label, signals) => {
|
|
47
|
+
it("flushes immediately when the transcript is dirty, bypassing the time cadence", () => {
|
|
57
48
|
const scheduler = new StreamingUpdateScheduler(CONFIG, 0);
|
|
58
49
|
scheduler.markUpdateSent(1, 0);
|
|
59
50
|
|
|
60
51
|
// Only 1ms after the last flush: the scheduler alone would say no...
|
|
61
|
-
expect(shouldPersistStreamingStatus(
|
|
62
|
-
// ...but
|
|
63
|
-
expect(shouldPersistStreamingStatus(
|
|
52
|
+
expect(shouldPersistStreamingStatus(false, scheduler, 2, 1)).toBe(false);
|
|
53
|
+
// ...but a discrete transcript change flushes now.
|
|
54
|
+
expect(shouldPersistStreamingStatus(true, scheduler, 2, 1)).toBe(true);
|
|
64
55
|
});
|
|
65
56
|
|
|
66
57
|
// The #179 starvation scenario: a short turn of < 20 events. Under the old
|
|
67
58
|
// `eventCount % 20` gate, a tool call appearing at event 3 (and completing at
|
|
68
59
|
// event 4) would never be persisted until the unconditional final flush. With
|
|
69
|
-
// the converged decision, the tool lifecycle
|
|
70
|
-
//
|
|
60
|
+
// the converged decision, the tool lifecycle flushes the instant it happens,
|
|
61
|
+
// regardless of how few events the turn has.
|
|
71
62
|
it("surfaces a tool call on a short (<20 event) turn", () => {
|
|
72
63
|
const scheduler = new StreamingUpdateScheduler(CONFIG, 0);
|
|
73
64
|
const flushes: number[] = [];
|
|
74
65
|
let clock = 0;
|
|
75
66
|
|
|
76
67
|
// Helper mirroring the loop: decide, then mark both clocks on a flush.
|
|
77
|
-
const tick = (eventCount: number,
|
|
78
|
-
const persist = shouldPersistStreamingStatus(
|
|
79
|
-
{ ...NO_FORCE, contentDirty },
|
|
80
|
-
scheduler,
|
|
81
|
-
eventCount,
|
|
82
|
-
clock,
|
|
83
|
-
);
|
|
68
|
+
const tick = (eventCount: number, transcriptDirty: boolean) => {
|
|
69
|
+
const persist = shouldPersistStreamingStatus(transcriptDirty, scheduler, eventCount, clock);
|
|
84
70
|
if (persist) {
|
|
85
71
|
flushes.push(eventCount);
|
|
86
72
|
scheduler.markUpdateSent(eventCount, clock);
|
|
@@ -90,8 +76,8 @@ describe("shouldPersistStreamingStatus", () => {
|
|
|
90
76
|
|
|
91
77
|
tick(1, false); // assistant delta — first-event flush
|
|
92
78
|
tick(2, false); // thinking delta — within 500ms, no flush
|
|
93
|
-
tick(3, true); // tool call starts —
|
|
94
|
-
tick(4, true); // tool call completes —
|
|
79
|
+
tick(3, true); // tool call starts — the transcript is dirty, flush
|
|
80
|
+
tick(4, true); // tool call completes — dirty again, flush
|
|
95
81
|
tick(5, false); // closing assistant delta — within 500ms, no flush
|
|
96
82
|
|
|
97
83
|
// The tool lifecycle (events 3 and 4) is observed live; event 1 is the
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The shared prompt glue (`shared/prompt-sections.ts`): the standing order,
|
|
3
3
|
* the input-files lines, the skill selection and the also-available sentence
|
|
4
4
|
* (the sentence's arms came from `skill-writer.test.ts`, retired with its
|
|
5
|
-
* module
|
|
5
|
+
* module in #1096). What each harness renders AROUND these is pinned whole by
|
|
6
6
|
* the two builders' prompt goldens (`execute-deep-agent/__tests__/
|
|
7
7
|
* prompt-goldens.test.ts`, `execute-cursor/__tests__/prompt-goldens.test.ts`);
|
|
8
8
|
* this file pins the glue's own contract, harness-free.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for the shared turn-boundary flowed-row stamping
|
|
3
3
|
* (`shared/tool-row.ts` `stampFlowedFileEditRows` /
|
|
4
|
-
* `stampFlowedSubAgentFileEditRows`; the deep-agent's copy until
|
|
4
|
+
* `stampFlowedSubAgentFileEditRows`; the deep-agent's copy until #1096), with
|
|
5
5
|
* emphasis on the sub-agent path added by the DD-24 follow-up: sub-agent edit
|
|
6
6
|
* rows fold into the parent turn's change set, so they carry the parent change
|
|
7
7
|
* set id, scoped to this turn by tool-call-id novelty (they lack the
|
|
@@ -342,7 +342,7 @@ describe("offloadOversizedToolOutputs", () => {
|
|
|
342
342
|
await offloadOversizedToolOutputs(status, ctx);
|
|
343
343
|
expect(uploads).toHaveLength(1);
|
|
344
344
|
|
|
345
|
-
// Simulate
|
|
345
|
+
// Simulate the builder's finish upsert re-inflating the inline result with the SAME
|
|
346
346
|
// bytes on a subsequent persist; the ref's content hash still matches.
|
|
347
347
|
status.messages[0].toolCalls[0].result = result;
|
|
348
348
|
await offloadOversizedToolOutputs(status, ctx);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
2
|
import {
|
|
3
3
|
StreamingUpdateScheduler,
|
|
4
|
-
UpdateReason,
|
|
5
4
|
loadStreamingConfig,
|
|
6
5
|
type StreamingConfig,
|
|
7
6
|
} from "../streaming-scheduler.js";
|
|
@@ -17,7 +16,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
17
16
|
it("always sends on first event", () => {
|
|
18
17
|
const s = new StreamingUpdateScheduler(BASE_CONFIG, 0);
|
|
19
18
|
expect(s.shouldSendUpdate(1, 0)).toBe(true);
|
|
20
|
-
expect(s.updateReason).toBe(
|
|
19
|
+
expect(s.updateReason).toBe("first_update");
|
|
21
20
|
});
|
|
22
21
|
|
|
23
22
|
it("does not send if zero events processed", () => {
|
|
@@ -32,7 +31,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
32
31
|
s.markUpdateSent(0, 0);
|
|
33
32
|
|
|
34
33
|
expect(s.shouldSendUpdate(1, 500)).toBe(true);
|
|
35
|
-
expect(s.updateReason).toBe(
|
|
34
|
+
expect(s.updateReason).toBe("time_threshold");
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
it("does not send before minInterval", () => {
|
|
@@ -40,7 +39,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
40
39
|
s.markUpdateSent(0, 0);
|
|
41
40
|
|
|
42
41
|
expect(s.shouldSendUpdate(1, 499)).toBe(false);
|
|
43
|
-
expect(s.updateReason).toBe(
|
|
42
|
+
expect(s.updateReason).toBe("none");
|
|
44
43
|
});
|
|
45
44
|
|
|
46
45
|
it("does not send after minInterval with zero new events", () => {
|
|
@@ -57,7 +56,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
57
56
|
s.markUpdateSent(0, 0);
|
|
58
57
|
|
|
59
58
|
expect(s.shouldSendUpdate(50, 100)).toBe(true);
|
|
60
|
-
expect(s.updateReason).toBe(
|
|
59
|
+
expect(s.updateReason).toBe("burst_protection");
|
|
61
60
|
});
|
|
62
61
|
|
|
63
62
|
it("does not send at threshold - 1", () => {
|
|
@@ -74,7 +73,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
74
73
|
s.markUpdateSent(10, 0);
|
|
75
74
|
|
|
76
75
|
expect(s.shouldSendUpdate(10, 5000)).toBe(true);
|
|
77
|
-
expect(s.updateReason).toBe(
|
|
76
|
+
expect(s.updateReason).toBe("keepalive");
|
|
78
77
|
});
|
|
79
78
|
|
|
80
79
|
it("does not send keepalive before maxInterval", () => {
|
|
@@ -91,7 +90,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
91
90
|
s.markUpdateSent(10, 1000);
|
|
92
91
|
|
|
93
92
|
expect(s.shouldSendUpdate(11, 1500)).toBe(true);
|
|
94
|
-
expect(s.updateReason).toBe(
|
|
93
|
+
expect(s.updateReason).toBe("time_threshold");
|
|
95
94
|
|
|
96
95
|
s.markUpdateSent(11, 1500);
|
|
97
96
|
|
|
@@ -125,7 +124,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
125
124
|
const s = new StreamingUpdateScheduler(BASE_CONFIG, 0);
|
|
126
125
|
// First check with event and enough time — should be FIRST_UPDATE, not TIME_THRESHOLD
|
|
127
126
|
expect(s.shouldSendUpdate(1, 600)).toBe(true);
|
|
128
|
-
expect(s.updateReason).toBe(
|
|
127
|
+
expect(s.updateReason).toBe("first_update");
|
|
129
128
|
});
|
|
130
129
|
|
|
131
130
|
it("time_threshold takes priority over burst_protection", () => {
|
|
@@ -134,7 +133,7 @@ describe("StreamingUpdateScheduler", () => {
|
|
|
134
133
|
|
|
135
134
|
// Both time and burst conditions met — time wins
|
|
136
135
|
expect(s.shouldSendUpdate(50, 500)).toBe(true);
|
|
137
|
-
expect(s.updateReason).toBe(
|
|
136
|
+
expect(s.updateReason).toBe("time_threshold");
|
|
138
137
|
});
|
|
139
138
|
});
|
|
140
139
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for applyTodoUpdate — the harness-agnostic to-do map projection
|
|
3
|
-
*
|
|
3
|
+
* the one transcript builder projects a todo write through, for both harnesses.
|
|
4
4
|
*
|
|
5
5
|
* These pin the exact mapping contract (status coercion, id synthesis,
|
|
6
6
|
* created_at preservation, merge vs. full-replace, clear-on-empty, defensive
|
|
@@ -382,7 +382,7 @@ describe("collectSettledToolCallIds", () => {
|
|
|
382
382
|
// scoping them as this-turn would mis-attribute a dead call to the
|
|
383
383
|
// resuming turn's change set. (The Cursor monotonic guard makes the
|
|
384
384
|
// opposite call for the same status so a replayed event can still advance
|
|
385
|
-
// the row; see
|
|
385
|
+
// the row; see isSettled in harness/transcript/builder.ts.)
|
|
386
386
|
const ids = collectSettledToolCallIds([
|
|
387
387
|
msgWith("tc-interrupted", ToolCallStatus.TOOL_CALL_INTERRUPTED),
|
|
388
388
|
]);
|
|
@@ -466,3 +466,98 @@ export function resolveApprovalMessage(
|
|
|
466
466
|
return JSON.stringify(value);
|
|
467
467
|
});
|
|
468
468
|
}
|
|
469
|
+
|
|
470
|
+
// ── The gate's decision ─────────────────────────────────────────────
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* THE approval-message template per mutating built-in category — the one
|
|
474
|
+
* table both harnesses word their approval cards from (since #1097).
|
|
475
|
+
* Keyed by category (not raw tool name) so every alias of a mutation renders
|
|
476
|
+
* one message; placeholders resolve against the stream arg shape
|
|
477
|
+
* (`path`/`command`; `resolveApprovalMessage`). The native gate decides with
|
|
478
|
+
* it (`resolveToolApproval`), the Cursor translator words its `gate` from it
|
|
479
|
+
* (`execute-cursor/approval-policy.ts` `getBuiltInApprovalMessage`), and the
|
|
480
|
+
* Cursor boundary resolves a denied call's message through the same path.
|
|
481
|
+
*
|
|
482
|
+
* Until then the Cursor harness carried a table of its own and the two differed
|
|
483
|
+
* by a word — `shell` read "Run command" there and "Execute command" here.
|
|
484
|
+
* Unified on the plainer word: a user reads "Run command" and knows
|
|
485
|
+
* what is being asked. Known and deliberately left (#1112):
|
|
486
|
+
* `write` resolves `{{args.path}}`, while deepagents' file tools send
|
|
487
|
+
* `file_path`, so a gated native write reads "Write file: <unknown>".
|
|
488
|
+
*/
|
|
489
|
+
export const CATEGORY_APPROVAL_MESSAGE: Record<ToolApprovalCategory, string> = {
|
|
490
|
+
write: "Write file: {{args.path}}",
|
|
491
|
+
delete: "Delete: {{args.path}}",
|
|
492
|
+
shell: "Run command: {{args.command}}",
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
/** What the gate decides for one call: whether it waits, the message the card shows, and which layer said so. */
|
|
496
|
+
export interface ApprovalRequirement {
|
|
497
|
+
readonly requiresApproval: boolean;
|
|
498
|
+
readonly message: string;
|
|
499
|
+
/** Which policy layer determined this verdict — stamped on the shadow receipt. */
|
|
500
|
+
readonly source: PolicySource;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* THE approval decision for one tool call — the same function the native gate
|
|
505
|
+
* (`middleware/approval-gate.ts`) interrupts on and the native translator
|
|
506
|
+
* reports as `tool_started.gate`, so the row can never disagree with the gate
|
|
507
|
+
* about whether a call waits (since #1097; until then the transcript
|
|
508
|
+
* builder carried its own weaker copy that gated MCP tools only). Its
|
|
509
|
+
* read-side twin is {@link resolveApprovalProvenance}, which answers "which
|
|
510
|
+
* layer governs this call" for EVERY call, gated or not.
|
|
511
|
+
*
|
|
512
|
+
* MCP tools stay governed by the connect-flow classifier + four-level policy
|
|
513
|
+
* chain. The policy map carries only the tools that REQUIRE approval, so an
|
|
514
|
+
* absent entry means the classifier already auto-approved it — fail-OPEN is
|
|
515
|
+
* correct here (a fail-closed default would re-gate everything the classifier
|
|
516
|
+
* cleared). A server-scoped lease surfaces as an absent entry too: the leased
|
|
517
|
+
* server's tools are dropped from `policies` upstream (`mergeApprovalPolicies`),
|
|
518
|
+
* so a lease-cleared MCP tool takes the same auto-approve path (its receipt
|
|
519
|
+
* therefore reads classifier_default rather than approval_lease; a faithful
|
|
520
|
+
* per-server lease provenance would need the lease set threaded here and is
|
|
521
|
+
* deferred with the rest of the persisted-receipt work).
|
|
522
|
+
*
|
|
523
|
+
* Built-in/platform tools: gate exactly the mutating categories through the
|
|
524
|
+
* shared classifier — fail-CLOSED for the mutating set (write/edit/delete/shell
|
|
525
|
+
* require approval), fail-open for read-only and unclassified built-ins. A
|
|
526
|
+
* run-lifetime category lease (the user chose "approve all <category>" earlier
|
|
527
|
+
* in this run) auto-approves every built-in of that category for the rest of
|
|
528
|
+
* the run — the scoped successor to auto-approve-all.
|
|
529
|
+
*/
|
|
530
|
+
export function resolveToolApproval(
|
|
531
|
+
toolName: string,
|
|
532
|
+
serverSlug: string,
|
|
533
|
+
args: Record<string, unknown>,
|
|
534
|
+
policies: ReadonlyMap<string, MergedToolPolicy>,
|
|
535
|
+
leasedCategories: ReadonlySet<ToolApprovalCategory>,
|
|
536
|
+
): ApprovalRequirement {
|
|
537
|
+
if (serverSlug) {
|
|
538
|
+
const key = `${serverSlug}/${toolName}`;
|
|
539
|
+
const policy = policies.get(key);
|
|
540
|
+
if (policy) {
|
|
541
|
+
return {
|
|
542
|
+
requiresApproval: policy.requiresApproval,
|
|
543
|
+
message: resolveApprovalMessage(policy.approvalMessage, toolName, args),
|
|
544
|
+
source: policy.source,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return { requiresApproval: false, message: "", source: "classifier_default" };
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const category = toolApprovalCategory(toolName);
|
|
551
|
+
if (category) {
|
|
552
|
+
if (leasedCategories.has(category)) {
|
|
553
|
+
return { requiresApproval: false, message: "", source: "approval_lease" };
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
requiresApproval: true,
|
|
557
|
+
message: resolveApprovalMessage(CATEGORY_APPROVAL_MESSAGE[category], toolName, args),
|
|
558
|
+
source: "builtin_category",
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return { requiresApproval: false, message: "", source: "builtin_category" };
|
|
563
|
+
}
|