@stigmer/runner 3.0.9-dev.20260616060535 → 3.1.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/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/approval-contract/types.d.ts +174 -0
- package/dist/__test-utils__/approval-contract/types.js +24 -0
- package/dist/__test-utils__/approval-contract/types.js.map +1 -0
- package/dist/activities/call-agent-status.d.ts +19 -1
- package/dist/activities/call-agent-status.js +64 -5
- package/dist/activities/call-agent-status.js.map +1 -1
- package/dist/activities/call-llm.js +19 -53
- package/dist/activities/call-llm.js.map +1 -1
- package/dist/activities/classify-tool-approvals.d.ts +24 -0
- package/dist/activities/classify-tool-approvals.js +69 -17
- package/dist/activities/classify-tool-approvals.js.map +1 -1
- package/dist/activities/discover-mcp-server.d.ts +7 -0
- package/dist/activities/discover-mcp-server.js +11 -1
- package/dist/activities/discover-mcp-server.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +140 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +130 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.d.ts +18 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +123 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -0
- package/dist/activities/execute-cursor/approval-policy.d.ts +17 -61
- package/dist/activities/execute-cursor/approval-policy.js +8 -120
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +219 -9
- package/dist/activities/execute-cursor/approval-state.js +233 -17
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +127 -0
- package/dist/activities/execute-cursor/capture-flow.js +234 -0
- package/dist/activities/execute-cursor/capture-flow.js.map +1 -0
- package/dist/activities/execute-cursor/cas-observations.d.ts +96 -0
- package/dist/activities/execute-cursor/cas-observations.js +184 -0
- package/dist/activities/execute-cursor/cas-observations.js.map +1 -0
- package/dist/activities/execute-cursor/command-provenance.d.ts +62 -0
- package/dist/activities/execute-cursor/command-provenance.js +128 -0
- package/dist/activities/execute-cursor/command-provenance.js.map +1 -0
- package/dist/activities/execute-cursor/exact-apply.d.ts +110 -0
- package/dist/activities/execute-cursor/exact-apply.js +204 -0
- package/dist/activities/execute-cursor/exact-apply.js.map +1 -0
- package/dist/activities/execute-cursor/hook-script.d.ts +53 -24
- package/dist/activities/execute-cursor/hook-script.js +310 -47
- package/dist/activities/execute-cursor/hook-script.js.map +1 -1
- package/dist/activities/execute-cursor/index.d.ts +8 -1
- package/dist/activities/execute-cursor/index.js +500 -64
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +258 -11
- package/dist/activities/execute-cursor/message-translator.js +836 -90
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +20 -23
- package/dist/activities/execute-cursor/prompt-builder.js +74 -15
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/workspace-setup.d.ts +17 -0
- package/dist/activities/execute-cursor/workspace-setup.js +212 -33
- package/dist/activities/execute-cursor/workspace-setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.d.ts +19 -0
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js +143 -0
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +88 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +81 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -0
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +47 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js +68 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -0
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +8 -1
- package/dist/activities/execute-deep-agent/attachment-injector.js +7 -7
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +42 -0
- package/dist/activities/execute-deep-agent/cas-capture-backend.js +47 -0
- package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +79 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js +112 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -0
- package/dist/activities/execute-deep-agent/hitl.d.ts +10 -0
- package/dist/activities/execute-deep-agent/hitl.js +5 -1
- package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.d.ts +2 -1
- package/dist/activities/execute-deep-agent/index.js +370 -56
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +7 -1
- package/dist/activities/execute-deep-agent/inline-publisher.js +23 -2
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +53 -2
- package/dist/activities/execute-deep-agent/setup.js +149 -92
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +36 -0
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +56 -0
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +1 -0
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +34 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.js +26 -25
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder.d.ts +11 -5
- package/dist/activities/execute-deep-agent/status-builder.js +6 -2
- package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +2 -19
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming.js +3 -15
- package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -7
- package/dist/activities/execute-deep-agent/subagent-transformer.js +23 -7
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +30 -3
- package/dist/activities/execute-deep-agent/subagent-wiring.js +29 -3
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.js +6 -2
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/claimcheck/payload-codec.js +9 -5
- package/dist/claimcheck/payload-codec.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +2 -0
- package/dist/client/stigmer-client.js +2 -0
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +85 -4
- package/dist/middleware/approval-gate.js +165 -38
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/types.d.ts +2 -5
- package/dist/shared/activity-input.d.ts +43 -0
- package/dist/shared/activity-input.js +17 -0
- package/dist/shared/activity-input.js.map +1 -0
- package/dist/shared/approval-canonicalize.d.ts +19 -0
- package/dist/shared/approval-canonicalize.js +119 -0
- package/dist/shared/approval-canonicalize.js.map +1 -0
- package/dist/shared/approval-fingerprint.d.ts +106 -0
- package/dist/shared/approval-fingerprint.js +113 -0
- package/dist/shared/approval-fingerprint.js.map +1 -0
- package/dist/shared/approval-policy.d.ts +182 -12
- package/dist/shared/approval-policy.js +213 -27
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/args-preview.d.ts +52 -0
- package/dist/shared/args-preview.js +93 -0
- package/dist/shared/args-preview.js.map +1 -0
- package/dist/shared/artifact-storage.d.ts +19 -1
- package/dist/shared/artifact-storage.js +48 -11
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/file-change.d.ts +44 -0
- package/dist/shared/file-change.js +57 -0
- package/dist/shared/file-change.js.map +1 -0
- package/dist/shared/file-tools.d.ts +107 -0
- package/dist/shared/file-tools.js +168 -0
- package/dist/shared/file-tools.js.map +1 -0
- package/dist/shared/filereview/capture.d.ts +202 -0
- package/dist/shared/filereview/capture.js +498 -0
- package/dist/shared/filereview/capture.js.map +1 -0
- package/dist/shared/filereview/cas-substrate.d.ts +190 -0
- package/dist/shared/filereview/cas-substrate.js +284 -0
- package/dist/shared/filereview/cas-substrate.js.map +1 -0
- package/dist/shared/filereview/digest.d.ts +40 -0
- package/dist/shared/filereview/digest.js +66 -0
- package/dist/shared/filereview/digest.js.map +1 -0
- package/dist/shared/filereview/events.d.ts +170 -0
- package/dist/shared/filereview/events.js +298 -0
- package/dist/shared/filereview/events.js.map +1 -0
- package/dist/shared/filereview/git-substrate.d.ts +175 -0
- package/dist/shared/filereview/git-substrate.js +439 -0
- package/dist/shared/filereview/git-substrate.js.map +1 -0
- package/dist/shared/filereview/index.d.ts +11 -0
- package/dist/shared/filereview/index.js +12 -0
- package/dist/shared/filereview/index.js.map +1 -0
- package/dist/shared/filereview/secret-paths.d.ts +63 -0
- package/dist/shared/filereview/secret-paths.js +105 -0
- package/dist/shared/filereview/secret-paths.js.map +1 -0
- package/dist/shared/fingerprint-secret.d.ts +26 -0
- package/dist/shared/fingerprint-secret.js +47 -0
- package/dist/shared/fingerprint-secret.js.map +1 -0
- package/dist/shared/model-client.d.ts +51 -0
- package/dist/shared/model-client.js +77 -0
- package/dist/shared/model-client.js.map +1 -0
- package/dist/shared/plan-artifact.js +0 -2
- package/dist/shared/plan-artifact.js.map +1 -1
- package/dist/shared/status-offload.d.ts +83 -9
- package/dist/shared/status-offload.js +399 -79
- package/dist/shared/status-offload.js.map +1 -1
- package/dist/shared/status.js +14 -1
- package/dist/shared/status.js.map +1 -1
- package/dist/shared/tool-kind.d.ts +19 -0
- package/dist/shared/tool-kind.js +13 -0
- package/dist/shared/tool-kind.js.map +1 -1
- package/dist/shared/tool-row.d.ts +88 -0
- package/dist/shared/tool-row.js +127 -0
- package/dist/shared/tool-row.js.map +1 -0
- package/dist/shared/workspace/platform-dir.d.ts +25 -0
- package/dist/shared/workspace/platform-dir.js +38 -2
- package/dist/shared/workspace/platform-dir.js.map +1 -1
- package/dist/workflows/call-agent-orchestrator.js +56 -7
- package/dist/workflows/call-agent-orchestrator.js.map +1 -1
- package/dist/workflows/connect-mcp-server.d.ts +50 -0
- package/dist/workflows/connect-mcp-server.js +136 -15
- package/dist/workflows/connect-mcp-server.js.map +1 -1
- package/dist/workflows/types.d.ts +8 -0
- package/package.json +2 -2
- package/src/__test-utils__/approval-contract/contract.ts +224 -0
- package/src/__test-utils__/approval-contract/types.ts +179 -0
- package/src/__test-utils__/fake-artifact-storage.ts +72 -0
- package/src/__tests__/approval-gateway-contract.test.ts +29 -0
- package/src/__tests__/claimcheck-codec.test.ts +16 -53
- package/src/__tests__/golden-e2e.test.ts +2 -0
- package/src/__tests__/runner-token-coordinator.test.ts +3 -3
- package/src/activities/__tests__/call-agent-status.test.ts +135 -0
- package/src/activities/__tests__/call-llm.test.ts +1 -1
- package/src/activities/__tests__/classify-tool-approvals.test.ts +208 -1
- package/src/activities/__tests__/discover-mcp-server.test.ts +30 -0
- package/src/activities/__tests__/workflow-event-activities.test.ts +2 -1
- package/src/activities/call-agent-status.ts +74 -4
- package/src/activities/call-llm.ts +18 -63
- package/src/activities/classify-tool-approvals.ts +101 -19
- package/src/activities/discover-mcp-server.ts +29 -1
- package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +216 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +148 -0
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +41 -9
- package/src/activities/execute-cursor/__tests__/approval-state.test.ts +292 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +68 -1
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +1005 -0
- package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +187 -0
- package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +97 -0
- package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +240 -0
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +203 -0
- package/src/activities/execute-cursor/__tests__/exact-apply.test.ts +375 -0
- package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +1294 -24
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +446 -0
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +384 -110
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +171 -25
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +189 -0
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +44 -23
- package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +190 -10
- package/src/activities/execute-cursor/approval-policy.ts +28 -159
- package/src/activities/execute-cursor/approval-state.ts +366 -18
- package/src/activities/execute-cursor/capture-flow.ts +323 -0
- package/src/activities/execute-cursor/cas-observations.ts +204 -0
- package/src/activities/execute-cursor/command-provenance.ts +168 -0
- package/src/activities/execute-cursor/exact-apply.ts +253 -0
- package/src/activities/execute-cursor/hook-script.ts +317 -51
- package/src/activities/execute-cursor/index.ts +575 -67
- package/src/activities/execute-cursor/message-translator.ts +963 -89
- package/src/activities/execute-cursor/prompt-builder.ts +80 -14
- package/src/activities/execute-cursor/workspace-setup.ts +257 -42
- package/src/activities/execute-deep-agent/__test-utils__/gateway-substrate.ts +180 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +134 -0
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +84 -0
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +11 -24
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +64 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-observer.test.ts +163 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +8 -5
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +342 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +2 -5
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +31 -13
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +349 -0
- package/src/activities/execute-deep-agent/__tests__/stamp-flowed-rows.test.ts +119 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +12 -11
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +9 -9
- package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +213 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +3 -6
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +84 -1
- package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +4 -1
- package/src/activities/execute-deep-agent/approval-file-change.ts +80 -0
- package/src/activities/execute-deep-agent/attachment-injector.ts +20 -11
- package/src/activities/execute-deep-agent/cas-capture-backend.ts +66 -0
- package/src/activities/execute-deep-agent/cas-capture-observer.ts +125 -0
- package/src/activities/execute-deep-agent/hitl.ts +15 -1
- package/src/activities/execute-deep-agent/index.ts +434 -64
- package/src/activities/execute-deep-agent/inline-publisher.ts +27 -4
- package/src/activities/execute-deep-agent/setup.ts +223 -125
- package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +64 -0
- package/src/activities/execute-deep-agent/status-builder-shared.ts +62 -23
- package/src/activities/execute-deep-agent/status-builder.ts +19 -7
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +2 -16
- package/src/activities/execute-deep-agent/streaming.ts +3 -13
- package/src/activities/execute-deep-agent/subagent-transformer.ts +53 -13
- package/src/activities/execute-deep-agent/subagent-wiring.ts +50 -3
- package/src/activities/execute-deep-agent/v3-status-builder.ts +8 -2
- package/src/claimcheck/payload-codec.ts +8 -8
- package/src/client/stigmer-client.ts +9 -1
- package/src/middleware/__tests__/approval-gate.test.ts +488 -4
- package/src/middleware/approval-gate.ts +247 -38
- package/src/middleware/types.ts +5 -5
- package/src/shared/__tests__/activity-input.test.ts +78 -0
- package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
- package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
- package/src/shared/__tests__/approval-policy.test.ts +274 -40
- package/src/shared/__tests__/args-preview.test.ts +78 -0
- package/src/shared/__tests__/artifact-storage-extended.test.ts +62 -10
- package/src/shared/__tests__/artifact-storage.test.ts +123 -11
- package/src/shared/__tests__/file-change.test.ts +85 -0
- package/src/shared/__tests__/file-tools.test.ts +90 -0
- package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
- package/src/shared/__tests__/lease-scope-corpus.test.ts +56 -0
- package/src/shared/__tests__/model-client.test.ts +162 -0
- package/src/shared/__tests__/plan-artifact.test.ts +11 -26
- package/src/shared/__tests__/policy-source-corpus.test.ts +58 -0
- package/src/shared/__tests__/status-offload.test.ts +573 -16
- package/src/shared/__tests__/status.test.ts +4 -5
- package/src/shared/__tests__/tool-kind.test.ts +24 -1
- package/src/shared/__tests__/tool-row.test.ts +221 -0
- package/src/shared/activity-input.ts +57 -0
- package/src/shared/approval-canonicalize.ts +159 -0
- package/src/shared/approval-fingerprint.ts +148 -0
- package/src/shared/approval-policy.ts +303 -27
- package/src/shared/args-preview.ts +98 -0
- package/src/shared/artifact-storage.ts +62 -11
- package/src/shared/checkpointer/__tests__/http-saver.test.ts +1 -2
- package/src/shared/file-change.ts +64 -0
- package/src/shared/file-tools.ts +169 -0
- package/src/shared/filereview/__tests__/capture.test.ts +856 -0
- package/src/shared/filereview/__tests__/cas-substrate.test.ts +404 -0
- package/src/shared/filereview/__tests__/digest.test.ts +100 -0
- package/src/shared/filereview/__tests__/events.test.ts +245 -0
- package/src/shared/filereview/__tests__/git-substrate.test.ts +362 -0
- package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +286 -0
- package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
- package/src/shared/filereview/capture.ts +727 -0
- package/src/shared/filereview/cas-substrate.ts +401 -0
- package/src/shared/filereview/digest.ts +83 -0
- package/src/shared/filereview/events.ts +449 -0
- package/src/shared/filereview/git-substrate.ts +555 -0
- package/src/shared/filereview/index.ts +60 -0
- package/src/shared/filereview/secret-paths.ts +121 -0
- package/src/shared/fingerprint-secret.ts +53 -0
- package/src/shared/model-client.ts +122 -0
- package/src/shared/plan-artifact.ts +0 -2
- package/src/shared/status-offload.ts +433 -77
- package/src/shared/status.ts +13 -0
- package/src/shared/tool-kind.ts +33 -0
- package/src/shared/tool-row.ts +135 -0
- package/src/shared/workspace/platform-dir.ts +41 -2
- package/src/workflow-engine/__tests__/golden-execution.test.ts +35 -18
- package/src/workflow-engine/__tests__/tasks/try.test.ts +1 -1
- package/src/workflows/__tests__/connect-mcp-server.test.ts +304 -29
- package/src/workflows/call-agent-orchestrator.ts +53 -6
- package/src/workflows/connect-mcp-server.ts +179 -24
- package/src/workflows/types.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-policy.js","sourceRoot":"","sources":["../../src/shared/approval-policy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"approval-policy.js","sourceRoot":"","sources":["../../src/shared/approval-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-agnostic sanitization of tool arguments for the `args_preview` field.
|
|
3
|
+
*
|
|
4
|
+
* `args_preview` is the human-readable, UI-facing projection of a tool call's
|
|
5
|
+
* arguments. It is surfaced on the approval card, the CLI, and the web console,
|
|
6
|
+
* and — for the Cursor harness — it is the field a resumed turn parses to rebuild
|
|
7
|
+
* an approval grant's salient identity. So it must always be SMALL and VALID
|
|
8
|
+
* JSON: the per-tool offload does not touch it, and the aggregate size backstop
|
|
9
|
+
* would replace an oversized preview with an unparseable marker.
|
|
10
|
+
*
|
|
11
|
+
* This module is the single home for arg sanitization shared by both harnesses
|
|
12
|
+
* (native re-exports {@link sanitizeArgsPreview} from its status builders; the
|
|
13
|
+
* Cursor gate path uses {@link buildElidedArgsPreview}).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Argument keys whose values are secrets and must never appear in a preview.
|
|
17
|
+
* Matched case-insensitively against the top-level key name.
|
|
18
|
+
*/
|
|
19
|
+
export declare const SENSITIVE_ARG_KEYS: ReadonlySet<string>;
|
|
20
|
+
/** Whole-preview length cap for {@link sanitizeArgsPreview} (native). */
|
|
21
|
+
export declare const MAX_ARGS_PREVIEW_LENGTH = 500;
|
|
22
|
+
/**
|
|
23
|
+
* Sanitize args into a compact preview string (native harness behavior).
|
|
24
|
+
*
|
|
25
|
+
* Redacts sensitive keys, then truncates the whole JSON to a fixed length. The
|
|
26
|
+
* truncation can yield invalid JSON, which is acceptable for the native harness
|
|
27
|
+
* (its resume model keys on `tool_call_id`, never on a re-parsed preview). The
|
|
28
|
+
* Cursor gate path must instead use {@link buildElidedArgsPreview}, which keeps
|
|
29
|
+
* the JSON valid and preserves the salient identity fields.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sanitizeArgsPreview(args: Record<string, unknown>): string;
|
|
32
|
+
/**
|
|
33
|
+
* Build a compact, ALWAYS-VALID `args_preview` from a tool call's full,
|
|
34
|
+
* authoritative arguments.
|
|
35
|
+
*
|
|
36
|
+
* Unlike {@link sanitizeArgsPreview} (which truncates the whole string, possibly
|
|
37
|
+
* to invalid JSON), this elides oversized string *values* in place — preserving
|
|
38
|
+
* every key and the JSON structure. Two invariants make it safe for the Cursor
|
|
39
|
+
* gate path:
|
|
40
|
+
* - It NEVER elides a salient field (the resume grant's identity — the file
|
|
41
|
+
* path or shell command — is parsed back out of this preview, so it must
|
|
42
|
+
* survive verbatim).
|
|
43
|
+
* - It redacts secret keys.
|
|
44
|
+
*
|
|
45
|
+
* The heavy content (a whole-file body, a large diff) lives on `file_changes`
|
|
46
|
+
* (offloaded to a ref when large) and `args` (bounded by the size backstop), so
|
|
47
|
+
* the preview itself stays small even for a multi-MB write.
|
|
48
|
+
*
|
|
49
|
+
* @param args the full tool arguments
|
|
50
|
+
* @param salientFields keys whose values must be preserved verbatim (identity)
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildElidedArgsPreview(args: Record<string, unknown>, salientFields: readonly string[]): string;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-agnostic sanitization of tool arguments for the `args_preview` field.
|
|
3
|
+
*
|
|
4
|
+
* `args_preview` is the human-readable, UI-facing projection of a tool call's
|
|
5
|
+
* arguments. It is surfaced on the approval card, the CLI, and the web console,
|
|
6
|
+
* and — for the Cursor harness — it is the field a resumed turn parses to rebuild
|
|
7
|
+
* an approval grant's salient identity. So it must always be SMALL and VALID
|
|
8
|
+
* JSON: the per-tool offload does not touch it, and the aggregate size backstop
|
|
9
|
+
* would replace an oversized preview with an unparseable marker.
|
|
10
|
+
*
|
|
11
|
+
* This module is the single home for arg sanitization shared by both harnesses
|
|
12
|
+
* (native re-exports {@link sanitizeArgsPreview} from its status builders; the
|
|
13
|
+
* Cursor gate path uses {@link buildElidedArgsPreview}).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Argument keys whose values are secrets and must never appear in a preview.
|
|
17
|
+
* Matched case-insensitively against the top-level key name.
|
|
18
|
+
*/
|
|
19
|
+
export const SENSITIVE_ARG_KEYS = new Set([
|
|
20
|
+
"password", "token", "secret", "api_key", "apikey",
|
|
21
|
+
"credentials", "auth", "authorization",
|
|
22
|
+
]);
|
|
23
|
+
/** Whole-preview length cap for {@link sanitizeArgsPreview} (native). */
|
|
24
|
+
export const MAX_ARGS_PREVIEW_LENGTH = 500;
|
|
25
|
+
/**
|
|
26
|
+
* Sanitize args into a compact preview string (native harness behavior).
|
|
27
|
+
*
|
|
28
|
+
* Redacts sensitive keys, then truncates the whole JSON to a fixed length. The
|
|
29
|
+
* truncation can yield invalid JSON, which is acceptable for the native harness
|
|
30
|
+
* (its resume model keys on `tool_call_id`, never on a re-parsed preview). The
|
|
31
|
+
* Cursor gate path must instead use {@link buildElidedArgsPreview}, which keeps
|
|
32
|
+
* the JSON valid and preserves the salient identity fields.
|
|
33
|
+
*/
|
|
34
|
+
export function sanitizeArgsPreview(args) {
|
|
35
|
+
const sanitized = {};
|
|
36
|
+
for (const [key, value] of Object.entries(args)) {
|
|
37
|
+
sanitized[key] = SENSITIVE_ARG_KEYS.has(key.toLowerCase()) ? "[REDACTED]" : value;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const json = JSON.stringify(sanitized);
|
|
41
|
+
return json.length > MAX_ARGS_PREVIEW_LENGTH
|
|
42
|
+
? json.slice(0, MAX_ARGS_PREVIEW_LENGTH) + "…"
|
|
43
|
+
: json;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Per-string-value cap for {@link buildElidedArgsPreview}. */
|
|
50
|
+
const MAX_PREVIEW_VALUE_LENGTH = 200;
|
|
51
|
+
/**
|
|
52
|
+
* Build a compact, ALWAYS-VALID `args_preview` from a tool call's full,
|
|
53
|
+
* authoritative arguments.
|
|
54
|
+
*
|
|
55
|
+
* Unlike {@link sanitizeArgsPreview} (which truncates the whole string, possibly
|
|
56
|
+
* to invalid JSON), this elides oversized string *values* in place — preserving
|
|
57
|
+
* every key and the JSON structure. Two invariants make it safe for the Cursor
|
|
58
|
+
* gate path:
|
|
59
|
+
* - It NEVER elides a salient field (the resume grant's identity — the file
|
|
60
|
+
* path or shell command — is parsed back out of this preview, so it must
|
|
61
|
+
* survive verbatim).
|
|
62
|
+
* - It redacts secret keys.
|
|
63
|
+
*
|
|
64
|
+
* The heavy content (a whole-file body, a large diff) lives on `file_changes`
|
|
65
|
+
* (offloaded to a ref when large) and `args` (bounded by the size backstop), so
|
|
66
|
+
* the preview itself stays small even for a multi-MB write.
|
|
67
|
+
*
|
|
68
|
+
* @param args the full tool arguments
|
|
69
|
+
* @param salientFields keys whose values must be preserved verbatim (identity)
|
|
70
|
+
*/
|
|
71
|
+
export function buildElidedArgsPreview(args, salientFields) {
|
|
72
|
+
const out = {};
|
|
73
|
+
for (const [key, value] of Object.entries(args)) {
|
|
74
|
+
if (SENSITIVE_ARG_KEYS.has(key.toLowerCase())) {
|
|
75
|
+
out[key] = "[REDACTED]";
|
|
76
|
+
}
|
|
77
|
+
else if (!salientFields.includes(key) &&
|
|
78
|
+
typeof value === "string" &&
|
|
79
|
+
value.length > MAX_PREVIEW_VALUE_LENGTH) {
|
|
80
|
+
out[key] = `[${value.length} chars]`;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
out[key] = value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return JSON.stringify(out);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return "";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=args-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args-preview.js","sourceRoot":"","sources":["../../src/shared/args-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ;IAClD,aAAa,EAAE,MAAM,EAAE,eAAe;CACvC,CAAC,CAAC;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAC/D,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,SAAS,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC;IACpF,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,MAAM,GAAG,uBAAuB;YAC1C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,GAAG,GAAG;YAC9C,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA6B,EAC7B,aAAgC;IAEhC,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC9C,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;QAC1B,CAAC;aAAM,IACL,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC5B,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,CAAC,MAAM,GAAG,wBAAwB,EACvC,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,MAAM,SAAS,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* Artifact storage abstraction for the unified runner.
|
|
3
3
|
*
|
|
4
4
|
* Two backends:
|
|
5
|
-
* - Local: writes to the filesystem
|
|
5
|
+
* - Local: writes to the filesystem (OSS mode). The runner reads its own
|
|
6
|
+
* artifacts straight back off disk via {@link ArtifactStorage.download} — the
|
|
7
|
+
* exact inverse of {@link ArtifactStorage.upload}. `getDownloadUrl` still
|
|
8
|
+
* returns the stigmer-server serve URL, but that is for OTHER consumers (the
|
|
9
|
+
* web console fetching an artifact for display), not the runner's own reads.
|
|
6
10
|
* - Proxy: uses presigned URLs from the Stigmer Side-Channel Proxy (cloud mode).
|
|
11
|
+
* Here `download` resolves a presigned URL and fetches it over HTTPS.
|
|
7
12
|
*
|
|
8
13
|
* The runner never holds R2/S3 credentials — in cloud mode it calls the proxy
|
|
9
14
|
* to obtain a presigned upload URL, then PUTs content over plain HTTPS.
|
|
@@ -14,6 +19,17 @@ import type { Config } from "../config.js";
|
|
|
14
19
|
export interface ArtifactStorage {
|
|
15
20
|
upload(key: string, content: Buffer, contentType?: string): Promise<string>;
|
|
16
21
|
getDownloadUrl(key: string): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Read an artifact's raw bytes by key — the inverse of {@link upload} and the
|
|
24
|
+
* single read path for all runner read-back (CAS reconcile, exact-apply,
|
|
25
|
+
* claimcheck decode, attachment injection).
|
|
26
|
+
*
|
|
27
|
+
* Returns the exact stored bytes, or throws a descriptive, key-scoped `Error`
|
|
28
|
+
* when the object is missing or the transport fails. Per-backend semantics:
|
|
29
|
+
* local reads directly off disk; proxy resolves a presigned URL and fetches
|
|
30
|
+
* it. Callers own their own error-wrapping / degradation policy.
|
|
31
|
+
*/
|
|
32
|
+
download(key: string): Promise<Buffer>;
|
|
17
33
|
exists(key: string): Promise<boolean>;
|
|
18
34
|
}
|
|
19
35
|
export type ArtifactStorageType = "local" | "proxy";
|
|
@@ -23,6 +39,7 @@ export declare class LocalArtifactStorage implements ArtifactStorage {
|
|
|
23
39
|
constructor(basePath: string, serveUrlBase: string);
|
|
24
40
|
upload(key: string, content: Buffer, _contentType?: string): Promise<string>;
|
|
25
41
|
getDownloadUrl(key: string): Promise<string>;
|
|
42
|
+
download(key: string): Promise<Buffer>;
|
|
26
43
|
exists(key: string): Promise<boolean>;
|
|
27
44
|
}
|
|
28
45
|
export declare class ProxyArtifactStorage implements ArtifactStorage {
|
|
@@ -31,6 +48,7 @@ export declare class ProxyArtifactStorage implements ArtifactStorage {
|
|
|
31
48
|
constructor(proxyEndpoint: string, authToken: string);
|
|
32
49
|
upload(key: string, content: Buffer, contentType?: string): Promise<string>;
|
|
33
50
|
getDownloadUrl(key: string): Promise<string>;
|
|
51
|
+
download(key: string): Promise<Buffer>;
|
|
34
52
|
exists(key: string): Promise<boolean>;
|
|
35
53
|
}
|
|
36
54
|
export interface ArtifactStorageConfig {
|
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
* Artifact storage abstraction for the unified runner.
|
|
3
3
|
*
|
|
4
4
|
* Two backends:
|
|
5
|
-
* - Local: writes to the filesystem
|
|
5
|
+
* - Local: writes to the filesystem (OSS mode). The runner reads its own
|
|
6
|
+
* artifacts straight back off disk via {@link ArtifactStorage.download} — the
|
|
7
|
+
* exact inverse of {@link ArtifactStorage.upload}. `getDownloadUrl` still
|
|
8
|
+
* returns the stigmer-server serve URL, but that is for OTHER consumers (the
|
|
9
|
+
* web console fetching an artifact for display), not the runner's own reads.
|
|
6
10
|
* - Proxy: uses presigned URLs from the Stigmer Side-Channel Proxy (cloud mode).
|
|
11
|
+
* Here `download` resolves a presigned URL and fetches it over HTTPS.
|
|
7
12
|
*
|
|
8
13
|
* The runner never holds R2/S3 credentials — in cloud mode it calls the proxy
|
|
9
14
|
* to obtain a presigned upload URL, then PUTs content over plain HTTPS.
|
|
10
15
|
*
|
|
11
16
|
* DD-6: No direct R2 backend. Local + Proxy only.
|
|
12
17
|
*/
|
|
13
|
-
import { mkdir, writeFile, access } from "node:fs/promises";
|
|
18
|
+
import { mkdir, writeFile, readFile, access } from "node:fs/promises";
|
|
14
19
|
import { dirname, join } from "node:path";
|
|
15
20
|
// ── Local Backend ────────────────────────────────────────────────────
|
|
16
21
|
export class LocalArtifactStorage {
|
|
@@ -29,6 +34,18 @@ export class LocalArtifactStorage {
|
|
|
29
34
|
async getDownloadUrl(key) {
|
|
30
35
|
return `${this.serveUrlBase}/${key}`;
|
|
31
36
|
}
|
|
37
|
+
async download(key) {
|
|
38
|
+
// Direct disk read — the exact inverse of `upload`. The runner wrote these
|
|
39
|
+
// bytes to `basePath`, so it reads them back without a self-HTTP round-trip
|
|
40
|
+
// and without depending on the serve URL being set or reachable.
|
|
41
|
+
try {
|
|
42
|
+
return await readFile(join(this.basePath, key));
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
46
|
+
throw new Error(`Artifact not found for key '${key}': ${reason}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
32
49
|
async exists(key) {
|
|
33
50
|
try {
|
|
34
51
|
await access(join(this.basePath, key));
|
|
@@ -112,21 +129,41 @@ export class ProxyArtifactStorage {
|
|
|
112
129
|
const data = await resp.json();
|
|
113
130
|
return data.url;
|
|
114
131
|
}
|
|
132
|
+
async download(key) {
|
|
133
|
+
const url = await this.getDownloadUrl(key);
|
|
134
|
+
const resp = await fetch(url);
|
|
135
|
+
if (!resp.ok) {
|
|
136
|
+
throw new Error(`Artifact download failed (HTTP ${resp.status}) for key '${key}': ` +
|
|
137
|
+
await resp.text());
|
|
138
|
+
}
|
|
139
|
+
return Buffer.from(await resp.arrayBuffer());
|
|
140
|
+
}
|
|
115
141
|
async exists(key) {
|
|
142
|
+
// A presigned URL is minted for ANY key — the presign endpoint does not check
|
|
143
|
+
// the object — so "did presign succeed?" is NOT existence (that bug turned a
|
|
144
|
+
// git-only file-review reconcile into a doomed manifest download + 404 crash).
|
|
145
|
+
// Probe the object itself with a 1-byte ranged GET: the presigned URL is
|
|
146
|
+
// SigV4-signed for GET (a HEAD would break the signature), and `Range:
|
|
147
|
+
// bytes=0-0` transfers at most one byte. Missing => 404; present => 200/206
|
|
148
|
+
// (or 416 for a 0-byte object, whose range is unsatisfiable yet it exists).
|
|
149
|
+
let url;
|
|
116
150
|
try {
|
|
117
|
-
|
|
118
|
-
method: "POST",
|
|
119
|
-
headers: {
|
|
120
|
-
"Authorization": `Bearer ${this.authToken}`,
|
|
121
|
-
"Content-Type": "application/json",
|
|
122
|
-
},
|
|
123
|
-
body: JSON.stringify({ key }),
|
|
124
|
-
});
|
|
125
|
-
return resp.ok;
|
|
151
|
+
url = await this.getDownloadUrl(key);
|
|
126
152
|
}
|
|
127
153
|
catch {
|
|
154
|
+
// Presign endpoint unreachable: report absent. The sole caller (content-
|
|
155
|
+
// addressed CAS blob dedup) then re-uploads, which is idempotent.
|
|
128
156
|
return false;
|
|
129
157
|
}
|
|
158
|
+
const resp = await fetch(url, { headers: { Range: "bytes=0-0" } });
|
|
159
|
+
await resp.arrayBuffer().catch(() => undefined); // drain the <=1-byte body
|
|
160
|
+
if (resp.status === 404)
|
|
161
|
+
return false;
|
|
162
|
+
if (resp.status === 200 || resp.status === 206 || resp.status === 416)
|
|
163
|
+
return true;
|
|
164
|
+
// Any other status (e.g. 403 expired/misconfigured, 5xx) is a real fault, not
|
|
165
|
+
// an existence answer — surface it rather than silently mis-reporting.
|
|
166
|
+
throw new Error(`Artifact existence check failed (HTTP ${resp.status}) for key '${key}'`);
|
|
130
167
|
}
|
|
131
168
|
}
|
|
132
169
|
export function loadArtifactStorageConfig(config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-storage.js","sourceRoot":"","sources":["../../src/shared/artifact-storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"artifact-storage.js","sourceRoot":"","sources":["../../src/shared/artifact-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure path + binary-detection helpers shared by the native (deepagents) and
|
|
3
|
+
* Cursor harnesses' file-review capture.
|
|
4
|
+
*
|
|
5
|
+
* Deliberately dependency-free and side-effect-free: no file IO, no diff
|
|
6
|
+
* computation, no proto knowledge. `resolveWorkspacePath` normalizes a touched
|
|
7
|
+
* path to (display path, absolute path); `looksBinary`/`bytesLookBinary` are the
|
|
8
|
+
* single definition of "binary" across every capture substrate.
|
|
9
|
+
*
|
|
10
|
+
* @since First-Class Diff Review (#186)
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Heuristic binary detection: a NUL byte never appears in valid UTF-8 text. This
|
|
14
|
+
* is a safety net, not a feature — the native edit/write tools are string-based,
|
|
15
|
+
* so captured content is text in practice.
|
|
16
|
+
*/
|
|
17
|
+
export declare function looksBinary(content: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Byte-level binary detection: a NUL byte never appears in valid UTF-8 text. The
|
|
20
|
+
* single definition of "binary" shared by every substrate that reads raw bytes
|
|
21
|
+
* (the git substrate's blob reads and the CAS substrate's captured bodies), so
|
|
22
|
+
* "what is binary" is decided one way across the whole file-review subsystem.
|
|
23
|
+
*
|
|
24
|
+
* Prefer this over {@link looksBinary} whenever the raw bytes are in hand: it is
|
|
25
|
+
* exact, whereas scanning a UTF-8-decoded string can miss a NUL that a lossy
|
|
26
|
+
* decode dropped.
|
|
27
|
+
*/
|
|
28
|
+
export declare function bytesLookBinary(bytes: Uint8Array): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Derive the workspace-root-relative display path and the absolute on-disk path
|
|
31
|
+
* for a file a tool touched.
|
|
32
|
+
*
|
|
33
|
+
* `virtualRoot` distinguishes the two harness path conventions:
|
|
34
|
+
* - native (deepagents) addresses files against a virtual root where a leading
|
|
35
|
+
* "/" denotes the workspace root — mirrors `InlinePublisher.normalizePath`;
|
|
36
|
+
* - Cursor passes real filesystem paths that may be absolute.
|
|
37
|
+
*
|
|
38
|
+
* A path that is absolute but outside `rootDir` is displayed as-is (we never
|
|
39
|
+
* surface an escaping `../../` relative path).
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveWorkspacePath(rawPath: string, rootDir: string, virtualRoot: boolean): {
|
|
42
|
+
path: string;
|
|
43
|
+
absolutePath: string;
|
|
44
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure path + binary-detection helpers shared by the native (deepagents) and
|
|
3
|
+
* Cursor harnesses' file-review capture.
|
|
4
|
+
*
|
|
5
|
+
* Deliberately dependency-free and side-effect-free: no file IO, no diff
|
|
6
|
+
* computation, no proto knowledge. `resolveWorkspacePath` normalizes a touched
|
|
7
|
+
* path to (display path, absolute path); `looksBinary`/`bytesLookBinary` are the
|
|
8
|
+
* single definition of "binary" across every capture substrate.
|
|
9
|
+
*
|
|
10
|
+
* @since First-Class Diff Review (#186)
|
|
11
|
+
*/
|
|
12
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
13
|
+
/**
|
|
14
|
+
* Heuristic binary detection: a NUL byte never appears in valid UTF-8 text. This
|
|
15
|
+
* is a safety net, not a feature — the native edit/write tools are string-based,
|
|
16
|
+
* so captured content is text in practice.
|
|
17
|
+
*/
|
|
18
|
+
export function looksBinary(content) {
|
|
19
|
+
return content.includes("\u0000");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Byte-level binary detection: a NUL byte never appears in valid UTF-8 text. The
|
|
23
|
+
* single definition of "binary" shared by every substrate that reads raw bytes
|
|
24
|
+
* (the git substrate's blob reads and the CAS substrate's captured bodies), so
|
|
25
|
+
* "what is binary" is decided one way across the whole file-review subsystem.
|
|
26
|
+
*
|
|
27
|
+
* Prefer this over {@link looksBinary} whenever the raw bytes are in hand: it is
|
|
28
|
+
* exact, whereas scanning a UTF-8-decoded string can miss a NUL that a lossy
|
|
29
|
+
* decode dropped.
|
|
30
|
+
*/
|
|
31
|
+
export function bytesLookBinary(bytes) {
|
|
32
|
+
return bytes.includes(0);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Derive the workspace-root-relative display path and the absolute on-disk path
|
|
36
|
+
* for a file a tool touched.
|
|
37
|
+
*
|
|
38
|
+
* `virtualRoot` distinguishes the two harness path conventions:
|
|
39
|
+
* - native (deepagents) addresses files against a virtual root where a leading
|
|
40
|
+
* "/" denotes the workspace root — mirrors `InlinePublisher.normalizePath`;
|
|
41
|
+
* - Cursor passes real filesystem paths that may be absolute.
|
|
42
|
+
*
|
|
43
|
+
* A path that is absolute but outside `rootDir` is displayed as-is (we never
|
|
44
|
+
* surface an escaping `../../` relative path).
|
|
45
|
+
*/
|
|
46
|
+
export function resolveWorkspacePath(rawPath, rootDir, virtualRoot) {
|
|
47
|
+
if (virtualRoot || !isAbsolute(rawPath)) {
|
|
48
|
+
const rel = rawPath.replace(/^\/+/, "").replace(/^\.\//, "");
|
|
49
|
+
return { path: rel, absolutePath: join(rootDir, rel) };
|
|
50
|
+
}
|
|
51
|
+
const rel = relative(rootDir, rawPath);
|
|
52
|
+
if (rel && !rel.startsWith("..") && !isAbsolute(rel)) {
|
|
53
|
+
return { path: rel, absolutePath: rawPath };
|
|
54
|
+
}
|
|
55
|
+
return { path: rawPath, absolutePath: rawPath };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=file-change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-change.js","sourceRoot":"","sources":["../../src/shared/file-change.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEvD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,KAAiB;IAC/C,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,OAAe,EACf,WAAoB;IAEpB,IAAI,WAAW,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Introspection of file-modifying tools, shared by every runner surface that
|
|
3
|
+
* reacts to a file edit: the native (deepagents) streaming side-effects (publish,
|
|
4
|
+
* git writeback, post-exec file-change capture), the Cursor streaming capture,
|
|
5
|
+
* and BOTH harnesses' approval-gate pre-execution capture (shared/gate-file-change.ts).
|
|
6
|
+
*
|
|
7
|
+
* This is the single source of truth for "which tools mutate files" and "where
|
|
8
|
+
* their path / whole-file content / edit replacement lives in the tool
|
|
9
|
+
* arguments". It is deliberately pure — no IO, no proto knowledge — so the same
|
|
10
|
+
* identification logic is used whether args come from a streamed `on_tool_*`
|
|
11
|
+
* event, a v3 protocol event, an AI-message tool call read out of graph state at
|
|
12
|
+
* an interrupt, or the Cursor preToolUse hook's captured `tool_input`.
|
|
13
|
+
*
|
|
14
|
+
* Both taxonomies are covered in one place on purpose: the deepagents harness
|
|
15
|
+
* names a file write `write_file`/`write`, the Cursor SDK stream names it
|
|
16
|
+
* `edit`/`write`, and the Cursor preToolUse hook names it `Write`/`StrReplace`/
|
|
17
|
+
* `EditNotebook`. The four extractors below span every arg-field name these
|
|
18
|
+
* surfaces use, so a single capture path is correct for all of them.
|
|
19
|
+
*
|
|
20
|
+
* @since First-Class Diff Review (#186); cross-harness gate unification (HITL diff)
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The file-modifying tools, across both harness taxonomies.
|
|
24
|
+
*
|
|
25
|
+
* - deepagents (native): `write_file`/`edit_file`/`create_file` (stream) and
|
|
26
|
+
* `write`/`edit`/`create`/`str_replace_editor` (SDK names);
|
|
27
|
+
* - Cursor: `write`/`edit` (SDK stream, shared with native) and
|
|
28
|
+
* `Write`/`StrReplace`/`EditNotebook` (preToolUse hook + tool names).
|
|
29
|
+
*
|
|
30
|
+
* Delete is intentionally absent: it has no whole-file content or hunk to
|
|
31
|
+
* preview, so it is not "file-modifying" in the diff-capture sense.
|
|
32
|
+
*/
|
|
33
|
+
export declare const FILE_MODIFYING_TOOLS: ReadonlySet<string>;
|
|
34
|
+
/** Whether `toolName` is a file-modifying tool in either harness taxonomy. */
|
|
35
|
+
export declare function isFileModifyingTool(toolName: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Extract the target file path from a file-modifying tool's arguments. Returns
|
|
38
|
+
* `null` when no recognized path key is present. The key set is the union across
|
|
39
|
+
* both taxonomies: deepagents/Cursor write+edit use `path`/`file_path`; a Cursor
|
|
40
|
+
* notebook edit uses `target_notebook`; the rest are defensive against drift.
|
|
41
|
+
*/
|
|
42
|
+
export declare function extractFilePath(args: Record<string, unknown>): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Top-level arg keys, in priority order, that carry a write-family tool's
|
|
45
|
+
* WHOLE-FILE body, across both harness taxonomies (Cursor `Write` uses
|
|
46
|
+
* `content`; the SDK stream uses `contents`). Exported so the generated Cursor
|
|
47
|
+
* hook injects the SAME list into its inline content-digest extractor — the
|
|
48
|
+
* field names diverge across the hook/stream layers, so a single shared list is
|
|
49
|
+
* what keeps the runner-side and hook-side digests byte-identical.
|
|
50
|
+
*/
|
|
51
|
+
export declare const WRITE_CONTENT_FIELDS: readonly ["content", "contents", "file_content"];
|
|
52
|
+
/**
|
|
53
|
+
* Extract the WHOLE-FILE content from a write-family tool's arguments. Returns
|
|
54
|
+
* `null` for an edit-family call (which carries `old_string`/`new_string`, not a
|
|
55
|
+
* whole-file body) or when no content key is present. An empty string is a real
|
|
56
|
+
* value (an empty file) and is preserved.
|
|
57
|
+
*
|
|
58
|
+
* Critical: this is kept strictly separate from {@link extractEditNewString}.
|
|
59
|
+
* `new_string` is an edit replacement fragment, NOT whole-file content;
|
|
60
|
+
* conflating the two would make an edit look like a whole-file capture and read
|
|
61
|
+
* the wrong `before` at the gate.
|
|
62
|
+
*/
|
|
63
|
+
export declare function extractWriteContent(args: Record<string, unknown>): string | null;
|
|
64
|
+
/**
|
|
65
|
+
* Top-level arg keys for an edit-family tool's pre-/post-edit fragments, across
|
|
66
|
+
* both taxonomies. Exported for the same reason as {@link WRITE_CONTENT_FIELDS}:
|
|
67
|
+
* the Cursor hook injects them into its inline digest extractor so its content
|
|
68
|
+
* digest matches the runner's byte-for-byte.
|
|
69
|
+
*/
|
|
70
|
+
export declare const EDIT_OLD_FIELDS: readonly ["old_string", "old_text", "oldText"];
|
|
71
|
+
export declare const EDIT_NEW_FIELDS: readonly ["new_string", "new_text", "newText", "replacement"];
|
|
72
|
+
/**
|
|
73
|
+
* Extract an edit-family tool's pre-edit fragment (`old_string` and its
|
|
74
|
+
* variants). Returns `null` when absent; an empty string is preserved (an
|
|
75
|
+
* insertion has an empty `old_string`), matching the native gate capture.
|
|
76
|
+
*/
|
|
77
|
+
export declare function extractEditOldString(args: Record<string, unknown>): string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Extract an edit-family tool's post-edit fragment (`new_string` and its
|
|
80
|
+
* variants, including `replacement`). Returns `null` when absent; an empty
|
|
81
|
+
* string is preserved (a deletion has an empty `new_string`).
|
|
82
|
+
*/
|
|
83
|
+
export declare function extractEditNewString(args: Record<string, unknown>): string | null;
|
|
84
|
+
/**
|
|
85
|
+
* Stable content digest of a file-mutating tool call's arguments — the content
|
|
86
|
+
* discriminator the deny-only Cursor HITL identity adds on top of
|
|
87
|
+
* (category, path) so a DIFFERENT edit to the same file re-gates rather than
|
|
88
|
+
* riding an earlier approval through.
|
|
89
|
+
*
|
|
90
|
+
* It hashes ONLY the edit content, never the path (the path is the identity's
|
|
91
|
+
* "salient" already). A whole-file write hashes its body; an edit hashes its
|
|
92
|
+
* (old, new) fragment pair. Returns "" for a call with no recoverable edit
|
|
93
|
+
* content — a shell command, a delete, a read, an MCP tool, or the hook's
|
|
94
|
+
* grep-fallback denial — which keep the coarse (category, salient) identity
|
|
95
|
+
* (already content-exact for a command / delete path).
|
|
96
|
+
*
|
|
97
|
+
* THE FORMAT IS A CROSS-LAYER CONTRACT. The Cursor preToolUse hook recomputes
|
|
98
|
+
* this digest inline from `tool_input`, running the SAME Node binary as the
|
|
99
|
+
* runner (see buildContentDigestScript in execute-cursor/hook-script.ts), so the
|
|
100
|
+
* two values must be byte-identical — any change here MUST be mirrored there.
|
|
101
|
+
* JSON.stringify of a fixed-shape string array is deterministic and identical on
|
|
102
|
+
* both sides; the leading tag ("w"/"e") keeps a write body from ever colliding
|
|
103
|
+
* with an edit pair, and the union field lists above are injected into the hook
|
|
104
|
+
* so both extract the same value despite the file_path/path & content/contents
|
|
105
|
+
* cross-layer name divergence.
|
|
106
|
+
*/
|
|
107
|
+
export declare function contentDigest(args: Record<string, unknown>): string;
|