@stigmer/runner 3.15.3-dev.20260914121148 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- 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 +2 -2
- 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 +47 -12
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +41 -10
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +15 -6
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +17 -4
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +4 -4
- package/dist/activities/execute-cursor/adapter.js +4 -4
- 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/service-tier.js +1 -2
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- 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/activities/generate-session-subject.d.ts +25 -4
- package/dist/activities/generate-session-subject.js +17 -7
- package/dist/activities/generate-session-subject.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +17 -6
- package/dist/client/stigmer-client.js +47 -14
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/config.d.ts +6 -3
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- 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/interceptors/run-credential-activity.d.ts +28 -0
- package/dist/interceptors/run-credential-activity.js +56 -0
- package/dist/interceptors/run-credential-activity.js.map +1 -0
- 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 +10 -4
- package/dist/runner-manager.js.map +1 -1
- package/dist/shared/activity-input.d.ts +9 -0
- package/dist/shared/activity-input.js +17 -0
- package/dist/shared/activity-input.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-zip.d.ts +2 -2
- package/dist/shared/attachment-zip.js +2 -2
- package/dist/shared/channel-attachment.d.ts +8 -5
- package/dist/shared/channel-attachment.js +10 -6
- package/dist/shared/channel-attachment.js.map +1 -1
- 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/filereview/progress.d.ts +13 -0
- package/dist/shared/filereview/progress.js +13 -0
- package/dist/shared/filereview/progress.js.map +1 -1
- 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/memory-attachment.d.ts +16 -9
- package/dist/shared/memory-attachment.js +18 -10
- package/dist/shared/memory-attachment.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/run-credential-store.d.ts +32 -0
- package/dist/shared/run-credential-store.js +39 -0
- package/dist/shared/run-credential-store.js.map +1 -0
- package/dist/shared/run-credential.d.ts +61 -0
- package/dist/shared/run-credential.js +68 -0
- package/dist/shared/run-credential.js.map +1 -0
- 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/synthesized-attachment.d.ts +30 -3
- package/dist/shared/synthesized-attachment.js +26 -0
- package/dist/shared/synthesized-attachment.js.map +1 -1
- 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/dist/worker.js +10 -3
- package/dist/worker.js.map +1 -1
- package/dist/workflow-source.d.ts +10 -0
- package/dist/workflow-source.js +12 -0
- package/dist/workflow-source.js.map +1 -1
- package/dist/workflows/execute-from-execution.d.ts +15 -0
- package/dist/workflows/execute-from-execution.js +11 -0
- package/dist/workflows/execute-from-execution.js.map +1 -1
- package/dist/workflows/index.d.ts +5 -3
- package/dist/workflows/index.js +5 -3
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/interceptors/run-credential.d.ts +34 -0
- package/dist/workflows/interceptors/run-credential.js +71 -0
- package/dist/workflows/interceptors/run-credential.js.map +1 -0
- package/package.json +4 -4
- 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__/run-credential-e2e.test.ts +233 -0
- package/src/__tests__/run-credential-registration.test.ts +80 -0
- package/src/__tests__/runner-manager.test.ts +1 -1
- package/src/activities/__tests__/generate-session-subject-wire.test.ts +119 -0
- package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +2 -2
- 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 +67 -17
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +19 -5
- 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-event-recorder.test.ts +142 -0
- package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +19 -8
- package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +10 -8
- 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 +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -1
- 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 +7 -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 +5 -5
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +2 -1
- 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 +8 -8
- 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 +1 -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 +3 -3
- 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 +13 -1
- package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +2 -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__/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 +4 -4
- 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/service-tier.ts +1 -2
- 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/activities/generate-session-subject.ts +29 -4
- package/src/client/__tests__/stigmer-client.test.ts +92 -0
- package/src/client/stigmer-client.ts +48 -14
- package/src/config.ts +6 -3
- 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/interceptors/__tests__/run-credential-activity.test.ts +133 -0
- package/src/interceptors/run-credential-activity.ts +67 -0
- 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 +14 -4
- 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__/channel-attachment.test.ts +12 -0
- package/src/shared/__tests__/cost-guard.test.ts +1 -1
- package/src/shared/__tests__/exact-apply.test.ts +2 -1
- package/src/shared/__tests__/memory-attachment.test.ts +17 -0
- package/src/shared/__tests__/persist-decision.test.ts +19 -33
- package/src/shared/__tests__/prompt-sections.test.ts +1 -1
- package/src/shared/__tests__/run-credential.test.ts +111 -0
- 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/activity-input.ts +21 -0
- 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-zip.ts +2 -2
- package/src/shared/channel-attachment.ts +14 -6
- 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/filereview/progress.ts +13 -0
- package/src/shared/heartbeat.ts +1 -1
- package/src/shared/llm-backend.ts +0 -4
- package/src/shared/memory-attachment.ts +22 -10
- 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/run-credential-store.ts +45 -0
- package/src/shared/run-credential.ts +70 -0
- 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/synthesized-attachment.ts +38 -3
- 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/src/worker.ts +15 -3
- package/src/workflow-source.ts +15 -0
- package/src/workflows/__tests__/run-credential-interceptor.test.ts +178 -0
- package/src/workflows/execute-from-execution.ts +17 -0
- package/src/workflows/index.ts +5 -3
- package/src/workflows/interceptors/run-credential.ts +101 -0
- package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
- package/dist/activities/execute-cursor/delta-enricher.js +0 -265
- package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
- package/dist/activities/execute-cursor/message-translator.js +0 -2040
- package/dist/activities/execute-cursor/message-translator.js.map +0 -1
- package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
- package/dist/activities/execute-cursor/todo-tracker.js +0 -80
- package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
- package/dist/activities/execute-deep-agent/execution-state.js +0 -68
- package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
- package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
- package/dist/activities/execute-deep-agent/v3-events.js +0 -35
- package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
- package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
- package/dist/shared/execution-status-writer.d.ts +0 -31
- package/dist/shared/execution-status-writer.js +0 -43
- package/dist/shared/execution-status-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
- package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
- package/src/activities/execute-cursor/delta-enricher.ts +0 -307
- package/src/activities/execute-cursor/message-translator.ts +0 -2319
- package/src/activities/execute-cursor/todo-tracker.ts +0 -91
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
- package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
- package/src/activities/execute-deep-agent/execution-state.ts +0 -78
- package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
- package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
- package/src/activities/execute-deep-agent/v3-events.ts +0 -153
- package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
- package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
- package/src/shared/execution-status-writer.ts +0 -56
|
@@ -1,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.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run credential's wire reader and its store (`run-credential.ts`,
|
|
3
|
+
* `run-credential-store.ts`).
|
|
4
|
+
*
|
|
5
|
+
* The property that matters is the last arm: two activities whose awaits
|
|
6
|
+
* interleave in one process each see their own credential and never the
|
|
7
|
+
* other's. That is what lets one shared `StigmerClient` — one per worker for
|
|
8
|
+
* the turn activities — present the right run's credential per request.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
RUN_CREDENTIAL_HEADER,
|
|
15
|
+
RUN_CREDENTIAL_INPUT_KEY,
|
|
16
|
+
readRunCredentialFromInput,
|
|
17
|
+
} from "../run-credential.js";
|
|
18
|
+
import {
|
|
19
|
+
currentRunCredential,
|
|
20
|
+
withRunCredential,
|
|
21
|
+
} from "../run-credential-store.js";
|
|
22
|
+
|
|
23
|
+
describe("readRunCredentialFromInput", () => {
|
|
24
|
+
it("reads a non-empty string under the wire key", () => {
|
|
25
|
+
expect(
|
|
26
|
+
readRunCredentialFromInput({ [RUN_CREDENTIAL_INPUT_KEY]: "cred-1" }),
|
|
27
|
+
).toBe("cred-1");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("answers undefined for the positional string shape the turn activities also accept", () => {
|
|
31
|
+
expect(readRunCredentialFromInput("aex_123")).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("answers undefined for a credential-less object — an older server's dispatch", () => {
|
|
35
|
+
expect(
|
|
36
|
+
readRunCredentialFromInput({ execution_id: "aex_123", thread_id: "" }),
|
|
37
|
+
).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("answers undefined for an empty string, null, undefined and a non-string value", () => {
|
|
41
|
+
expect(
|
|
42
|
+
readRunCredentialFromInput({ [RUN_CREDENTIAL_INPUT_KEY]: "" }),
|
|
43
|
+
).toBeUndefined();
|
|
44
|
+
expect(readRunCredentialFromInput(null)).toBeUndefined();
|
|
45
|
+
expect(readRunCredentialFromInput(undefined)).toBeUndefined();
|
|
46
|
+
expect(
|
|
47
|
+
readRunCredentialFromInput({ [RUN_CREDENTIAL_INPUT_KEY]: 42 }),
|
|
48
|
+
).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("does not read the connect lane's camelCase per-call token", () => {
|
|
52
|
+
expect(
|
|
53
|
+
readRunCredentialFromInput({ executionContextToken: "connect-token" }),
|
|
54
|
+
).toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("pins the wire vocabulary as bytes", () => {
|
|
58
|
+
expect(RUN_CREDENTIAL_INPUT_KEY).toBe("execution_context_token");
|
|
59
|
+
expect(RUN_CREDENTIAL_HEADER).toBe("stigmer-run-credential");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe("run-credential store", () => {
|
|
64
|
+
it("is empty outside any activity", () => {
|
|
65
|
+
expect(currentRunCredential()).toBeUndefined();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("is visible to everything the wrapped function awaits, and gone after", async () => {
|
|
69
|
+
let inner: string | undefined;
|
|
70
|
+
await withRunCredential("cred-a", async () => {
|
|
71
|
+
await Promise.resolve();
|
|
72
|
+
inner = await (async () => currentRunCredential())();
|
|
73
|
+
});
|
|
74
|
+
expect(inner).toBe("cred-a");
|
|
75
|
+
expect(currentRunCredential()).toBeUndefined();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("is inherited by a promise created inside the scope and settled after it", async () => {
|
|
79
|
+
let detached: Promise<string | undefined> | undefined;
|
|
80
|
+
await withRunCredential("cred-b", async () => {
|
|
81
|
+
detached = new Promise((resolve) =>
|
|
82
|
+
setTimeout(() => resolve(currentRunCredential()), 5),
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
expect(await detached).toBe("cred-b");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("never crosses between two activities whose awaits interleave", async () => {
|
|
89
|
+
const seen: Array<[string, string | undefined]> = [];
|
|
90
|
+
const activity = async (name: string, ticks: number) => {
|
|
91
|
+
for (let i = 0; i < ticks; i++) {
|
|
92
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
93
|
+
seen.push([name, currentRunCredential()]);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
await Promise.all([
|
|
97
|
+
withRunCredential("cred-1", () => activity("one", 4)),
|
|
98
|
+
withRunCredential("cred-2", () => activity("two", 4)),
|
|
99
|
+
activity("none", 4),
|
|
100
|
+
]);
|
|
101
|
+
expect(seen.filter(([name]) => name === "one").map(([, c]) => c)).toEqual(
|
|
102
|
+
Array(4).fill("cred-1"),
|
|
103
|
+
);
|
|
104
|
+
expect(seen.filter(([name]) => name === "two").map(([, c]) => c)).toEqual(
|
|
105
|
+
Array(4).fill("cred-2"),
|
|
106
|
+
);
|
|
107
|
+
expect(seen.filter(([name]) => name === "none").map(([, c]) => c)).toEqual(
|
|
108
|
+
Array(4).fill(undefined),
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -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
|
]);
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
* then the control planes; once both are everywhere, drop the positional branch
|
|
16
16
|
* (and the `string` arms below).
|
|
17
17
|
*/
|
|
18
|
+
|
|
19
|
+
import type { RUN_CREDENTIAL_INPUT_KEY } from "./run-credential.js";
|
|
20
|
+
|
|
18
21
|
export interface ExecuteActivityInput {
|
|
19
22
|
readonly execution_id: string;
|
|
20
23
|
readonly thread_id: string;
|
|
@@ -27,8 +30,26 @@ export interface ExecuteActivityInput {
|
|
|
27
30
|
* from it. Absent on the legacy positional wire shape (defaults to 0).
|
|
28
31
|
*/
|
|
29
32
|
readonly turn_seq?: number;
|
|
33
|
+
/**
|
|
34
|
+
* The run credential the server minted for this execution at dispatch,
|
|
35
|
+
* handed on from the workflow input; absent when the dispatch carried none
|
|
36
|
+
* (an older server; the cloud). Not normalized here and never read by an
|
|
37
|
+
* activity: the activity boundary enters it into the run-credential store
|
|
38
|
+
* before the activity runs (`interceptors/run-credential-activity.ts`), and
|
|
39
|
+
* the control-plane client presents it per request (`run-credential.ts`).
|
|
40
|
+
*/
|
|
41
|
+
readonly execution_context_token?: string;
|
|
30
42
|
}
|
|
31
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Compile-time fence: the key the boundary reads
|
|
46
|
+
* (`RUN_CREDENTIAL_INPUT_KEY`) is a key of this input. The type keeps the
|
|
47
|
+
* literal so the wire shape stays readable; this line fails to type-check the
|
|
48
|
+
* day the two disagree.
|
|
49
|
+
*/
|
|
50
|
+
type _RunCredentialKeyIsOnTheWire =
|
|
51
|
+
ExecuteActivityInput[typeof RUN_CREDENTIAL_INPUT_KEY];
|
|
52
|
+
|
|
32
53
|
export interface NormalizedActivityInput {
|
|
33
54
|
readonly executionId: string;
|
|
34
55
|
readonly threadId: string;
|
|
@@ -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
|
+
}
|
|
@@ -8,9 +8,29 @@
|
|
|
8
8
|
* JSON: the per-tool offload does not touch it, and the aggregate size backstop
|
|
9
9
|
* would replace an oversized preview with an unparseable marker.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* ONE preview rule for every row (since #1097): the transcript builder
|
|
12
|
+
* stamps every tool row's preview through {@link buildElidedArgsPreview} over
|
|
13
|
+
* {@link SALIENT_ARG_FIELDS}, as `message.proto` promises — sanitized,
|
|
14
|
+
* redacted, at creation, for inline visibility. Until then there were two
|
|
15
|
+
* rules: native stamped a whole-string-truncating `sanitizeArgsPreview` on
|
|
16
|
+
* gated rows only (a preview that could truncate to invalid JSON, acceptable
|
|
17
|
+
* only because native's resume never re-parsed it), and Cursor's stream path
|
|
18
|
+
* stamped `JSON.stringify(args)` unredacted. Both are
|
|
19
|
+
* gone; this module holds the one builder and the one salient list.
|
|
20
|
+
*
|
|
21
|
+
* THE PREVIEW NEVER CARRIES A VALUE IT CANNOT CARRY WHOLE. A non-salient
|
|
22
|
+
* string over the per-value cap is left out of the preview — not replaced by
|
|
23
|
+
* an in-band marker. The marker this module wrote until #1097 (`"[381
|
|
24
|
+
* chars]"`) was a string no reader could tell from content: the approval gate
|
|
25
|
+
* rendered it as the file the user was asked to approve (stigmer#1107). An
|
|
26
|
+
* absent key is the out-of-band signal every reader already handles — a
|
|
27
|
+
* surface that needs the whole value reads the row's `args`, the way the
|
|
28
|
+
* gate does now; the codebase's precedent for "content not included" is a
|
|
29
|
+
* typed fact on the wire (file review's `FileReviewBlockReason`), never a
|
|
30
|
+
* display string, and the approval projection gaining such a fact is a
|
|
31
|
+
* follow-up of its own. The cost, named: the CLI's and ink's one-line preview
|
|
32
|
+
* loses the value's size, and Cursor's recovery digest reads `tool({})` for
|
|
33
|
+
* an MCP tool whose only argument is oversized.
|
|
14
34
|
*/
|
|
15
35
|
|
|
16
36
|
/**
|
|
@@ -22,24 +42,27 @@ export const SENSITIVE_ARG_KEYS: ReadonlySet<string> = new Set([
|
|
|
22
42
|
"credentials", "auth", "authorization",
|
|
23
43
|
]);
|
|
24
44
|
|
|
25
|
-
/** Whole-preview length cap for {@link sanitizeArgsPreview} (native). */
|
|
26
|
-
export const MAX_ARGS_PREVIEW_LENGTH = 500;
|
|
27
|
-
|
|
28
45
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
46
|
+
* Top-level tool-argument fields, in priority order, that identify the specific
|
|
47
|
+
* resource a built-in tool acts on — the values a preview must carry VERBATIM,
|
|
48
|
+
* however long, because an identity is parsed back out of them. The list
|
|
49
|
+
* deliberately spans BOTH taxonomies' arg shapes: Cursor's hook input names a
|
|
50
|
+
* file `file_path` and its stream names it `path`; deepagents' file tools send
|
|
51
|
+
* `file_path`; both name a shell command `command`. Extracting the same
|
|
52
|
+
* resource VALUE on both sides (the absolute path / the command string) is
|
|
53
|
+
* what lets the Cursor hook-recorded denial token equal the stream-computed
|
|
54
|
+
* token. Authored here once (moved from `execute-cursor/approval-policy.ts`
|
|
55
|
+
* in #1097) and injected into the generated preToolUse hook script
|
|
56
|
+
* so the runner and the hook never disagree on which field to match.
|
|
36
57
|
*/
|
|
58
|
+
export const SALIENT_ARG_FIELDS = ["file_path", "path", "target_notebook", "command"] as const;
|
|
59
|
+
|
|
37
60
|
/**
|
|
38
61
|
* Redact secret-keyed values (see {@link SENSITIVE_ARG_KEYS}), preserving every
|
|
39
|
-
* other entry verbatim. The
|
|
40
|
-
*
|
|
41
|
-
* header fix): full enough for the UI's path/primary-arg
|
|
42
|
-
* carrying a secret value.
|
|
62
|
+
* other entry verbatim. The first step of the preview builder, and the shape
|
|
63
|
+
* stamped as `args` on a proposed row the harness recovered from its engine's
|
|
64
|
+
* state (issue #754's header fix): full enough for the UI's path/primary-arg
|
|
65
|
+
* extraction, never carrying a secret value.
|
|
43
66
|
*/
|
|
44
67
|
export function redactSensitiveArgs(
|
|
45
68
|
args: Record<string, unknown>,
|
|
@@ -51,18 +74,6 @@ export function redactSensitiveArgs(
|
|
|
51
74
|
return redacted;
|
|
52
75
|
}
|
|
53
76
|
|
|
54
|
-
export function sanitizeArgsPreview(args: Record<string, unknown>): string {
|
|
55
|
-
const sanitized = redactSensitiveArgs(args);
|
|
56
|
-
try {
|
|
57
|
-
const json = JSON.stringify(sanitized);
|
|
58
|
-
return json.length > MAX_ARGS_PREVIEW_LENGTH
|
|
59
|
-
? json.slice(0, MAX_ARGS_PREVIEW_LENGTH) + "…"
|
|
60
|
-
: json;
|
|
61
|
-
} catch {
|
|
62
|
-
return "";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
77
|
/** Per-string-value cap for {@link buildElidedArgsPreview}. */
|
|
67
78
|
const MAX_PREVIEW_VALUE_LENGTH = 200;
|
|
68
79
|
|
|
@@ -70,18 +81,19 @@ const MAX_PREVIEW_VALUE_LENGTH = 200;
|
|
|
70
81
|
* Build a compact, ALWAYS-VALID `args_preview` from a tool call's full,
|
|
71
82
|
* authoritative arguments.
|
|
72
83
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* gate path:
|
|
84
|
+
* Leaves oversized string *values* out — every other key and the JSON
|
|
85
|
+
* structure kept — rather than truncating the whole string. Two invariants
|
|
86
|
+
* make it safe for the Cursor gate path:
|
|
77
87
|
* - It NEVER elides a salient field (the resume grant's identity — the file
|
|
78
88
|
* path or shell command — is parsed back out of this preview, so it must
|
|
79
89
|
* survive verbatim).
|
|
80
90
|
* - It redacts secret keys.
|
|
81
91
|
*
|
|
92
|
+
* For short, secret-free args the output is exactly `JSON.stringify(args)`.
|
|
82
93
|
* The heavy content (a whole-file body, a large diff) lives on `file_changes`
|
|
83
94
|
* (offloaded to a ref when large) and `args` (bounded by the size backstop), so
|
|
84
|
-
* the preview itself stays small even for a multi-MB write.
|
|
95
|
+
* the preview itself stays small even for a multi-MB write. Unserializable
|
|
96
|
+
* args (a cycle) yield `""`, never a thrown row.
|
|
85
97
|
*
|
|
86
98
|
* @param args the full tool arguments
|
|
87
99
|
* @param salientFields keys whose values must be preserved verbatim (identity)
|
|
@@ -94,15 +106,12 @@ export function buildElidedArgsPreview(
|
|
|
94
106
|
for (const [key, value] of Object.entries(args)) {
|
|
95
107
|
if (SENSITIVE_ARG_KEYS.has(key.toLowerCase())) {
|
|
96
108
|
out[key] = "[REDACTED]";
|
|
97
|
-
|
|
98
|
-
!salientFields.includes(key) &&
|
|
99
|
-
typeof value === "string" &&
|
|
100
|
-
value.length > MAX_PREVIEW_VALUE_LENGTH
|
|
101
|
-
) {
|
|
102
|
-
out[key] = `[${value.length} chars]`;
|
|
103
|
-
} else {
|
|
104
|
-
out[key] = value;
|
|
109
|
+
continue;
|
|
105
110
|
}
|
|
111
|
+
const oversized = typeof value === "string" && value.length > MAX_PREVIEW_VALUE_LENGTH;
|
|
112
|
+
// An oversized non-salient value is left out, never marked (see the header).
|
|
113
|
+
if (oversized && !salientFields.includes(key)) continue;
|
|
114
|
+
out[key] = value;
|
|
106
115
|
}
|
|
107
116
|
try {
|
|
108
117
|
return JSON.stringify(out);
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* written into the user's own tree would be committed to the session's
|
|
25
25
|
* write-back branch on completion (`git add -A`), and every real producer —
|
|
26
26
|
* the CLI's directory attachments, the approved plan the console mounts —
|
|
27
|
-
* already stays inside `inputs/` (
|
|
27
|
+
* already stays inside `inputs/` (since #1096; the proto's `/workspace/…`
|
|
28
28
|
* example is a doc issue). The prompt's `<input_files>` section and every
|
|
29
29
|
* path-derived directive are built from the RESOLVED paths, so prompt and
|
|
30
30
|
* filesystem can never disagree.
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
* {@link AttachmentResolutionError}; an archive that fails its guards
|
|
53
53
|
* aborts with the guard's own `AttachmentValidationError`.
|
|
54
54
|
*
|
|
55
|
-
* Until
|
|
56
|
-
* native harness's `attachment-injector.ts` did both and was retired
|
|
57
|
-
*
|
|
55
|
+
* Until #1096 this resolver ignored `mountPath` and could not extract; the
|
|
56
|
+
* native harness's `attachment-injector.ts` did both and was retired in that
|
|
57
|
+
* PR for this one pipeline.
|
|
58
58
|
*/
|
|
59
59
|
|
|
60
60
|
import { mkdir, copyFile, readFile, stat, writeFile } from "node:fs/promises";
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
* "the manifest promised a file extraction cannot find" is unrepresentable.
|
|
26
26
|
* The WRITE of an extracted entry is the caller's: the attachment resolver
|
|
27
27
|
* writes under the session's platform dir (`attachment-resolver.ts`), the
|
|
28
|
-
* one caller since
|
|
29
|
-
* injector
|
|
28
|
+
* one caller since #1096 retired the native injector. Moved here from that
|
|
29
|
+
* injector in the same PR so the guards have one home.
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
import { createInflateRaw } from "node:zlib";
|