@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
|
@@ -22,10 +22,17 @@ import type { ArtifactStorage } from "../../shared/artifact-storage.js";
|
|
|
22
22
|
import type { WorkspaceBackend } from "../../shared/workspace/types.js";
|
|
23
23
|
import type { ExecutionStatusWriter } from "./execution-status-writer.js";
|
|
24
24
|
import { utcTimestamp } from "../../shared/status.js";
|
|
25
|
+
import { isSecretLikePath } from "../../shared/filereview/secret-paths.js";
|
|
25
26
|
|
|
26
27
|
export class InlinePublisher {
|
|
27
28
|
private readonly workspaceBackend: WorkspaceBackend;
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* `undefined` when the runner has no artifact store (proxy misconfig). Inline
|
|
31
|
+
* publishing is a best-effort real-time UI nicety, so {@link publish} becomes a
|
|
32
|
+
* no-op — the operator was already warned once at setup, and the transcript still
|
|
33
|
+
* persists without the offloaded artifact.
|
|
34
|
+
*/
|
|
35
|
+
private readonly artifactStorage: ArtifactStorage | undefined;
|
|
29
36
|
private readonly statusWriter: ExecutionStatusWriter;
|
|
30
37
|
private readonly executionId: string;
|
|
31
38
|
|
|
@@ -34,7 +41,7 @@ export class InlinePublisher {
|
|
|
34
41
|
|
|
35
42
|
constructor(opts: {
|
|
36
43
|
workspaceBackend: WorkspaceBackend;
|
|
37
|
-
artifactStorage: ArtifactStorage;
|
|
44
|
+
artifactStorage: ArtifactStorage | undefined;
|
|
38
45
|
statusWriter: ExecutionStatusWriter;
|
|
39
46
|
executionId: string;
|
|
40
47
|
}) {
|
|
@@ -54,9 +61,27 @@ export class InlinePublisher {
|
|
|
54
61
|
* status builder. Fire-and-forget: errors are logged and swallowed.
|
|
55
62
|
*/
|
|
56
63
|
async publish(path: string): Promise<void> {
|
|
64
|
+
// No artifact store (proxy misconfig): nothing to upload to. Skip silently —
|
|
65
|
+
// this is a best-effort UI publisher and the operator was warned at setup.
|
|
66
|
+
if (!this.artifactStorage) return;
|
|
57
67
|
try {
|
|
58
68
|
const sandboxPath = normalizePath(path);
|
|
59
69
|
|
|
70
|
+
// Never publish a secret-like file to durable artifact storage (design
|
|
71
|
+
// doc 12, D4). This is the third secret-withholding choke point beside the
|
|
72
|
+
// CAS capture gate and the transcript args scrub: under the global bypass
|
|
73
|
+
// (spec.auto_approve_all) a secret write is not blocked up front, so it
|
|
74
|
+
// would otherwise be uploaded here (keyed by basename) and registered as an
|
|
75
|
+
// ExecutionArtifact. Fail-closed and unconditional — the same name-based
|
|
76
|
+
// gate the capture path uses, so the decision has one source of truth.
|
|
77
|
+
if (isSecretLikePath(sandboxPath)) {
|
|
78
|
+
console.log(
|
|
79
|
+
`[InlinePublisher] execution=${this.executionId} — withheld '${sandboxPath}' ` +
|
|
80
|
+
`(secret-like; never published to artifact storage)`,
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
const content = await this.workspaceBackend.readFile(sandboxPath);
|
|
61
86
|
const contentBuffer = Buffer.from(content, "utf-8");
|
|
62
87
|
const contentHash = sha256(contentBuffer);
|
|
@@ -69,7 +94,6 @@ export class InlinePublisher {
|
|
|
69
94
|
const storageKey = `artifacts/${this.executionId}/${fileName}`;
|
|
70
95
|
|
|
71
96
|
await this.artifactStorage.upload(storageKey, contentBuffer, guessContentType(fileName));
|
|
72
|
-
const downloadUrl = await this.artifactStorage.getDownloadUrl(storageKey);
|
|
73
97
|
|
|
74
98
|
const artifact = create(ExecutionArtifactSchema, {
|
|
75
99
|
name: fileName,
|
|
@@ -77,7 +101,6 @@ export class InlinePublisher {
|
|
|
77
101
|
kind: ExecutionArtifactKind.FILE,
|
|
78
102
|
sizeBytes: BigInt(contentBuffer.length),
|
|
79
103
|
storageKey,
|
|
80
|
-
downloadUrl,
|
|
81
104
|
createdAt: utcTimestamp(),
|
|
82
105
|
contentHash,
|
|
83
106
|
});
|
|
@@ -8,11 +8,8 @@
|
|
|
8
8
|
* the streaming phase needs.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { createDeepAgent,
|
|
11
|
+
import { createDeepAgent, type FilesystemPermission } from "deepagents";
|
|
12
12
|
import { InteractionMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
13
|
-
import { ChatAnthropic } from "@langchain/anthropic";
|
|
14
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
15
|
-
import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
16
13
|
import type { BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
|
|
17
14
|
import { z } from "zod";
|
|
18
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -32,6 +29,11 @@ import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
|
|
|
32
29
|
import { WorkspaceProvisioner } from "../../shared/workspace/provisioner.js";
|
|
33
30
|
import { LocalWorkspaceBackend } from "../../shared/workspace/local-backend.js";
|
|
34
31
|
import type { WorkspaceBackend, ProvisionResult } from "../../shared/workspace/types.js";
|
|
32
|
+
import { CasCaptureFilesystemBackend } from "./cas-capture-backend.js";
|
|
33
|
+
import { CasCaptureObserver } from "./cas-capture-observer.js";
|
|
34
|
+
import { isGitWorkTree, isPathCapturable } from "../../shared/filereview/git-substrate.js";
|
|
35
|
+
import { deriveCaptureMode } from "../../shared/filereview/capture.js";
|
|
36
|
+
import { resolveWorkspacePath } from "../../shared/file-change.js";
|
|
35
37
|
import { ensurePlatformDir } from "../../shared/workspace/platform-dir.js";
|
|
36
38
|
import { buildWorkspaceFileTree } from "../../shared/workspace/file-tree.js";
|
|
37
39
|
import { reportSetupProgress } from "../../shared/status.js";
|
|
@@ -39,8 +41,12 @@ import { resolveEnvironment, type EnvironmentResult } from "./environment.js";
|
|
|
39
41
|
import { buildEnhancedSystemPrompt } from "./prompt-builder.js";
|
|
40
42
|
import { buildMiddlewareStack, createThinkTool } from "../../middleware/index.js";
|
|
41
43
|
import type { GracefulStopMiddleware } from "../../middleware/index.js";
|
|
44
|
+
import type { ApprovalGateConfig } from "../../middleware/approval-gate.js";
|
|
45
|
+
import { deriveExecutionFingerprintKey } from "../../shared/approval-fingerprint.js";
|
|
46
|
+
import { getRunnerHitlMasterSecret } from "../../shared/fingerprint-secret.js";
|
|
42
47
|
import { getModelPricing, ensureLoaded as ensurePricingLoaded } from "../../shared/model-pricing.js";
|
|
43
48
|
import { getDefaultModel } from "../../shared/model-registry.js";
|
|
49
|
+
import { buildChatModel } from "../../shared/model-client.js";
|
|
44
50
|
import {
|
|
45
51
|
loadArtifactStorageConfig,
|
|
46
52
|
createArtifactStorage,
|
|
@@ -48,15 +54,10 @@ import {
|
|
|
48
54
|
} from "../../shared/artifact-storage.js";
|
|
49
55
|
import {
|
|
50
56
|
mergeApprovalPolicies,
|
|
51
|
-
|
|
57
|
+
deriveActiveLeases,
|
|
52
58
|
type MergedToolPolicy,
|
|
53
59
|
} from "../../shared/approval-policy.js";
|
|
54
|
-
import {
|
|
55
|
-
inferProvider,
|
|
56
|
-
stripProviderPrefix,
|
|
57
|
-
resolveProxyBaseUrl,
|
|
58
|
-
buildProxyHeaders,
|
|
59
|
-
} from "../../shared/llm-proxy.js";
|
|
60
|
+
import type { ToolApprovalCategory } from "../../shared/tool-kind.js";
|
|
60
61
|
import {
|
|
61
62
|
mergeSkillRefs,
|
|
62
63
|
fetchSkillsByRefs,
|
|
@@ -84,13 +85,62 @@ export interface SetupResult {
|
|
|
84
85
|
readonly secretKeys: ReadonlySet<string>;
|
|
85
86
|
readonly modelName: string;
|
|
86
87
|
readonly gracefulStop: GracefulStopMiddleware;
|
|
87
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Artifact storage for CAS blobs, tool-output offload, and attachment/plan
|
|
90
|
+
* artifacts. `undefined` only when it cannot be built (proxy transport with a
|
|
91
|
+
* missing token/endpoint — a misconfiguration; local storage never fails). Every
|
|
92
|
+
* consumer must tolerate its absence: capture degrades to the deny-gate (see
|
|
93
|
+
* `captureMode`), offload is disabled (the aggregate size guard still applies),
|
|
94
|
+
* and attachment/plan publishing surface a clear error rather than crashing.
|
|
95
|
+
*/
|
|
96
|
+
readonly artifactStorage: ArtifactStorage | undefined;
|
|
88
97
|
readonly provisionResults: readonly ProvisionResult[];
|
|
89
98
|
readonly approvalPolicies: ReadonlyMap<string, MergedToolPolicy>;
|
|
90
99
|
readonly toolServerMap: ReadonlyMap<string, string>;
|
|
91
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Built-in approval categories with a run-lifetime scoped lease (from an
|
|
102
|
+
* interactive APPROVE_ALL). Threaded to the StatusBuilder so a leased built-in
|
|
103
|
+
* call is attributed to its lease (approval_lease) rather than the plain
|
|
104
|
+
* category gate. Empty under a global pre-arm or when no lease is active.
|
|
105
|
+
*/
|
|
106
|
+
readonly leasedCategories: ReadonlySet<ToolApprovalCategory>;
|
|
107
|
+
/**
|
|
108
|
+
* Pre-armed spec.auto_approve_all — the one unscoped, whole-run bypass. When
|
|
109
|
+
* true the approval gate is not installed at all. Interactive "approve all"
|
|
110
|
+
* decisions are NOT folded in here; they become scoped leases applied inside
|
|
111
|
+
* the gate (see ActiveLeases / deriveActiveLeases).
|
|
112
|
+
*/
|
|
113
|
+
readonly globalBypass: boolean;
|
|
92
114
|
readonly hasStructuredOutput: boolean;
|
|
93
115
|
readonly streamVersion: "v2" | "v3";
|
|
116
|
+
/**
|
|
117
|
+
* The single owner of this turn's CAS-capture state (design docs 08/11/12):
|
|
118
|
+
* the pre-turn bytes of first-touched gitignored paths (recorded
|
|
119
|
+
* gate-independently by the CAS-observing backends of the parent AND every
|
|
120
|
+
* sub-agent) plus the gitignored paths the gate hard-blocked as secret-like
|
|
121
|
+
* (DD-E). The turn boundary reads both to compose the CAS change set. Empty in
|
|
122
|
+
* the legacy (non-capture) path, where no CAS-observing backend is installed.
|
|
123
|
+
*/
|
|
124
|
+
readonly casObserver: CasCaptureObserver;
|
|
125
|
+
/**
|
|
126
|
+
* Apply-then-review capture mode, decided by {@link deriveCaptureMode} (shared
|
|
127
|
+
* with the Cursor harness so both degrade identically): file edits flow during
|
|
128
|
+
* the turn and are reviewed post-hoc as a captured `FileChangeSet` (the activity
|
|
129
|
+
* authors the baseline/candidate ledger events and reconciles on resume). True
|
|
130
|
+
* whenever there is a capture substrate — a git work tree (needs no storage) OR
|
|
131
|
+
* artifact storage for the non-git CAS path. False for a non-git workspace with
|
|
132
|
+
* no artifact storage (proxy misconfig): capture has no substrate, so file writes
|
|
133
|
+
* fall back to the deny-gate (gated pre-execution) exactly like Cursor's DD-22
|
|
134
|
+
* fallback. When true, the deny-gate covers only shell/MCP/irreversible tools.
|
|
135
|
+
*/
|
|
136
|
+
readonly captureMode: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* True when the workspace is a git work tree. Selects the capture SUBSTRATE for
|
|
139
|
+
* this turn: git-diff (pinned baseline/after trees) when true; content-addressed
|
|
140
|
+
* CAS manifest (path-scoped to touched paths) when false. Threaded into the
|
|
141
|
+
* baseline/candidate/reconcile seam (`capture.ts`) and the CAS capture-class.
|
|
142
|
+
*/
|
|
143
|
+
readonly gitWorkspace: boolean;
|
|
94
144
|
}
|
|
95
145
|
|
|
96
146
|
export interface SetupDependencies {
|
|
@@ -151,9 +201,20 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
151
201
|
await reportSetupProgress(client, executionId, "Resolving environment…");
|
|
152
202
|
const envResult: EnvironmentResult = await resolveEnvironment(client, executionId);
|
|
153
203
|
|
|
154
|
-
// Step 6: Create artifact storage
|
|
155
|
-
|
|
156
|
-
|
|
204
|
+
// Step 6: Create artifact storage. Best-effort, mirroring the Cursor harness:
|
|
205
|
+
// `createArtifactStorage` throws only for proxy transport with a missing
|
|
206
|
+
// token/endpoint (a misconfiguration; local storage never throws). We degrade
|
|
207
|
+
// rather than crash — an absent store flips capture mode off (deny-gate
|
|
208
|
+
// fallback below) and disables offload, instead of failing the whole execution.
|
|
209
|
+
let artifactStorage: ArtifactStorage | undefined;
|
|
210
|
+
try {
|
|
211
|
+
artifactStorage = createArtifactStorage(loadArtifactStorageConfig(config));
|
|
212
|
+
} catch (storageErr) {
|
|
213
|
+
console.warn(
|
|
214
|
+
`[setup] artifact storage unavailable — capture degrades to the deny-gate ` +
|
|
215
|
+
`and tool-output offload is disabled: execution=${executionId}, error=${storageErr}`,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
157
218
|
|
|
158
219
|
// Step 7: Provision workspace
|
|
159
220
|
await reportSetupProgress(client, executionId, "Initializing workspace…");
|
|
@@ -164,6 +225,61 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
164
225
|
sessionId,
|
|
165
226
|
);
|
|
166
227
|
|
|
228
|
+
// Apply-then-review is the file-review model whenever there is a capture
|
|
229
|
+
// SUBSTRATE (DD-21 D2, Slice 2b): file edits flow during the turn and are
|
|
230
|
+
// reviewed post-hoc as a captured `FileChangeSet` (reconciled byte-exactly on
|
|
231
|
+
// resume), never gated before they run. The substrate is selected by
|
|
232
|
+
// `gitWorkspace`:
|
|
233
|
+
// - a git work tree diffs a pinned baseline -> candidate tree (git-substrate,
|
|
234
|
+
// needs no artifact storage), and routes its .gitignored edits into the
|
|
235
|
+
// path-scoped CAS observer;
|
|
236
|
+
// - a non-git workspace has no git snapshot at all, so EVERY touched path is
|
|
237
|
+
// captured into the content-addressed CAS manifest (cas-substrate), which
|
|
238
|
+
// needs artifact storage to persist blobs.
|
|
239
|
+
// So a non-git workspace with NO artifact storage has no substrate: capture
|
|
240
|
+
// degrades to the deny-gate (file writes gated pre-execution), exactly like the
|
|
241
|
+
// Cursor harness (DD-22). `deriveCaptureMode` is the shared decision so both
|
|
242
|
+
// harnesses degrade identically. When capture is on, the deny-gate survives only
|
|
243
|
+
// for shell/MCP/irreversible tools.
|
|
244
|
+
const gitWorkspace = await isGitWorkTree(workspaceBackend.rootDir);
|
|
245
|
+
const captureMode = deriveCaptureMode(
|
|
246
|
+
workspaceBackend.rootDir,
|
|
247
|
+
gitWorkspace,
|
|
248
|
+
!!artifactStorage,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Git-tracked capturability, consulted by the gate to route a file write to
|
|
252
|
+
// disk-and-git-diff (tracked) vs into CAS (ignored). Only meaningful in a git
|
|
253
|
+
// work tree. In a non-git workspace nothing is "git-capturable" (there is no
|
|
254
|
+
// snapshot), so this resolves false for every path and the gate routes all
|
|
255
|
+
// file writes through its captureIgnored (CAS) arm.
|
|
256
|
+
const isCapturablePath = gitWorkspace
|
|
257
|
+
? (rawPath: string): Promise<boolean> =>
|
|
258
|
+
isPathCapturable(
|
|
259
|
+
workspaceBackend.rootDir,
|
|
260
|
+
resolveWorkspacePath(rawPath, workspaceBackend.rootDir, true).path,
|
|
261
|
+
)
|
|
262
|
+
: (_rawPath: string): Promise<boolean> => Promise.resolve(false);
|
|
263
|
+
|
|
264
|
+
// CAS capture (design docs 08/11/12): the content-addressed half of
|
|
265
|
+
// apply-then-review. The single per-turn observer owns the before-bytes of
|
|
266
|
+
// first-touched CAS-owned paths AND the secret-blocked paths, keyed
|
|
267
|
+
// workspace-root-relative so they align with the CAS reconcile's
|
|
268
|
+
// `join(workspaceRoot, path)`. It is shared by the parent AND every sub-agent
|
|
269
|
+
// CAS backend, giving race-free first-touch-wins across concurrent graphs.
|
|
270
|
+
// Its ownership predicate is memoized, so `git check-ignore` runs at most once
|
|
271
|
+
// per distinct path.
|
|
272
|
+
const casObserver = new CasCaptureObserver({
|
|
273
|
+
rootDir: workspaceBackend.rootDir,
|
|
274
|
+
// Which touched paths the observer owns (records pre-turn bytes for). In a
|
|
275
|
+
// git work tree that is the .gitignored set only — git captures the tracked
|
|
276
|
+
// ones. In a non-git workspace there is no git substrate, so the observer
|
|
277
|
+
// owns EVERY touched path; the CAS manifest is the sole capture surface.
|
|
278
|
+
isIgnored: gitWorkspace
|
|
279
|
+
? async (relPath) => !(await isPathCapturable(workspaceBackend.rootDir, relPath))
|
|
280
|
+
: async () => true,
|
|
281
|
+
});
|
|
282
|
+
|
|
167
283
|
// Step 7: Resolve and connect MCP servers
|
|
168
284
|
const mcpServerUsages = [
|
|
169
285
|
...(agent.spec!.mcpServerUsages || []),
|
|
@@ -258,8 +374,18 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
258
374
|
injectedFiles,
|
|
259
375
|
});
|
|
260
376
|
|
|
261
|
-
// Step 9: Construct the LLM model
|
|
262
|
-
|
|
377
|
+
// Step 9: Construct the LLM model. Resolution to the provider API id
|
|
378
|
+
// happens inside buildChatModel; modelName stays the registry id for
|
|
379
|
+
// pricing, the native-thinking heuristic, and sub-agent inheritance.
|
|
380
|
+
const requestTimeoutMs =
|
|
381
|
+
parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
|
|
382
|
+
const { model } = await buildChatModel({
|
|
383
|
+
modelName,
|
|
384
|
+
proxyEndpoint: config.proxyEndpoint ?? undefined,
|
|
385
|
+
stigmerToken: config.stigmerToken ?? undefined,
|
|
386
|
+
headerScope: { executionId },
|
|
387
|
+
timeoutMs: requestTimeoutMs,
|
|
388
|
+
});
|
|
263
389
|
|
|
264
390
|
// Step 10: Build middleware stack
|
|
265
391
|
await ensurePricingLoaded();
|
|
@@ -275,25 +401,64 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
275
401
|
}
|
|
276
402
|
}
|
|
277
403
|
|
|
278
|
-
// Step 10b: Resolve approval policies
|
|
404
|
+
// Step 10b: Resolve approval policies + leases.
|
|
279
405
|
//
|
|
280
|
-
//
|
|
281
|
-
// spec.auto_approve_all
|
|
282
|
-
// APPROVE_ALL
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
const
|
|
287
|
-
|
|
406
|
+
// Two distinct bypasses (see ActiveLeases): the pre-armed
|
|
407
|
+
// spec.auto_approve_all is the one whole-run global bypass; an interactive
|
|
408
|
+
// APPROVE_ALL grants a run-lifetime lease scoped to that action's class (its
|
|
409
|
+
// built-in category, or its MCP server). Server leases shape the policy map
|
|
410
|
+
// (leased servers dropped); built-in category leases are applied inside the
|
|
411
|
+
// gate. Both flow into sub-agents via the shared config below.
|
|
412
|
+
const leases = deriveActiveLeases(execution);
|
|
413
|
+
const globalBypass = leases.global;
|
|
288
414
|
const agentOverrides = agent.spec!.mcpServerUsages?.flatMap(
|
|
289
415
|
u => u.toolApprovalOverrides ?? [],
|
|
290
416
|
) ?? [];
|
|
291
417
|
const approvalPolicies = mergeApprovalPolicies(
|
|
292
418
|
resolvedMcpServers?.resolvedServers ?? [],
|
|
293
419
|
agentOverrides,
|
|
294
|
-
|
|
420
|
+
leases,
|
|
295
421
|
);
|
|
296
422
|
|
|
423
|
+
// The approval gate config is the single source of truth for HITL gating,
|
|
424
|
+
// built once and inherited verbatim by sub-agents (so a mutating tool inside
|
|
425
|
+
// a sub-agent is gated identically to one in the parent). Null under the
|
|
426
|
+
// global pre-arm, where the gate is inert; under scoped leases the gate stays
|
|
427
|
+
// active and clears only leased categories. The per-execution fingerprint key
|
|
428
|
+
// (runner master secret + execution_id) drives the shadow ExecutionReceipt.
|
|
429
|
+
const approvalGateConfig: ApprovalGateConfig | null = !globalBypass
|
|
430
|
+
? {
|
|
431
|
+
policies: approvalPolicies,
|
|
432
|
+
leasedCategories: leases.categories,
|
|
433
|
+
toolServerMap,
|
|
434
|
+
fingerprintKey: deriveExecutionFingerprintKey(
|
|
435
|
+
getRunnerHitlMasterSecret(),
|
|
436
|
+
executionId,
|
|
437
|
+
),
|
|
438
|
+
executionId,
|
|
439
|
+
// Capture mode: file edits flow and are reviewed post-hoc. In a git work
|
|
440
|
+
// tree, git-tracked edits flow to the git diff and .gitignored edits flow
|
|
441
|
+
// into CAS (captureIgnored) on THIS parent gate; in a non-git workspace
|
|
442
|
+
// isCapturablePath is always false, so ALL file writes take the CAS arm.
|
|
443
|
+
// Secret-like paths are hard-blocked (DD-E) and recorded for a
|
|
444
|
+
// DIFF_UNREVIEWABLE entry. shell/MCP stay gated. Sub-agents inherit this
|
|
445
|
+
// config; buildSubAgentMiddleware sets their captureIgnored explicitly
|
|
446
|
+
// from whether a CAS observer backs the sub-agent (Session 26, DD-19),
|
|
447
|
+
// so their captured edits flow into the SAME observer.
|
|
448
|
+
//
|
|
449
|
+
// When captureMode is false (no substrate — non-git + no storage),
|
|
450
|
+
// fileCaptureMode is false so file writes take the plain deny-gate. The
|
|
451
|
+
// CAS arm additionally requires storage: captureIgnored gates gitignored
|
|
452
|
+
// writes onto CAS only when a store exists to persist their blobs (the
|
|
453
|
+
// git+no-storage case), matching the Cursor harness's
|
|
454
|
+
// `captureMode && !!artifactStorage`.
|
|
455
|
+
fileCaptureMode: captureMode,
|
|
456
|
+
isCapturablePath,
|
|
457
|
+
captureIgnored: captureMode && !!artifactStorage,
|
|
458
|
+
recordBlockedSecret: (rawPath: string) => casObserver.recordBlockedSecret(rawPath),
|
|
459
|
+
}
|
|
460
|
+
: null;
|
|
461
|
+
|
|
297
462
|
const maxCostUsd = execConfig?.maxCostUsd ?? 0;
|
|
298
463
|
const { middleware, gracefulStop, costCap: costCapMiddleware } = buildMiddlewareStack({
|
|
299
464
|
loopDetection: {
|
|
@@ -318,11 +483,7 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
318
483
|
warningPct: 80,
|
|
319
484
|
} : null,
|
|
320
485
|
otelSpans: { toolServerMap },
|
|
321
|
-
approvalGate:
|
|
322
|
-
policies: approvalPolicies,
|
|
323
|
-
autoApproveAll,
|
|
324
|
-
toolServerMap,
|
|
325
|
-
} : null,
|
|
486
|
+
approvalGate: approvalGateConfig,
|
|
326
487
|
});
|
|
327
488
|
|
|
328
489
|
// Step 11: Build tools list (MCP tools + think tool)
|
|
@@ -352,12 +513,22 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
352
513
|
parentMcpUsages: mcpServerUsages,
|
|
353
514
|
skillClient: client,
|
|
354
515
|
workspaceBackend,
|
|
355
|
-
|
|
356
|
-
|
|
516
|
+
approvalGate: approvalGateConfig,
|
|
517
|
+
// Capture is universal (Slice 2b), so every sub-agent gets a CAS-observing
|
|
518
|
+
// backend wired to the SAME per-turn observer as the parent — their
|
|
519
|
+
// captured writes (.gitignored in a git tree, all touched paths in a
|
|
520
|
+
// non-git one) compose into the parent's change set (Session 26, DD-19).
|
|
521
|
+
casObserver,
|
|
357
522
|
parentModelName: modelName,
|
|
358
523
|
parentHasNativeThinking: _modelHasNativeThinking(modelName),
|
|
359
524
|
costCap: costCapMiddleware ?? undefined,
|
|
360
|
-
modelFactory: (m: string) =>
|
|
525
|
+
modelFactory: async (m: string) =>
|
|
526
|
+
(await buildChatModel({
|
|
527
|
+
modelName: m,
|
|
528
|
+
proxyEndpoint: config.proxyEndpoint ?? undefined,
|
|
529
|
+
stigmerToken: config.stigmerToken ?? undefined,
|
|
530
|
+
headerScope: { executionId },
|
|
531
|
+
})).model,
|
|
361
532
|
});
|
|
362
533
|
}
|
|
363
534
|
|
|
@@ -381,10 +552,20 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
381
552
|
{ operations: ["write"], paths: ["/**"], mode: "deny" },
|
|
382
553
|
];
|
|
383
554
|
|
|
555
|
+
// File capture point. Apply-then-review is universal (Slice 2b), so the
|
|
556
|
+
// CAS-observing backend: git-tracked edits flow to disk (the turn-boundary
|
|
557
|
+
// git diff is authoritative), and the shared CAS observer records the pre-turn
|
|
558
|
+
// bytes of every CAS-owned path — .gitignored paths in a git work tree, all
|
|
559
|
+
// touched paths in a non-git one — so the boundary can capture them into CAS.
|
|
560
|
+
// It is gate-independent, so it holds even under the global bypass.
|
|
561
|
+
const fileBackend = new CasCaptureFilesystemBackend(
|
|
562
|
+
{ rootDir: workspaceBackend.rootDir },
|
|
563
|
+
{ observer: casObserver },
|
|
564
|
+
);
|
|
384
565
|
const agentGraph = await createDeepAgent({
|
|
385
566
|
model,
|
|
386
567
|
checkpointer: checkpointer as any,
|
|
387
|
-
backend:
|
|
568
|
+
backend: fileBackend,
|
|
388
569
|
systemPrompt,
|
|
389
570
|
tools,
|
|
390
571
|
middleware: middleware as any,
|
|
@@ -432,9 +613,13 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
432
613
|
provisionResults,
|
|
433
614
|
approvalPolicies,
|
|
434
615
|
toolServerMap,
|
|
435
|
-
|
|
616
|
+
leasedCategories: leases.categories,
|
|
617
|
+
globalBypass,
|
|
436
618
|
hasStructuredOutput: !!outputSchema,
|
|
437
619
|
streamVersion,
|
|
620
|
+
casObserver,
|
|
621
|
+
captureMode,
|
|
622
|
+
gitWorkspace,
|
|
438
623
|
};
|
|
439
624
|
} catch (err) {
|
|
440
625
|
if (mcpConnection) {
|
|
@@ -444,93 +629,6 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
|
|
|
444
629
|
}
|
|
445
630
|
}
|
|
446
631
|
|
|
447
|
-
/**
|
|
448
|
-
* Construct the appropriate chat model for the given model name.
|
|
449
|
-
*
|
|
450
|
-
* Provider inference uses name prefix heuristics (claude → Anthropic,
|
|
451
|
-
* gpt/o1/o3/o4 → OpenAI). In proxy mode, requests route through the
|
|
452
|
-
* stigmer-cloud LlmProxyController at provider-specific paths.
|
|
453
|
-
*/
|
|
454
|
-
function constructModel(
|
|
455
|
-
modelName: string,
|
|
456
|
-
config: Config,
|
|
457
|
-
executionId?: string,
|
|
458
|
-
): BaseChatModel {
|
|
459
|
-
const provider = inferProvider(modelName);
|
|
460
|
-
const apiModelId = stripProviderPrefix(modelName);
|
|
461
|
-
|
|
462
|
-
const baseUrl = config.proxyEndpoint
|
|
463
|
-
? resolveProxyBaseUrl(config.proxyEndpoint, provider)
|
|
464
|
-
: undefined;
|
|
465
|
-
|
|
466
|
-
const headers = config.proxyEndpoint && config.stigmerToken
|
|
467
|
-
? buildProxyHeaders(config.stigmerToken, { executionId })
|
|
468
|
-
: undefined;
|
|
469
|
-
|
|
470
|
-
switch (provider) {
|
|
471
|
-
case "anthropic":
|
|
472
|
-
return buildAnthropicModel(apiModelId, baseUrl, headers, config);
|
|
473
|
-
case "openai":
|
|
474
|
-
return buildOpenAIModel(apiModelId, baseUrl, headers, config);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function buildAnthropicModel(
|
|
479
|
-
model: string,
|
|
480
|
-
baseUrl: string | undefined,
|
|
481
|
-
headers: Record<string, string> | undefined,
|
|
482
|
-
config: Config,
|
|
483
|
-
): BaseChatModel {
|
|
484
|
-
const apiKey = config.proxyEndpoint
|
|
485
|
-
? (config.stigmerToken ?? "proxy-managed")
|
|
486
|
-
: (process.env.ANTHROPIC_API_KEY ?? "");
|
|
487
|
-
|
|
488
|
-
const requestTimeoutMs = parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
|
|
489
|
-
|
|
490
|
-
return new ChatAnthropic({
|
|
491
|
-
model,
|
|
492
|
-
apiKey,
|
|
493
|
-
temperature: 0,
|
|
494
|
-
...(requestTimeoutMs ? { maxRetries: 0, timeout: requestTimeoutMs } : {}),
|
|
495
|
-
...(baseUrl || headers
|
|
496
|
-
? {
|
|
497
|
-
clientOptions: {
|
|
498
|
-
...(baseUrl ? { baseURL: baseUrl } : {}),
|
|
499
|
-
...(headers ? { defaultHeaders: headers } : {}),
|
|
500
|
-
},
|
|
501
|
-
}
|
|
502
|
-
: {}),
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
function buildOpenAIModel(
|
|
507
|
-
model: string,
|
|
508
|
-
baseUrl: string | undefined,
|
|
509
|
-
headers: Record<string, string> | undefined,
|
|
510
|
-
config: Config,
|
|
511
|
-
): BaseChatModel {
|
|
512
|
-
const apiKey = config.proxyEndpoint
|
|
513
|
-
? (config.stigmerToken ?? "proxy-managed")
|
|
514
|
-
: (process.env.OPENAI_API_KEY ?? "");
|
|
515
|
-
|
|
516
|
-
const requestTimeoutMs = parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
|
|
517
|
-
|
|
518
|
-
return new ChatOpenAI({
|
|
519
|
-
model,
|
|
520
|
-
apiKey,
|
|
521
|
-
temperature: 0,
|
|
522
|
-
...(requestTimeoutMs ? { maxRetries: 0, timeout: requestTimeoutMs } : {}),
|
|
523
|
-
...(baseUrl || headers
|
|
524
|
-
? {
|
|
525
|
-
configuration: {
|
|
526
|
-
...(baseUrl ? { baseURL: baseUrl } : {}),
|
|
527
|
-
...(headers ? { defaultHeaders: headers } : {}),
|
|
528
|
-
},
|
|
529
|
-
}
|
|
530
|
-
: {}),
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
|
|
534
632
|
/**
|
|
535
633
|
* Provision workspace from session workspace entries.
|
|
536
634
|
*/
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-agent turn-boundary stamping of flowed file-edit rows — the deep-agent
|
|
3
|
+
* analog of the Cursor adapter's `stampFlowedFileEditRows` (in `capture-flow.ts`),
|
|
4
|
+
* minus deny-token coordination (this harness has no deny gate; every
|
|
5
|
+
* write/delete flowed). Extracted from the activity entry point so it is
|
|
6
|
+
* directly unit-testable, mirroring how `approval-file-change.ts` isolates the
|
|
7
|
+
* capture helpers.
|
|
8
|
+
*
|
|
9
|
+
* Rows stay visible in place as observational records; `file_change_sets`
|
|
10
|
+
* remains the single decision surface (DD-24).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
14
|
+
import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
|
|
15
|
+
import { toolApprovalCategory } from "../../shared/tool-kind.js";
|
|
16
|
+
import { isToolCallRowHidden, stampFileEditRow } from "../../shared/tool-row.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Stamp every flowed file-edit row (category write/delete) with this turn's
|
|
20
|
+
* change set id. Skips already-stamped rows (a resume seeds prior turns' rows
|
|
21
|
+
* into this transcript — re-stamping would mis-attribute them) and legacy hidden
|
|
22
|
+
* rows from pre-stamping sessions (they belong to an earlier turn's set).
|
|
23
|
+
*
|
|
24
|
+
* `skipToolCallIds` scopes the pass to rows CREATED this turn: a tool-call id
|
|
25
|
+
* present before this turn's stream is skipped. Top-level callers omit it (a
|
|
26
|
+
* top-level flowed row is this-turn's by the already-stamped/hidden shields);
|
|
27
|
+
* sub-agent callers pass a pre-turn snapshot, since sub-agent rows have neither
|
|
28
|
+
* shield (see `collectSubAgentToolCallIds` in `shared/tool-row.ts`).
|
|
29
|
+
*/
|
|
30
|
+
export function stampFlowedFileEditRows(
|
|
31
|
+
messages: readonly AgentMessage[],
|
|
32
|
+
changeSetId: string,
|
|
33
|
+
skipToolCallIds?: ReadonlySet<string>,
|
|
34
|
+
): void {
|
|
35
|
+
for (const msg of messages) {
|
|
36
|
+
for (const tc of msg.toolCalls) {
|
|
37
|
+
if (tc.fileChangeSetId) continue;
|
|
38
|
+
if (skipToolCallIds?.has(tc.id)) continue;
|
|
39
|
+
if (isToolCallRowHidden(tc)) continue;
|
|
40
|
+
const category = toolApprovalCategory(tc.name);
|
|
41
|
+
if (category !== "write" && category !== "delete") continue;
|
|
42
|
+
stampFileEditRow(tc, changeSetId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Stamp the current turn's sub-agent flowed file-edit rows with the parent
|
|
49
|
+
* turn's change set id. Sub-agent writes fold their files into the SAME parent
|
|
50
|
+
* turn set (shared git diff + one shared CasCaptureObserver, DD-19), so they
|
|
51
|
+
* carry the parent change set id and badge against the same set the parent's
|
|
52
|
+
* rows do. They live under `subAgentExecutions` (not the top-level transcript),
|
|
53
|
+
* so they are walked separately and scoped to this turn via `priorToolCallIds`
|
|
54
|
+
* (the sub-agent tool-call ids that existed before this turn's stream).
|
|
55
|
+
*/
|
|
56
|
+
export function stampFlowedSubAgentFileEditRows(
|
|
57
|
+
subAgents: readonly SubAgentExecution[],
|
|
58
|
+
changeSetId: string,
|
|
59
|
+
priorToolCallIds: ReadonlySet<string>,
|
|
60
|
+
): void {
|
|
61
|
+
for (const sa of subAgents) {
|
|
62
|
+
stampFlowedFileEditRows(sa.messages, changeSetId, priorToolCallIds);
|
|
63
|
+
}
|
|
64
|
+
}
|