@stigmer/runner 3.0.9-dev.20260615153829 → 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 +16 -3
- package/dist/activities/execute-deep-agent/hitl.js +11 -3
- 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 +393 -33
- 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 +17 -5
- package/dist/activities/execute-deep-agent/status-builder.js +44 -3
- 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 +32 -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 +284 -0
- package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +14 -36
- 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 +91 -10
- 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 +23 -7
- package/src/activities/execute-deep-agent/index.ts +463 -40
- 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 +63 -8
- 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 +36 -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
|
@@ -16,15 +16,96 @@
|
|
|
16
16
|
* pausing again.
|
|
17
17
|
*
|
|
18
18
|
* Platform tool defaults: DeepAgents JS backend tools (read, write,
|
|
19
|
-
* edit, execute, etc.) are not covered by MCP policy chains.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* edit, execute, etc.) are not covered by MCP policy chains. Built-in tools
|
|
20
|
+
* are classified through the shared {@link toolApprovalCategory} — the single
|
|
21
|
+
* source of truth, shared with the Cursor deny-oracle hook — so read-only tools
|
|
22
|
+
* are auto-approved and every mutating tool (write/edit/delete/shell) is gated
|
|
23
|
+
* fail-CLOSED, by category rather than by a hand-maintained name list. An
|
|
24
|
+
* unrecognized mutating built-in (e.g. `bash`, `overwrite_file`) is therefore
|
|
25
|
+
* gated by what it does, not by whether someone remembered to list it.
|
|
26
|
+
*
|
|
27
|
+
* Gateway invariant (Phase 2): this middleware IS the in-process execution
|
|
28
|
+
* gateway for the deep-agent harness — `handler(request)` is the side effect. A
|
|
29
|
+
* side effect runs only with a backing authorization: either (a) the tool was
|
|
30
|
+
* auto-approved (policy/classifier cleared it, or auto-approve-all disabled the
|
|
31
|
+
* whole gate), or (b) the user explicitly approved THIS interrupted call. Every
|
|
32
|
+
* other outcome — skip, reject, or an unrecognized decision — returns a
|
|
33
|
+
* ToolMessage WITHOUT executing. There is no path from a model proposal to a
|
|
34
|
+
* side effect that skips an authorization.
|
|
35
|
+
*
|
|
36
|
+
* Shadow ExecutionReceipt: when the gateway lets a side effect through it emits a
|
|
37
|
+
* structured, non-persisted receipt (a `[hitl-gateway] receipt …` log carrying
|
|
38
|
+
* the action's HMAC fingerprint and the authorization source). This is an audit
|
|
39
|
+
* + uniformity signal only — no proto, no storage — mirroring the Phase-1 shadow
|
|
40
|
+
* discipline. On the deep-agent normal path the fingerprint match is guaranteed
|
|
41
|
+
* by LangGraph checkpoint replay (the resumed action equals the approved one), so
|
|
42
|
+
* the receipt is defense-in-depth here; the fingerprint earns real enforcement
|
|
43
|
+
* teeth in the out-of-process Cursor substrate.
|
|
22
44
|
*/
|
|
23
45
|
import type { StigmerMiddleware } from "./types.js";
|
|
24
46
|
import { type MergedToolPolicy } from "../shared/approval-policy.js";
|
|
47
|
+
import { type ToolApprovalCategory } from "../shared/tool-kind.js";
|
|
48
|
+
import { type FingerprintKey } from "../shared/approval-fingerprint.js";
|
|
25
49
|
export interface ApprovalGateConfig {
|
|
26
50
|
readonly policies: ReadonlyMap<string, MergedToolPolicy>;
|
|
27
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Built-in approval categories with a run-lifetime lease (the scoped successor
|
|
53
|
+
* to auto-approve-all; see ActiveLeases). A built-in whose category is leased
|
|
54
|
+
* is auto-approved for the rest of the run. MCP-server leases are NOT carried
|
|
55
|
+
* here — they are applied upstream by dropping the server's tools from
|
|
56
|
+
* `policies` (mergeApprovalPolicies), which clears them for this gate too.
|
|
57
|
+
* Absent/empty means no built-in lease is active. Inherited verbatim by
|
|
58
|
+
* sub-agents along with the rest of this config.
|
|
59
|
+
*/
|
|
60
|
+
readonly leasedCategories?: ReadonlySet<ToolApprovalCategory>;
|
|
28
61
|
readonly toolServerMap: ReadonlyMap<string, string>;
|
|
62
|
+
/**
|
|
63
|
+
* Per-execution HMAC key for the shadow receipt's action fingerprint. Derived
|
|
64
|
+
* from the runner master secret + execution_id (see fingerprint-secret.ts).
|
|
65
|
+
* Optional: when absent (unit tests, no-secret paths) the receipt is emitted
|
|
66
|
+
* without a fingerprint rather than failing.
|
|
67
|
+
*/
|
|
68
|
+
readonly fingerprintKey?: FingerprintKey;
|
|
69
|
+
/** Execution id, carried into the shadow receipt for audit correlation. */
|
|
70
|
+
readonly executionId?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Apply-then-review capture mode (git workspaces). When true, a built-in
|
|
73
|
+
* `write`/`delete` whose target path is capturable (git-tracked — see
|
|
74
|
+
* {@link isCapturablePath}) FLOWS instead of interrupting: the edit is reviewed
|
|
75
|
+
* post-hoc as a captured `FileChangeSet`, not gated before it runs. A gitignored
|
|
76
|
+
* path is NOT capturable, so it stays gated (the git substrate cannot capture or
|
|
77
|
+
* revert it) — the exact twin of the Cursor hook's `__stigmer_is_gitignored`
|
|
78
|
+
* allow-branch. `shell` and MCP tools are never bypassed by this flag. Off (the
|
|
79
|
+
* default) keeps the classic true-pause gate for every mutation.
|
|
80
|
+
*/
|
|
81
|
+
readonly fileCaptureMode?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Capturability predicate for {@link fileCaptureMode}: given a tool's raw target
|
|
84
|
+
* path (as the model wrote it), resolves true when the path would be captured by
|
|
85
|
+
* the git snapshot (tracked / not gitignored). Injected by setup so the gate
|
|
86
|
+
* stays pure and testable, and so the harness owns path normalization (the
|
|
87
|
+
* deep-agent virtual-root path mapping). Absent ⇒ nothing is bypassed (safe).
|
|
88
|
+
*/
|
|
89
|
+
readonly isCapturablePath?: (rawPath: string) => Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Route gitignored `write`/`edit` edits into CAS capture (apply-then-review)
|
|
92
|
+
* instead of the interrupt gate, applying the DD-E secret gate. When off, a
|
|
93
|
+
* gitignored path stays on the interrupt gate exactly as before.
|
|
94
|
+
*
|
|
95
|
+
* TRUE ONLY FOR THE PARENT GATE. Sub-agents build their own plain filesystem
|
|
96
|
+
* backends, which the CAS observer does not wrap, so flowing their gitignored
|
|
97
|
+
* edits would apply unobserved, unreviewable bytes. `buildSubAgentMiddleware`
|
|
98
|
+
* therefore forces this to false for sub-agent gates — it must NOT be inherited
|
|
99
|
+
* as true. (Sub-agent git-tracked edits are still captured by the turn-boundary
|
|
100
|
+
* git diff, which is backend-agnostic.)
|
|
101
|
+
*/
|
|
102
|
+
readonly captureIgnored?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Sink for a gitignored path hard-blocked as secret-like (DD-E): the write is
|
|
105
|
+
* never applied and never captured, and the turn boundary reads these paths to
|
|
106
|
+
* author a `DIFF_UNREVIEWABLE` change entry (path only — the name is not the
|
|
107
|
+
* secret; the CONTENT never leaves the workspace). Absent ⇒ nothing recorded.
|
|
108
|
+
*/
|
|
109
|
+
readonly recordBlockedSecret?: (rawPath: string) => void;
|
|
29
110
|
}
|
|
30
111
|
export declare function createApprovalGateMiddleware(config: ApprovalGateConfig): StigmerMiddleware;
|
|
@@ -16,46 +16,107 @@
|
|
|
16
16
|
* pausing again.
|
|
17
17
|
*
|
|
18
18
|
* Platform tool defaults: DeepAgents JS backend tools (read, write,
|
|
19
|
-
* edit, execute, etc.) are not covered by MCP policy chains.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* edit, execute, etc.) are not covered by MCP policy chains. Built-in tools
|
|
20
|
+
* are classified through the shared {@link toolApprovalCategory} — the single
|
|
21
|
+
* source of truth, shared with the Cursor deny-oracle hook — so read-only tools
|
|
22
|
+
* are auto-approved and every mutating tool (write/edit/delete/shell) is gated
|
|
23
|
+
* fail-CLOSED, by category rather than by a hand-maintained name list. An
|
|
24
|
+
* unrecognized mutating built-in (e.g. `bash`, `overwrite_file`) is therefore
|
|
25
|
+
* gated by what it does, not by whether someone remembered to list it.
|
|
26
|
+
*
|
|
27
|
+
* Gateway invariant (Phase 2): this middleware IS the in-process execution
|
|
28
|
+
* gateway for the deep-agent harness — `handler(request)` is the side effect. A
|
|
29
|
+
* side effect runs only with a backing authorization: either (a) the tool was
|
|
30
|
+
* auto-approved (policy/classifier cleared it, or auto-approve-all disabled the
|
|
31
|
+
* whole gate), or (b) the user explicitly approved THIS interrupted call. Every
|
|
32
|
+
* other outcome — skip, reject, or an unrecognized decision — returns a
|
|
33
|
+
* ToolMessage WITHOUT executing. There is no path from a model proposal to a
|
|
34
|
+
* side effect that skips an authorization.
|
|
35
|
+
*
|
|
36
|
+
* Shadow ExecutionReceipt: when the gateway lets a side effect through it emits a
|
|
37
|
+
* structured, non-persisted receipt (a `[hitl-gateway] receipt …` log carrying
|
|
38
|
+
* the action's HMAC fingerprint and the authorization source). This is an audit
|
|
39
|
+
* + uniformity signal only — no proto, no storage — mirroring the Phase-1 shadow
|
|
40
|
+
* discipline. On the deep-agent normal path the fingerprint match is guaranteed
|
|
41
|
+
* by LangGraph checkpoint replay (the resumed action equals the approved one), so
|
|
42
|
+
* the receipt is defense-in-depth here; the fingerprint earns real enforcement
|
|
43
|
+
* teeth in the out-of-process Cursor substrate.
|
|
22
44
|
*/
|
|
23
45
|
import { ToolMessage } from "@langchain/core/messages";
|
|
24
46
|
import { interrupt } from "@langchain/langgraph";
|
|
25
|
-
import { resolveApprovalMessage, } from "../shared/approval-policy.js";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
["create_file", "Create file: {{args.path}}"],
|
|
40
|
-
["delete", "Delete: {{args.path}}"],
|
|
41
|
-
["delete_file", "Delete file: {{args.path}}"],
|
|
42
|
-
["execute", "Execute command: {{args.command}}"],
|
|
43
|
-
["shell", "Execute shell command: {{args.command}}"],
|
|
44
|
-
["str_replace_editor", "Edit file: {{args.path}}"],
|
|
45
|
-
]);
|
|
47
|
+
import { POLICY_ENGINE_VERSION, resolveApprovalMessage, } from "../shared/approval-policy.js";
|
|
48
|
+
import { toolApprovalCategory } from "../shared/tool-kind.js";
|
|
49
|
+
import { extractFilePath } from "../shared/file-tools.js";
|
|
50
|
+
import { isSecretLikePath } from "../shared/filereview/secret-paths.js";
|
|
51
|
+
import { computeApprovalFingerprint, } from "../shared/approval-fingerprint.js";
|
|
52
|
+
// Approval-message template per mutating category. Keyed by category (not raw
|
|
53
|
+
// tool name) so every alias of a mutation renders one message; placeholders
|
|
54
|
+
// resolve against the deep-agent stream arg shape (`path`/`command`). Mirrors
|
|
55
|
+
// the Cursor side's CATEGORY_APPROVAL_MESSAGE.
|
|
56
|
+
const CATEGORY_APPROVAL_MESSAGE = {
|
|
57
|
+
write: "Write file: {{args.path}}",
|
|
58
|
+
delete: "Delete: {{args.path}}",
|
|
59
|
+
shell: "Execute command: {{args.command}}",
|
|
60
|
+
};
|
|
46
61
|
export function createApprovalGateMiddleware(config) {
|
|
47
|
-
const { policies,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
const { policies, toolServerMap } = config;
|
|
63
|
+
const leasedCategories = config.leasedCategories ?? EMPTY_CATEGORY_SET;
|
|
64
|
+
// No global-bypass early return: a pre-armed spec.auto_approve_all means the
|
|
65
|
+
// gate is never even installed (setup.ts builds this config only when not
|
|
66
|
+
// global). Scoped leases keep the gate active so non-leased actions still gate.
|
|
51
67
|
return {
|
|
52
68
|
name: "ApprovalGateMiddleware",
|
|
53
69
|
async wrapToolCall(request, handler) {
|
|
54
70
|
const { toolCall } = request;
|
|
55
71
|
const toolName = toolCall.name;
|
|
56
72
|
const serverSlug = toolServerMap.get(toolName) ?? "";
|
|
57
|
-
const
|
|
73
|
+
const category = toolApprovalCategory(toolName);
|
|
74
|
+
// Capture mode (git workspaces): a git-tracked built-in file mutation flows
|
|
75
|
+
// during the turn and is reviewed post-hoc via the file_review ledger (the
|
|
76
|
+
// apply-then-review model). shell and MCP tools (serverSlug present) are
|
|
77
|
+
// never bypassed here.
|
|
78
|
+
if (config.fileCaptureMode &&
|
|
79
|
+
config.isCapturablePath &&
|
|
80
|
+
!serverSlug &&
|
|
81
|
+
(category === "write" || category === "delete")) {
|
|
82
|
+
const path = extractFilePath(toolCall.args);
|
|
83
|
+
if (path !== null) {
|
|
84
|
+
if (await config.isCapturablePath(path)) {
|
|
85
|
+
// Git-tracked: flows and is reviewed post-hoc by the git substrate.
|
|
86
|
+
emitExecutionReceipt(config, toolCall, serverSlug, category, "auto_approve", "file_capture");
|
|
87
|
+
return await handler(request);
|
|
88
|
+
}
|
|
89
|
+
// Gitignored path. Only the PARENT gate (captureIgnored) routes it into
|
|
90
|
+
// CAS capture; sub-agent gates fall through to the interrupt gate below,
|
|
91
|
+
// exactly as before (their backends are not CAS-observed).
|
|
92
|
+
if (config.captureIgnored) {
|
|
93
|
+
if (isSecretLikePath(path)) {
|
|
94
|
+
// DD-E fail-closed: a secret-like gitignored edit is NEVER applied
|
|
95
|
+
// and NEVER captured. Record it so the turn boundary authors a
|
|
96
|
+
// DIFF_UNREVIEWABLE entry (blocking approval); nothing is written.
|
|
97
|
+
config.recordBlockedSecret?.(path);
|
|
98
|
+
return new ToolMessage({
|
|
99
|
+
content: `Tool '${toolName}' was blocked for security: '${path}' matches a ` +
|
|
100
|
+
`secret-like path Stigmer will not capture for review. Nothing was written.`,
|
|
101
|
+
tool_call_id: toolCall.id,
|
|
102
|
+
name: toolName,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (category === "write") {
|
|
106
|
+
// Non-secret gitignored write/edit: flows (apply-then-review). The
|
|
107
|
+
// CAS observer already holds its before-bytes and the turn boundary
|
|
108
|
+
// captures it into CAS. (A gitignored delete has no backend capture
|
|
109
|
+
// path, so it falls through to the interrupt gate.)
|
|
110
|
+
emitExecutionReceipt(config, toolCall, serverSlug, category, "auto_approve", "file_capture");
|
|
111
|
+
return await handler(request);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const requirement = resolveToolApproval(toolName, serverSlug, toolCall.args, policies, leasedCategories);
|
|
58
117
|
if (!requirement.requiresApproval) {
|
|
118
|
+
// Backing authorization: the classifier/policy auto-approved this tool.
|
|
119
|
+
emitExecutionReceipt(config, toolCall, serverSlug, category, "auto_approve", requirement.source);
|
|
59
120
|
return await handler(request);
|
|
60
121
|
}
|
|
61
122
|
const approvalRequest = {
|
|
@@ -63,12 +124,18 @@ export function createApprovalGateMiddleware(config) {
|
|
|
63
124
|
tool_name: toolName,
|
|
64
125
|
mcp_server_slug: serverSlug,
|
|
65
126
|
message: requirement.message,
|
|
127
|
+
// Carry the gate's provenance verdict through the interrupt so the
|
|
128
|
+
// reinvocation that seeds the WAITING_APPROVAL tool call (index.ts) can
|
|
129
|
+
// persist ToolCall.approval_policy_source without re-deriving it.
|
|
130
|
+
policy_source: requirement.source,
|
|
66
131
|
};
|
|
67
132
|
const response = interrupt(approvalRequest);
|
|
68
133
|
const action = (typeof response === "object" && response !== null
|
|
69
134
|
? (response.action ?? "")
|
|
70
135
|
: "").toString().toLowerCase();
|
|
71
136
|
if (action === "approve") {
|
|
137
|
+
// Backing authorization: the user approved THIS interrupted call.
|
|
138
|
+
emitExecutionReceipt(config, toolCall, serverSlug, category, "approval", requirement.source);
|
|
72
139
|
return await handler(request);
|
|
73
140
|
}
|
|
74
141
|
if (action === "skip") {
|
|
@@ -98,28 +165,88 @@ export function createApprovalGateMiddleware(config) {
|
|
|
98
165
|
},
|
|
99
166
|
};
|
|
100
167
|
}
|
|
101
|
-
function resolveToolApproval(toolName, serverSlug, args, policies) {
|
|
168
|
+
function resolveToolApproval(toolName, serverSlug, args, policies, leasedCategories) {
|
|
102
169
|
if (serverSlug) {
|
|
170
|
+
// MCP tools stay governed by the connect-flow classifier + four-level policy
|
|
171
|
+
// chain. The policy map carries only the tools that REQUIRE approval, so an
|
|
172
|
+
// absent entry means the classifier already auto-approved it — fail-OPEN is
|
|
173
|
+
// correct here (a fail-closed default would re-gate everything the classifier
|
|
174
|
+
// cleared). This is deliberately NOT changed by the built-in fail-closed flip.
|
|
175
|
+
//
|
|
176
|
+
// A server-scoped lease surfaces here as an absent entry too: the leased
|
|
177
|
+
// server's tools are dropped from `policies` upstream (mergeApprovalPolicies),
|
|
178
|
+
// so a lease-cleared MCP tool takes this same auto-approve path. (Its shadow
|
|
179
|
+
// receipt therefore reads classifier_default rather than approval_lease; a
|
|
180
|
+
// faithful per-server lease provenance would need the lease set threaded here
|
|
181
|
+
// and is deferred with the rest of the persisted-receipt work.)
|
|
103
182
|
const key = `${serverSlug}/${toolName}`;
|
|
104
183
|
const policy = policies.get(key);
|
|
105
184
|
if (policy) {
|
|
106
185
|
return {
|
|
107
186
|
requiresApproval: policy.requiresApproval,
|
|
108
187
|
message: resolveApprovalMessage(policy.approvalMessage, toolName, args),
|
|
188
|
+
source: policy.source,
|
|
109
189
|
};
|
|
110
190
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return { requiresApproval: false, message: "" };
|
|
191
|
+
// Absent = cleared by the MCP four-level chain (classifier base) or by a
|
|
192
|
+
// server-scoped lease (dropped upstream).
|
|
193
|
+
return { requiresApproval: false, message: "", source: "classifier_default" };
|
|
115
194
|
}
|
|
116
|
-
|
|
117
|
-
|
|
195
|
+
// Built-in/platform tool: gate exactly the mutating categories via the shared
|
|
196
|
+
// classifier. Fail-CLOSED for the mutating set — any built-in classifyTool
|
|
197
|
+
// deems write/edit/delete/shell requires approval. Read-only and unclassified
|
|
198
|
+
// built-ins are not mutating, so they remain fail-open.
|
|
199
|
+
const category = toolApprovalCategory(toolName);
|
|
200
|
+
if (category) {
|
|
201
|
+
// Run-lifetime category lease: the user chose "approve all <category>"
|
|
202
|
+
// earlier in this run, so every built-in of that category is auto-approved
|
|
203
|
+
// for the rest of the run (the scoped successor to auto-approve-all).
|
|
204
|
+
if (leasedCategories.has(category)) {
|
|
205
|
+
return { requiresApproval: false, message: "", source: "approval_lease" };
|
|
206
|
+
}
|
|
118
207
|
return {
|
|
119
208
|
requiresApproval: true,
|
|
120
|
-
message: resolveApprovalMessage(
|
|
209
|
+
message: resolveApprovalMessage(CATEGORY_APPROVAL_MESSAGE[category], toolName, args),
|
|
210
|
+
source: "builtin_category",
|
|
121
211
|
};
|
|
122
212
|
}
|
|
123
|
-
return { requiresApproval: false, message: "" };
|
|
213
|
+
return { requiresApproval: false, message: "", source: "builtin_category" };
|
|
214
|
+
}
|
|
215
|
+
/** Shared empty set so a config without leases allocates nothing per call. */
|
|
216
|
+
const EMPTY_CATEGORY_SET = new Set();
|
|
217
|
+
/**
|
|
218
|
+
* Emit the shadow ExecutionReceipt when the gateway authorizes a side effect.
|
|
219
|
+
*
|
|
220
|
+
* Scope: only side-effecting actions are recorded — a mutating built-in (a
|
|
221
|
+
* non-empty {@link ToolApprovalCategory}) or any MCP tool (`serverSlug` present).
|
|
222
|
+
* Read-only built-ins are not side effects, so recording them would only dilute
|
|
223
|
+
* the signal. The receipt is a structured log carrying the action's HMAC
|
|
224
|
+
* fingerprint and the authorization source; it is never persisted and crosses no
|
|
225
|
+
* wire (no proto). The fingerprint is omitted (empty) when no per-execution key
|
|
226
|
+
* was supplied (tests / no-secret paths).
|
|
227
|
+
*/
|
|
228
|
+
function emitExecutionReceipt(config, toolCall, serverSlug, category, source, policySource) {
|
|
229
|
+
if (!category && !serverSlug)
|
|
230
|
+
return;
|
|
231
|
+
const fingerprint = config.fingerprintKey
|
|
232
|
+
? computeApprovalFingerprint(config.fingerprintKey, {
|
|
233
|
+
toolName: toolCall.name,
|
|
234
|
+
mcpServerSlug: serverSlug,
|
|
235
|
+
args: toolCall.args,
|
|
236
|
+
})
|
|
237
|
+
: "";
|
|
238
|
+
console.log("[hitl-gateway] receipt " +
|
|
239
|
+
JSON.stringify({
|
|
240
|
+
executionId: config.executionId ?? "",
|
|
241
|
+
toolCallId: toolCall.id,
|
|
242
|
+
toolName: toolCall.name,
|
|
243
|
+
mcpServerSlug: serverSlug,
|
|
244
|
+
category: category ?? "",
|
|
245
|
+
authorization: source,
|
|
246
|
+
policySource,
|
|
247
|
+
policyEngineVersion: POLICY_ENGINE_VERSION,
|
|
248
|
+
fingerprint,
|
|
249
|
+
substrate: "deep-agent",
|
|
250
|
+
}));
|
|
124
251
|
}
|
|
125
252
|
//# sourceMappingURL=approval-gate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-gate.js","sourceRoot":"","sources":["../../src/middleware/approval-gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"approval-gate.js","sourceRoot":"","sources":["../../src/middleware/approval-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -81,11 +81,8 @@ export interface CostCapConfig {
|
|
|
81
81
|
export interface OtelSpansConfig {
|
|
82
82
|
readonly toolServerMap: ReadonlyMap<string, string>;
|
|
83
83
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
readonly autoApproveAll: boolean;
|
|
87
|
-
readonly toolServerMap: ReadonlyMap<string, string>;
|
|
88
|
-
}
|
|
84
|
+
import type { ApprovalGateConfig } from "./approval-gate.js";
|
|
85
|
+
export type { ApprovalGateConfig };
|
|
89
86
|
/**
|
|
90
87
|
* Top-level configuration for buildMiddlewareStack().
|
|
91
88
|
* All sections are optional — the factory applies sensible defaults.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed Temporal activity input shared by ExecuteCursor and ExecuteDeepAgent.
|
|
3
|
+
*
|
|
4
|
+
* The Go and Java control planes now invoke these activities with a single
|
|
5
|
+
* object carrying snake_case keys (mirroring the polyglot workflow-input
|
|
6
|
+
* convention) instead of positional string args. This ends the prior drift
|
|
7
|
+
* where Go sent (executionId, threadId) and Java sent
|
|
8
|
+
* (executionId, threadId, invokerIdentityAccountId) while this single runner
|
|
9
|
+
* read only the first two positionally.
|
|
10
|
+
*
|
|
11
|
+
* TRANSITIONAL DUAL-SHAPE: the activity is MaximumAttempts=1 (a failed activity
|
|
12
|
+
* fails the execution with no retry), and the control plane and this runner
|
|
13
|
+
* deploy separately. To make the rollout order-independent, the runner accepts
|
|
14
|
+
* BOTH the new object and the legacy positional args. Deploy the runner first,
|
|
15
|
+
* then the control planes; once both are everywhere, drop the positional branch
|
|
16
|
+
* (and the `string` arms below).
|
|
17
|
+
*/
|
|
18
|
+
export interface ExecuteActivityInput {
|
|
19
|
+
readonly execution_id: string;
|
|
20
|
+
readonly thread_id: string;
|
|
21
|
+
/** Carried for cross-edition parity; the runner hydrates the invoker from the DB. */
|
|
22
|
+
readonly invoker_identity_account_id?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Monotonic HITL-cycle index within this execution: 0 on the first invocation,
|
|
25
|
+
* then the workflow's approvalCycle on each reinvocation. The Cursor producer
|
|
26
|
+
* mints its deterministic file-review change-set id ({@code executionId:turnSeq})
|
|
27
|
+
* from it. Absent on the legacy positional wire shape (defaults to 0).
|
|
28
|
+
*/
|
|
29
|
+
readonly turn_seq?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface NormalizedActivityInput {
|
|
32
|
+
readonly executionId: string;
|
|
33
|
+
readonly threadId: string;
|
|
34
|
+
/** HITL-cycle index for this invocation; 0 on the first turn / legacy wire shape. */
|
|
35
|
+
readonly turnSeq: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Normalizes either the new typed object or the legacy positional args into the
|
|
39
|
+
* `{ executionId, threadId, turnSeq }` the inner activity path consumes.
|
|
40
|
+
* `thread_id` is empty on a first invocation (new harness state) and `turn_seq`
|
|
41
|
+
* defaults to 0 (first turn, or the legacy positional shape that never carried it).
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeActivityInput(arg0: ExecuteActivityInput | string | undefined, arg1?: string): NormalizedActivityInput;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes either the new typed object or the legacy positional args into the
|
|
3
|
+
* `{ executionId, threadId, turnSeq }` the inner activity path consumes.
|
|
4
|
+
* `thread_id` is empty on a first invocation (new harness state) and `turn_seq`
|
|
5
|
+
* defaults to 0 (first turn, or the legacy positional shape that never carried it).
|
|
6
|
+
*/
|
|
7
|
+
export function normalizeActivityInput(arg0, arg1) {
|
|
8
|
+
if (arg0 !== null && typeof arg0 === "object") {
|
|
9
|
+
return {
|
|
10
|
+
executionId: arg0.execution_id ?? "",
|
|
11
|
+
threadId: arg0.thread_id ?? "",
|
|
12
|
+
turnSeq: arg0.turn_seq ?? 0,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return { executionId: arg0 ?? "", threadId: arg1 ?? "", turnSeq: 0 };
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=activity-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-input.js","sourceRoot":"","sources":["../../src/shared/activity-input.ts"],"names":[],"mappings":"AAsCA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA+C,EAC/C,IAAa;IAEb,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;YACpC,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;YAC9B,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC;SAC5B,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ToolActionInput {
|
|
2
|
+
toolName: string;
|
|
3
|
+
mcpServerSlug?: string;
|
|
4
|
+
paths?: string[];
|
|
5
|
+
shellCommand?: string;
|
|
6
|
+
args?: Record<string, unknown>;
|
|
7
|
+
secretKeys?: string[];
|
|
8
|
+
workspaceRoot?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CanonicalToolAction {
|
|
11
|
+
toolName: string;
|
|
12
|
+
mcpServerSlug: string;
|
|
13
|
+
paths: string[];
|
|
14
|
+
shellCommand: string;
|
|
15
|
+
args: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export declare function canonicalizeToolAction(input: ToolActionInput): CanonicalToolAction;
|
|
18
|
+
export declare function canonicalToolActionJson(input: ToolActionInput): string;
|
|
19
|
+
export declare function canonicalJson(value: unknown): string;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Deterministic canonicalization of a tool action into a byte-stable form.
|
|
2
|
+
// Domain: HITL approval. This is the cross-language contract the approval
|
|
3
|
+
// fingerprint (Phase 2) will hash; Phase 1 *defines and computes* it without
|
|
4
|
+
// hashing, so Go/Java/TS can be pinned to byte-identical output via the shared
|
|
5
|
+
// vector corpus (apis/testdata/hitl/canonicalization/).
|
|
6
|
+
//
|
|
7
|
+
// Why this exists: the March 2026 dedup bug was caused by hashing divergent
|
|
8
|
+
// representations of the same action (display args in one place, raw args in
|
|
9
|
+
// another). The fix is a single, explicit normalization pass — applied at ONE
|
|
10
|
+
// layer — that erases incidental differences (path separators, workspace
|
|
11
|
+
// location, shell whitespace, MCP slug case, secret values) before any hash.
|
|
12
|
+
import { createHash } from "node:crypto";
|
|
13
|
+
import { posix } from "node:path";
|
|
14
|
+
export function canonicalizeToolAction(input) {
|
|
15
|
+
return {
|
|
16
|
+
toolName: input.toolName.trim(),
|
|
17
|
+
// Slugs are case-insensitive identity; lowercase so "GitHub" == "github".
|
|
18
|
+
mcpServerSlug: (input.mcpServerSlug ?? "").trim().toLowerCase(),
|
|
19
|
+
paths: normalizePaths(input.paths ?? [], input.workspaceRoot),
|
|
20
|
+
shellCommand: normalizeShellCommand(input.shellCommand ?? ""),
|
|
21
|
+
args: redactSecrets(input.args ?? {}, new Set(input.secretKeys ?? [])),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// canonicalToolActionJson is the single entry point: normalize, then serialize
|
|
25
|
+
// to canonical JSON. The returned string is the byte-stable contract value.
|
|
26
|
+
export function canonicalToolActionJson(input) {
|
|
27
|
+
return canonicalJson(canonicalizeToolAction(input));
|
|
28
|
+
}
|
|
29
|
+
// canonicalJson serializes a value to RFC 8785-style canonical JSON: object keys
|
|
30
|
+
// sorted by UTF-16 code unit, no insignificant whitespace, UTF-8 output.
|
|
31
|
+
//
|
|
32
|
+
// The input domain is deliberately constrained to strings, booleans, null,
|
|
33
|
+
// integers, arrays, and plain objects — the shape of a normalized tool action.
|
|
34
|
+
// Non-integer numbers are rejected rather than implementing RFC 8785's full
|
|
35
|
+
// number-formatting algorithm, keeping this hand-rolled serializer small and
|
|
36
|
+
// provably cross-language without a third-party dependency. Revisit if the
|
|
37
|
+
// canonical domain ever needs floats.
|
|
38
|
+
export function canonicalJson(value) {
|
|
39
|
+
return serialize(value);
|
|
40
|
+
}
|
|
41
|
+
function serialize(v) {
|
|
42
|
+
if (v === null)
|
|
43
|
+
return "null";
|
|
44
|
+
switch (typeof v) {
|
|
45
|
+
case "boolean":
|
|
46
|
+
return v ? "true" : "false";
|
|
47
|
+
case "number":
|
|
48
|
+
if (!Number.isFinite(v))
|
|
49
|
+
throw new Error("canonicalJson: non-finite number");
|
|
50
|
+
if (!Number.isInteger(v)) {
|
|
51
|
+
throw new Error("canonicalJson: non-integer numbers are not part of the canonical contract");
|
|
52
|
+
}
|
|
53
|
+
return String(v);
|
|
54
|
+
case "string":
|
|
55
|
+
// JSON.stringify produces the same minimal escaping and raw UTF-8 for
|
|
56
|
+
// non-ASCII that RFC 8785 mandates for these inputs.
|
|
57
|
+
return JSON.stringify(v);
|
|
58
|
+
case "object":
|
|
59
|
+
if (Array.isArray(v))
|
|
60
|
+
return "[" + v.map(serialize).join(",") + "]";
|
|
61
|
+
return serializeObject(v);
|
|
62
|
+
default:
|
|
63
|
+
throw new Error(`canonicalJson: unsupported type ${typeof v}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function serializeObject(obj) {
|
|
67
|
+
// `undefined`-valued keys are dropped (they have no JSON representation);
|
|
68
|
+
// remaining keys are sorted by UTF-16 code unit, which is JS's default string
|
|
69
|
+
// ordering and matches RFC 8785.
|
|
70
|
+
const keys = Object.keys(obj)
|
|
71
|
+
.filter((k) => obj[k] !== undefined)
|
|
72
|
+
.sort(compareUtf16);
|
|
73
|
+
const parts = keys.map((k) => JSON.stringify(k) + ":" + serialize(obj[k]));
|
|
74
|
+
return "{" + parts.join(",") + "}";
|
|
75
|
+
}
|
|
76
|
+
function compareUtf16(a, b) {
|
|
77
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
78
|
+
}
|
|
79
|
+
function normalizePaths(paths, workspaceRoot) {
|
|
80
|
+
return paths.map((p) => normalizeOnePath(p, workspaceRoot)).sort(compareUtf16);
|
|
81
|
+
}
|
|
82
|
+
function normalizeOnePath(p, workspaceRoot) {
|
|
83
|
+
// Separator-normalize to forward slashes first so Windows and POSIX agree.
|
|
84
|
+
let s = p.replace(/\\/g, "/");
|
|
85
|
+
if (workspaceRoot) {
|
|
86
|
+
const root = workspaceRoot.replace(/\\/g, "/");
|
|
87
|
+
if (s === root) {
|
|
88
|
+
s = "";
|
|
89
|
+
}
|
|
90
|
+
else if (s.startsWith(root + "/")) {
|
|
91
|
+
s = s.slice(root.length + 1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Collapse `.`/`..` segments deterministically. posix.normalize("") -> ".".
|
|
95
|
+
return s === "" ? "" : posix.normalize(s);
|
|
96
|
+
}
|
|
97
|
+
function normalizeShellCommand(cmd) {
|
|
98
|
+
// Collapse runs of whitespace to a single space and trim. The argument VALUE
|
|
99
|
+
// (the command) is what matters; incidental spacing is not identity.
|
|
100
|
+
return cmd.replace(/\s+/g, " ").trim();
|
|
101
|
+
}
|
|
102
|
+
function redactSecrets(args, secretKeys) {
|
|
103
|
+
if (secretKeys.size === 0)
|
|
104
|
+
return args;
|
|
105
|
+
const out = {};
|
|
106
|
+
for (const [k, v] of Object.entries(args)) {
|
|
107
|
+
out[k] = secretKeys.has(k) ? redactValue(v) : v;
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function redactValue(v) {
|
|
112
|
+
// Redact-but-stable: a SHA-256 digest keeps the canonical form stable across
|
|
113
|
+
// runs without ever placing the secret in cleartext. This is NOT the approval
|
|
114
|
+
// fingerprint — that is an HMAC keyed on a Stigmer secret, introduced in
|
|
115
|
+
// Phase 2. This digest is unkeyed redaction only.
|
|
116
|
+
const material = typeof v === "string" ? v : canonicalJson(v);
|
|
117
|
+
return "sha256:" + createHash("sha256").update(material, "utf8").digest("hex");
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=approval-canonicalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-canonicalize.js","sourceRoot":"","sources":["../../src/shared/approval-canonicalize.ts"],"names":[],"mappings":"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"}
|