@stigmer/runner 3.14.0 → 3.15.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__/execution-record-fixture.d.ts +47 -0
- package/dist/__test-utils__/execution-record-fixture.js +68 -0
- package/dist/__test-utils__/execution-record-fixture.js.map +1 -0
- package/dist/__test-utils__/harness-contract/types.d.ts +166 -0
- package/dist/__test-utils__/harness-contract/types.js +49 -0
- package/dist/__test-utils__/harness-contract/types.js.map +1 -0
- package/dist/__test-utils__/hermetic-activity.d.ts +268 -0
- package/dist/__test-utils__/hermetic-activity.js +385 -0
- package/dist/__test-utils__/hermetic-activity.js.map +1 -0
- package/dist/__test-utils__/mock-client.d.ts +13 -0
- package/dist/__test-utils__/mock-client.js +45 -0
- package/dist/__test-utils__/mock-client.js.map +1 -0
- package/dist/__test-utils__/mock-workspace.d.ts +15 -0
- package/dist/__test-utils__/mock-workspace.js +21 -0
- package/dist/__test-utils__/mock-workspace.js.map +1 -0
- package/dist/__test-utils__/model-registry-fixture.d.ts +56 -0
- package/dist/__test-utils__/model-registry-fixture.js +66 -0
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -0
- package/dist/__test-utils__/turn-input-fixture.d.ts +60 -0
- package/dist/__test-utils__/turn-input-fixture.js +118 -0
- package/dist/__test-utils__/turn-input-fixture.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +107 -0
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +344 -0
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +20 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +58 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +2 -32
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +148 -0
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +257 -0
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +183 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +262 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +138 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +191 -0
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -0
- package/dist/activities/execute-cursor/adapter.d.ts +55 -0
- package/dist/activities/execute-cursor/adapter.js +119 -0
- package/dist/activities/execute-cursor/adapter.js.map +1 -0
- package/dist/activities/execute-cursor/approval-state.d.ts +2 -2
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +15 -30
- package/dist/activities/execute-cursor/capture-flow.js +17 -26
- package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +23 -0
- package/dist/activities/execute-cursor/cursor-capabilities.js +33 -0
- package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +2 -2
- package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -1
- package/dist/activities/execute-cursor/fetch-interceptor.d.ts +15 -25
- package/dist/activities/execute-cursor/fetch-interceptor.js +39 -33
- package/dist/activities/execute-cursor/fetch-interceptor.js.map +1 -1
- package/dist/activities/execute-cursor/http2-interceptor.d.ts +21 -17
- package/dist/activities/execute-cursor/http2-interceptor.js +38 -31
- package/dist/activities/execute-cursor/http2-interceptor.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +28 -19
- package/dist/activities/execute-cursor/message-translator.js +76 -27
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +180 -11
- package/dist/activities/execute-cursor/prompt-builder.js +171 -0
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/rejection-capture.d.ts +3 -6
- package/dist/activities/execute-cursor/rejection-capture.js +5 -7
- package/dist/activities/execute-cursor/rejection-capture.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -4
- package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-boundary.d.ts +1 -1
- package/dist/activities/execute-cursor/turn-settle.d.ts +49 -0
- package/dist/activities/execute-cursor/turn-settle.js +507 -0
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -0
- package/dist/activities/execute-cursor/turn-setup.d.ts +173 -0
- package/dist/activities/execute-cursor/turn-setup.js +496 -0
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -0
- package/dist/activities/execute-cursor/turn-stream.d.ts +41 -71
- package/dist/activities/execute-cursor/turn-stream.js +70 -135
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.d.ts +43 -0
- package/dist/activities/execute-cursor/turn.js +222 -0
- package/dist/activities/execute-cursor/turn.js.map +1 -0
- package/dist/activities/execute-cursor/usage-pricing.d.ts +38 -0
- package/dist/activities/execute-cursor/usage-pricing.js +50 -0
- package/dist/activities/execute-cursor/usage-pricing.js.map +1 -0
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.js +1 -1
- package/dist/activities/execute-deep-agent/environment.js +1 -1
- package/dist/activities/execute-deep-agent/environment.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.js +3 -2
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/hydrate-workflow-execution.js +1 -1
- package/dist/activities/hydrate-workflow-execution.js.map +1 -1
- package/dist/config.d.ts +15 -0
- package/dist/config.js.map +1 -1
- package/dist/harness/capabilities.d.ts +87 -0
- package/dist/harness/capabilities.js +37 -0
- package/dist/harness/capabilities.js.map +1 -0
- package/dist/harness/persist-chokepoint.d.ts +74 -0
- package/dist/harness/persist-chokepoint.js +88 -0
- package/dist/harness/persist-chokepoint.js.map +1 -0
- package/dist/harness/registry.d.ts +106 -0
- package/dist/harness/registry.js +168 -0
- package/dist/harness/registry.js.map +1 -0
- package/dist/harness/run-turn.d.ts +53 -0
- package/dist/harness/run-turn.js +528 -0
- package/dist/harness/run-turn.js.map +1 -0
- package/dist/harness/stop-controller.d.ts +50 -0
- package/dist/harness/stop-controller.js +62 -0
- package/dist/harness/stop-controller.js.map +1 -0
- package/dist/harness/terminal-table.d.ts +141 -0
- package/dist/harness/terminal-table.js +239 -0
- package/dist/harness/terminal-table.js.map +1 -0
- package/dist/harness/turn-context.d.ts +523 -0
- package/dist/harness/turn-context.js +739 -0
- package/dist/harness/turn-context.js.map +1 -0
- package/dist/harness/types.d.ts +448 -0
- package/dist/harness/types.js +64 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/usage-accumulator.d.ts +68 -0
- package/dist/harness/usage-accumulator.js +101 -0
- package/dist/harness/usage-accumulator.js.map +1 -0
- package/dist/harness-adapters.d.ts +27 -0
- package/dist/harness-adapters.js +28 -0
- package/dist/harness-adapters.js.map +1 -0
- package/dist/main.js.map +1 -1
- package/dist/runner-manager.js +64 -48
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.d.ts +5 -4
- package/dist/runner.js +65 -64
- package/dist/runner.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +1 -1
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/{activities/execute-cursor → shared}/attachment-resolver.d.ts +2 -2
- package/dist/{activities/execute-cursor → shared}/attachment-resolver.js +5 -5
- package/dist/shared/attachment-resolver.js.map +1 -0
- package/dist/{activities/execute-cursor → shared}/blueprint-resolver.d.ts +7 -5
- package/dist/{activities/execute-cursor → shared}/blueprint-resolver.js +3 -63
- package/dist/shared/blueprint-resolver.js.map +1 -0
- package/dist/shared/channel-attachment.d.ts +1 -1
- package/dist/shared/channel-attachment.js.map +1 -1
- package/dist/{activities/execute-cursor → shared}/cost-guard.d.ts +5 -1
- package/dist/{activities/execute-cursor → shared}/cost-guard.js +5 -1
- package/dist/shared/cost-guard.js.map +1 -0
- package/dist/{activities/execute-cursor → shared}/env-resolver.d.ts +1 -1
- package/dist/shared/env-resolver.js.map +1 -0
- package/dist/{activities/execute-cursor → shared}/exact-apply.d.ts +1 -1
- package/dist/{activities/execute-cursor → shared}/exact-apply.js +6 -6
- package/dist/shared/exact-apply.js.map +1 -0
- package/dist/shared/execution-context.d.ts +35 -0
- package/dist/shared/execution-context.js +38 -0
- package/dist/shared/execution-context.js.map +1 -0
- package/dist/{activities/execute-cursor → shared}/extract-structured-output.d.ts +5 -2
- package/dist/{activities/execute-cursor → shared}/extract-structured-output.js +9 -6
- package/dist/shared/extract-structured-output.js.map +1 -0
- package/dist/shared/filereview/capture.d.ts +1 -1
- package/dist/shared/filereview/capture.js +1 -1
- package/dist/shared/heartbeat.d.ts +13 -11
- package/dist/shared/heartbeat.js +14 -29
- package/dist/shared/heartbeat.js.map +1 -1
- package/dist/{activities/execute-cursor → shared}/persist-decision.d.ts +5 -2
- package/dist/{activities/execute-cursor → shared}/persist-decision.js +4 -1
- package/dist/shared/persist-decision.js.map +1 -0
- package/dist/{activities/execute-cursor → shared}/skill-resolver.d.ts +16 -3
- package/dist/{activities/execute-cursor → shared}/skill-resolver.js +12 -4
- package/dist/shared/skill-resolver.js.map +1 -0
- package/dist/shared/subagent-rows.d.ts +21 -0
- package/dist/shared/subagent-rows.js +34 -0
- package/dist/shared/subagent-rows.js.map +1 -0
- package/dist/shared/worker-shutdown.d.ts +43 -16
- package/dist/shared/worker-shutdown.js +28 -13
- package/dist/shared/worker-shutdown.js.map +1 -1
- package/dist/shared/workspace/platform-dir.d.ts +1 -1
- package/dist/shared/workspace/platform-dir.js +1 -1
- package/dist/shared/workspace/session-provision.d.ts +54 -0
- package/dist/{activities/execute-cursor/workspace-provision.js → shared/workspace/session-provision.js} +15 -12
- package/dist/shared/workspace/session-provision.js.map +1 -0
- package/package.json +4 -4
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +325 -0
- package/src/__test-utils__/config-fixture.ts +63 -0
- package/src/__test-utils__/execution-record-fixture.ts +104 -0
- package/src/__test-utils__/harness-boot-order-child.ts +58 -0
- package/src/__test-utils__/harness-contract/contract.ts +581 -0
- package/src/__test-utils__/harness-contract/recording-sink.ts +107 -0
- package/src/__test-utils__/harness-contract/runtime-contract.ts +666 -0
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +349 -0
- package/src/__test-utils__/harness-contract/types.ts +176 -0
- package/src/__test-utils__/hermetic-activity.ts +502 -0
- package/src/__test-utils__/model-registry-fixture.ts +72 -0
- package/src/__test-utils__/module-specifiers.ts +82 -0
- package/src/__test-utils__/proto-helpers.ts +25 -0
- package/src/__test-utils__/turn-input-fixture.ts +155 -0
- package/src/__tests__/harness-boot-order.test.ts +77 -0
- package/src/__tests__/harness-contract.test.ts +27 -0
- package/src/__tests__/runner-manager.test.ts +18 -0
- package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +102 -0
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +396 -0
- package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +66 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +2 -43
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +342 -0
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +368 -0
- package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +254 -0
- package/src/activities/execute-cursor/__tests__/adapter-is-temporal-free.test.ts +45 -0
- package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +90 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +7 -8
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +28 -1
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +64 -6
- package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +228 -0
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +180 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +53 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn1.status.json +55 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn2.status.json +77 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.status.json +126 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +40 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/plain-turn.status.json +48 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +56 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-fresh-agent.status.json +53 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.status.json +48 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.status.json +36 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.status.json +37 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +38 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +59 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-call.status.json +68 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +79 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +42 -0
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +170 -0
- package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +205 -0
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +171 -0
- package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +156 -0
- package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +286 -0
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +332 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +193 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +137 -0
- package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +185 -0
- package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +151 -0
- package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +65 -35
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -40
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +171 -0
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +118 -243
- package/src/activities/execute-cursor/__tests__/usage-pricing.test.ts +84 -0
- package/src/activities/execute-cursor/adapter.ts +138 -0
- package/src/activities/execute-cursor/approval-state.ts +2 -2
- package/src/activities/execute-cursor/capture-flow.ts +18 -41
- package/src/activities/execute-cursor/cursor-capabilities.ts +35 -0
- package/src/activities/execute-cursor/cursor-mcp-config.ts +2 -2
- package/src/activities/execute-cursor/fetch-interceptor.ts +48 -45
- package/src/activities/execute-cursor/http2-interceptor.ts +47 -34
- package/src/activities/execute-cursor/message-translator.ts +90 -45
- package/src/activities/execute-cursor/prompt-builder.ts +327 -12
- package/src/activities/execute-cursor/rejection-capture.ts +5 -12
- package/src/activities/execute-cursor/session-lifecycle.ts +1 -5
- package/src/activities/execute-cursor/turn-boundary.ts +1 -1
- package/src/activities/execute-cursor/turn-settle.ts +601 -0
- package/src/activities/execute-cursor/turn-setup.ts +645 -0
- package/src/activities/execute-cursor/turn-stream.ts +84 -210
- package/src/activities/execute-cursor/turn.ts +240 -0
- package/src/activities/execute-cursor/usage-pricing.ts +67 -0
- package/src/activities/execute-deep-agent/approval-file-change.ts +1 -1
- package/src/activities/execute-deep-agent/environment.ts +1 -1
- package/src/activities/execute-deep-agent/setup.ts +3 -2
- package/src/activities/hydrate-workflow-execution.ts +1 -1
- package/src/config.ts +13 -0
- package/src/harness/__tests__/import-direction.test.ts +168 -0
- package/src/harness/__tests__/persist-chokepoint.test.ts +146 -0
- package/src/harness/__tests__/registry.test.ts +168 -0
- package/src/harness/__tests__/run-turn.test.ts +165 -0
- package/src/harness/__tests__/stop-controller.test.ts +49 -0
- package/src/harness/__tests__/turn-context.test.ts +178 -0
- package/src/harness/__tests__/usage-accumulator.test.ts +83 -0
- package/src/harness/capabilities.ts +92 -0
- package/src/harness/persist-chokepoint.ts +112 -0
- package/src/harness/registry.ts +197 -0
- package/src/harness/run-turn.ts +618 -0
- package/src/harness/stop-controller.ts +83 -0
- package/src/harness/terminal-table.ts +276 -0
- package/src/harness/turn-context.ts +1028 -0
- package/src/harness/types.ts +473 -0
- package/src/harness/usage-accumulator.ts +122 -0
- package/src/harness-adapters.ts +30 -0
- package/src/main.ts +1 -1
- package/src/runner-manager.ts +68 -61
- package/src/runner.ts +67 -78
- package/src/shared/__tests__/attachment-naming.test.ts +1 -1
- package/src/{activities/execute-cursor → shared}/__tests__/attachment-resolver.test.ts +6 -4
- package/src/{activities/execute-cursor → shared}/__tests__/cost-guard.test.ts +2 -1
- package/src/{activities/execute-cursor → shared}/__tests__/exact-apply.test.ts +3 -3
- package/src/{activities/execute-cursor → shared}/__tests__/extract-structured-output.test.ts +8 -8
- package/src/{activities/execute-cursor → shared}/__tests__/persist-decision.test.ts +4 -2
- package/src/{activities/execute-cursor → shared}/__tests__/skill-resolver.test.ts +1 -1
- package/src/shared/__tests__/subagent-rows.test.ts +34 -0
- package/src/shared/__tests__/worker-shutdown.test.ts +44 -39
- package/src/shared/approval-policy.ts +1 -1
- package/src/{activities/execute-cursor → shared}/attachment-resolver.ts +6 -6
- package/src/{activities/execute-cursor → shared}/blueprint-resolver.ts +7 -78
- package/src/shared/channel-attachment.ts +1 -1
- package/src/{activities/execute-cursor → shared}/cost-guard.ts +5 -1
- package/src/{activities/execute-cursor → shared}/env-resolver.ts +1 -1
- package/src/{activities/execute-cursor → shared}/exact-apply.ts +7 -7
- package/src/shared/execution-context.ts +45 -0
- package/src/{activities/execute-cursor → shared}/extract-structured-output.ts +10 -7
- package/src/shared/filereview/capture.ts +1 -1
- package/src/shared/heartbeat.ts +13 -33
- package/src/{activities/execute-cursor → shared}/persist-decision.ts +5 -2
- package/src/{activities/execute-cursor → shared}/skill-resolver.ts +20 -6
- package/src/shared/subagent-rows.ts +39 -0
- package/src/shared/worker-shutdown.ts +55 -25
- package/src/{activities/execute-cursor/__tests__/workspace-provision.test.ts → shared/workspace/__tests__/session-provision.test.ts} +25 -28
- package/src/shared/workspace/platform-dir.ts +1 -1
- package/src/{activities/execute-cursor/workspace-provision.ts → shared/workspace/session-provision.ts} +29 -16
- package/dist/activities/execute-cursor/attachment-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/blueprint-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/cost-guard.js.map +0 -1
- package/dist/activities/execute-cursor/env-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/exact-apply.js.map +0 -1
- package/dist/activities/execute-cursor/extract-structured-output.js.map +0 -1
- package/dist/activities/execute-cursor/index.d.ts +0 -209
- package/dist/activities/execute-cursor/index.js +0 -2345
- package/dist/activities/execute-cursor/index.js.map +0 -1
- package/dist/activities/execute-cursor/persist-decision.js.map +0 -1
- package/dist/activities/execute-cursor/skill-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/usage-accumulator.d.ts +0 -89
- package/dist/activities/execute-cursor/usage-accumulator.js +0 -121
- package/dist/activities/execute-cursor/usage-accumulator.js.map +0 -1
- package/dist/activities/execute-cursor/workspace-provision.d.ts +0 -42
- package/dist/activities/execute-cursor/workspace-provision.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/usage-accumulator.test.ts +0 -164
- package/src/activities/execute-cursor/index.ts +0 -2876
- package/src/activities/execute-cursor/usage-accumulator.ts +0 -169
- /package/dist/{activities/execute-cursor → shared}/env-resolver.js +0 -0
|
@@ -30,13 +30,14 @@
|
|
|
30
30
|
* - approvalMessage: from the policy, with placeholder resolution
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
import { create } from "@bufbuild/protobuf";
|
|
33
|
+
import { clone, create } from "@bufbuild/protobuf";
|
|
34
34
|
import type { JsonObject } from "@bufbuild/protobuf";
|
|
35
|
+
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
35
36
|
import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
36
37
|
import type { AgentMessage, ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
37
38
|
import { SubAgentExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
|
|
38
39
|
import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
|
|
39
|
-
import { ApprovalPolicySource, MessageType, ToolCallStatus, SubAgentStatus, ToolKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
40
|
+
import { ApprovalAction, ApprovalPolicySource, MessageType, ToolCallStatus, SubAgentStatus, ToolKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
40
41
|
import type { SDKMessage } from "@cursor/sdk";
|
|
41
42
|
import type { MergedToolPolicy } from "./approval-policy.js";
|
|
42
43
|
import { lookupMcpToolPolicy, resolveApprovalMessage, builtInRequiresApproval, getBuiltInApprovalMessage, SALIENT_ARG_FIELDS } from "./approval-policy.js";
|
|
@@ -55,6 +56,7 @@ import {
|
|
|
55
56
|
type DeniedLedgerEntry,
|
|
56
57
|
} from "./approval-state.js";
|
|
57
58
|
import { utcTimestamp } from "../../shared/status.js";
|
|
59
|
+
import { cancelInProgressSubAgentProtos } from "../../shared/subagent-rows.js";
|
|
58
60
|
import { hideToolCallRow, isToolCallRowHidden } from "../../shared/tool-row.js";
|
|
59
61
|
import { classifyTool, toolApprovalCategory, type ToolApprovalCategory } from "../../shared/tool-kind.js";
|
|
60
62
|
import { resolveWorkspacePath } from "../../shared/file-change.js";
|
|
@@ -192,7 +194,7 @@ function translateToolCall(event: Extract<SDKMessage, { type: "tool_call" }>): A
|
|
|
192
194
|
*/
|
|
193
195
|
export function buildToolCallProto(
|
|
194
196
|
event: Extract<SDKMessage, { type: "tool_call" }>,
|
|
195
|
-
mergedPolicies?:
|
|
197
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>,
|
|
196
198
|
provenance?: ApprovalProvenanceContext,
|
|
197
199
|
): ToolCall {
|
|
198
200
|
const status = mapToolCallStatus(event.status);
|
|
@@ -714,7 +716,7 @@ function interpretSubAgentToolResult(result: unknown): {
|
|
|
714
716
|
* Options for creating a MessageAccumulator with policy awareness.
|
|
715
717
|
*/
|
|
716
718
|
export interface MessageAccumulatorOptions {
|
|
717
|
-
mergedPolicies?:
|
|
719
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>;
|
|
718
720
|
/**
|
|
719
721
|
* Run-scoped approval context (global bypass + active leases) so reconstructed
|
|
720
722
|
* tool calls carry their authorization provenance. Omitted in unit tests that
|
|
@@ -729,13 +731,28 @@ export interface MessageAccumulatorOptions {
|
|
|
729
731
|
workspaceRoot?: string;
|
|
730
732
|
/**
|
|
731
733
|
* Sub-agent executions carried over from the persisted transcript on a
|
|
732
|
-
* durable resume (
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
* Empty on a first run.
|
|
734
|
+
* durable resume ({@link seededSubAgentsOf}). The accumulator re-registers
|
|
735
|
+
* them so a sub-agent's resumed lifecycle updates merge onto the seeded row
|
|
736
|
+
* instead of producing a duplicate, and so the row survives the round-trip
|
|
737
|
+
* rather than being dropped from the rebuilt status. Empty on a first run.
|
|
737
738
|
*/
|
|
738
|
-
seededSubAgents?: SubAgentExecution[];
|
|
739
|
+
seededSubAgents?: readonly SubAgentExecution[];
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* The sub-agent rows a resumed turn re-registers, cloned from the persisted
|
|
744
|
+
* execution so the input stays immutable. This accumulator OWNS
|
|
745
|
+
* `status.subAgentExecutions` and overwrites it on every flush, which is why
|
|
746
|
+
* the runtime's transcript seeding (`harness/turn-context.ts`
|
|
747
|
+
* `seedTranscriptFromExecution`) leaves the sub-agents to this harness: they
|
|
748
|
+
* are re-registered here, never pushed onto the status. Same "left a
|
|
749
|
+
* transcript" test as the seeding, so a resume that seeded messages always
|
|
750
|
+
* seeds their sub-agents too.
|
|
751
|
+
*/
|
|
752
|
+
export function seededSubAgentsOf(execution: AgentExecution): SubAgentExecution[] {
|
|
753
|
+
const persisted = execution.status;
|
|
754
|
+
if (!persisted || persisted.messages.length === 0) return [];
|
|
755
|
+
return persisted.subAgentExecutions.map((sub) => clone(SubAgentExecutionSchema, sub));
|
|
739
756
|
}
|
|
740
757
|
|
|
741
758
|
/**
|
|
@@ -765,31 +782,6 @@ export interface MessageAccumulatorOptions {
|
|
|
765
782
|
* Task (sub-agent) tool calls additionally produce SubAgentExecution
|
|
766
783
|
* protos, accessible via the subAgentExecutions getter.
|
|
767
784
|
*/
|
|
768
|
-
/**
|
|
769
|
-
* Transition any non-terminal sub-agent (IN_PROGRESS or PENDING) in the given
|
|
770
|
-
* proto array to CANCELLED with a completion timestamp, in place.
|
|
771
|
-
*
|
|
772
|
-
* Operates directly on the status array (not the accumulator) because the
|
|
773
|
-
* Cursor cancellation exception unwinds out of the streaming loop into the
|
|
774
|
-
* activity's catch block, where the MessageAccumulator is out of scope. Returns
|
|
775
|
-
* true if any sub-agent changed.
|
|
776
|
-
*/
|
|
777
|
-
export function cancelInProgressSubAgentProtos(
|
|
778
|
-
subAgents: SubAgentExecution[],
|
|
779
|
-
): boolean {
|
|
780
|
-
let changed = false;
|
|
781
|
-
for (const sub of subAgents) {
|
|
782
|
-
if (
|
|
783
|
-
sub.status === SubAgentStatus.SUB_AGENT_IN_PROGRESS ||
|
|
784
|
-
sub.status === SubAgentStatus.SUB_AGENT_PENDING
|
|
785
|
-
) {
|
|
786
|
-
sub.status = SubAgentStatus.SUB_AGENT_CANCELLED;
|
|
787
|
-
sub.completedAt = utcTimestamp();
|
|
788
|
-
changed = true;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return changed;
|
|
792
|
-
}
|
|
793
785
|
|
|
794
786
|
export class MessageAccumulator {
|
|
795
787
|
private readonly messages: AgentMessage[];
|
|
@@ -797,7 +789,7 @@ export class MessageAccumulator {
|
|
|
797
789
|
private activeThinkingByRunId = new Map<string, AgentMessage>();
|
|
798
790
|
private readonly _subAgentExecutions: SubAgentExecution[] = [];
|
|
799
791
|
private readonly subAgentMap = new Map<string, SubAgentExecution>();
|
|
800
|
-
private readonly mergedPolicies?:
|
|
792
|
+
private readonly mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>;
|
|
801
793
|
private readonly provenance?: ApprovalProvenanceContext;
|
|
802
794
|
private readonly workspaceRoot?: string;
|
|
803
795
|
private readonly toolCallIndex = new Map<string, ToolCall>();
|
|
@@ -974,12 +966,21 @@ export class MessageAccumulator {
|
|
|
974
966
|
* pending call with the same identity naturally reconciles onto the next one.
|
|
975
967
|
* Tool calls created during this turn are not WAITING_APPROVAL until the
|
|
976
968
|
* post-stream denial reconciliation runs, so they can never be matched here.
|
|
969
|
+
*
|
|
970
|
+
* Only a row whose decision EXECUTES is resumable: the re-issue after an
|
|
971
|
+
* APPROVE is the approved act itself, landing on its row. A row the user
|
|
972
|
+
* declined (SKIP / REJECT) is a closed gate — a later same-identity call is a
|
|
973
|
+
* NEW act the model was told not to perform, and it gets its own row so the
|
|
974
|
+
* hook's denial gates it afresh instead of landing on the declined row and
|
|
975
|
+
* inheriting its decision (S2 M4 finding F9, the accumulator's half; the
|
|
976
|
+
* denial overlay's half is {@link isAdjudicatedRow}).
|
|
977
977
|
*/
|
|
978
978
|
private findResumableSeededToolCall(candidate: ToolCall): ToolCall | undefined {
|
|
979
979
|
const wanted = toolCallIdentityToken(candidate);
|
|
980
980
|
for (const tc of this.toolCallIndex.values()) {
|
|
981
981
|
if (
|
|
982
982
|
tc.status === ToolCallStatus.TOOL_CALL_WAITING_APPROVAL &&
|
|
983
|
+
!isDeclinedRow(tc) &&
|
|
983
984
|
toolCallIdentityToken(tc) === wanted
|
|
984
985
|
) {
|
|
985
986
|
return tc;
|
|
@@ -1241,7 +1242,7 @@ export class MessageAccumulator {
|
|
|
1241
1242
|
export async function reconcileDeniedToolCalls(
|
|
1242
1243
|
messages: AgentMessage[],
|
|
1243
1244
|
ledger: DeniedLedgerEntry[],
|
|
1244
|
-
mergedPolicies?:
|
|
1245
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>,
|
|
1245
1246
|
workspaceBackend?: WorkspaceBackend,
|
|
1246
1247
|
): Promise<ToolCall[]> {
|
|
1247
1248
|
// Defense-in-depth: only APPROVAL-kind denials may become approval gates.
|
|
@@ -1281,10 +1282,13 @@ export async function reconcileDeniedToolCalls(
|
|
|
1281
1282
|
// byte-for-byte (the path form agreed on both sides). The anchor resource
|
|
1282
1283
|
// re-attempted within the turn shares one token and collapses to a single
|
|
1283
1284
|
// approval (the first match is the keeper; same-identity twins are blanked
|
|
1284
|
-
// by collapseRedundantToolCallTwins below).
|
|
1285
|
+
// by collapseRedundantToolCallTwins below). A row an earlier invocation's
|
|
1286
|
+
// gate already settled is never the home of THIS turn's denial
|
|
1287
|
+
// (isAdjudicatedRow) — the search moves past it to this turn's attempt.
|
|
1285
1288
|
for (const msg of messages) {
|
|
1286
1289
|
if (anchorMatched) break;
|
|
1287
1290
|
for (const tc of msg.toolCalls) {
|
|
1291
|
+
if (isAdjudicatedRow(tc)) continue;
|
|
1288
1292
|
if (toolCallIdentityToken(tc) !== anchorToken) continue;
|
|
1289
1293
|
overlayDeniedStreamCall(tc, anchorInput, mergedPolicies);
|
|
1290
1294
|
matchedCalls.add(tc);
|
|
@@ -1415,7 +1419,7 @@ export async function reconcileDeniedToolCalls(
|
|
|
1415
1419
|
function overlayDeniedStreamCall(
|
|
1416
1420
|
tc: ToolCall,
|
|
1417
1421
|
input: Record<string, unknown> | undefined,
|
|
1418
|
-
mergedPolicies:
|
|
1422
|
+
mergedPolicies: ReadonlyMap<string, MergedToolPolicy> | undefined,
|
|
1419
1423
|
): void {
|
|
1420
1424
|
markWaitingApproval(tc, mergedPolicies);
|
|
1421
1425
|
applyGateInput(tc, input);
|
|
@@ -1466,6 +1470,42 @@ function isAlreadyCollapsed(tc: ToolCall): boolean {
|
|
|
1466
1470
|
);
|
|
1467
1471
|
}
|
|
1468
1472
|
|
|
1473
|
+
/**
|
|
1474
|
+
* Whether the server has already adjudicated this row — the user decided its
|
|
1475
|
+
* gate (`approval_action`, the server's field; the runner never writes it).
|
|
1476
|
+
*
|
|
1477
|
+
* Such a row belongs to a gate that is CLOSED: approved and executed, or
|
|
1478
|
+
* declined, in an earlier invocation of this execution. No reconciliation of
|
|
1479
|
+
* the CURRENT turn may rewrite it — not the denial overlay (a new denial of the
|
|
1480
|
+
* same identity is a NEW act and gets its own row), not the twin collapse (the
|
|
1481
|
+
* executed row is the transcript's record). Before this rule the overlay matched
|
|
1482
|
+
* a denial to the FIRST same-identity row in the whole transcript, flipped a
|
|
1483
|
+
* completed, approved row back to WAITING_APPROVAL with its APPROVE still on
|
|
1484
|
+
* it, and the next invocation read that as the decision for the new, undecided
|
|
1485
|
+
* proposal — an approval bleeding to a later identical act (S2 M4 finding F9,
|
|
1486
|
+
* found by the harness contract kit's invariant 3 against this adapter).
|
|
1487
|
+
*/
|
|
1488
|
+
function isAdjudicatedRow(tc: ToolCall): boolean {
|
|
1489
|
+
return tc.approvalAction !== ApprovalAction.UNSPECIFIED;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/** Adjudicated with a decision that does NOT execute: the user declined this gate. */
|
|
1493
|
+
function isDeclinedRow(tc: ToolCall): boolean {
|
|
1494
|
+
switch (tc.approvalAction) {
|
|
1495
|
+
case ApprovalAction.SKIP:
|
|
1496
|
+
case ApprovalAction.REJECT:
|
|
1497
|
+
return true;
|
|
1498
|
+
case ApprovalAction.UNSPECIFIED:
|
|
1499
|
+
case ApprovalAction.APPROVE:
|
|
1500
|
+
case ApprovalAction.APPROVE_ALL:
|
|
1501
|
+
return false;
|
|
1502
|
+
default: {
|
|
1503
|
+
const exhaustive: never = tc.approvalAction;
|
|
1504
|
+
throw new Error(`isDeclinedRow: unknown approval action ${String(exhaustive)}`);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1469
1509
|
/**
|
|
1470
1510
|
* Whether a tool call carries a change/output of its own — the signal that it is
|
|
1471
1511
|
* authoritative for its resource rather than a redundant denial/cancel twin.
|
|
@@ -1556,8 +1596,11 @@ export function collapseRedundantToolCallTwins(messages: AgentMessage[]): number
|
|
|
1556
1596
|
if (group.length < 2) continue; // a lone call is never a twin
|
|
1557
1597
|
|
|
1558
1598
|
// Keepers carry authoritative state: a change/output of their own
|
|
1559
|
-
// (carriesOwnChange)
|
|
1560
|
-
//
|
|
1599
|
+
// (carriesOwnChange), the approval gate itself, or a gate an earlier
|
|
1600
|
+
// invocation already settled (isAdjudicatedRow — the transcript's record of
|
|
1601
|
+
// what the user decided and what ran; a same-identity act in a later turn
|
|
1602
|
+
// is a new act, never this row's twin). For a file mutation the gate is the
|
|
1603
|
+
// sole authoritative row (the row carries no diff — review lives in the
|
|
1561
1604
|
// ledger, or the row IS the no-storage deny-gate), so a denied write's
|
|
1562
1605
|
// same-identity siblings collapse onto it; a shell/MCP twin keeps every
|
|
1563
1606
|
// distinct run with output.
|
|
@@ -1565,6 +1608,7 @@ export function collapseRedundantToolCallTwins(messages: AgentMessage[]): number
|
|
|
1565
1608
|
group.filter(
|
|
1566
1609
|
(tc) =>
|
|
1567
1610
|
carriesOwnChange(tc) ||
|
|
1611
|
+
isAdjudicatedRow(tc) ||
|
|
1568
1612
|
tc.status === ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
1569
1613
|
),
|
|
1570
1614
|
);
|
|
@@ -1613,6 +1657,7 @@ function collapseNonAnchorDenials(
|
|
|
1613
1657
|
let collapsed = 0;
|
|
1614
1658
|
for (const msg of messages) {
|
|
1615
1659
|
for (const tc of msg.toolCalls) {
|
|
1660
|
+
if (isAdjudicatedRow(tc)) continue;
|
|
1616
1661
|
const token = toolCallIdentityToken(tc);
|
|
1617
1662
|
if (token === anchorToken) continue;
|
|
1618
1663
|
if (!deniedTokens.has(token)) continue;
|
|
@@ -1714,7 +1759,7 @@ function findUnmatchedStreamCallByNormalizedSalient(
|
|
|
1714
1759
|
): ToolCall | undefined {
|
|
1715
1760
|
for (const msg of messages) {
|
|
1716
1761
|
for (const tc of msg.toolCalls) {
|
|
1717
|
-
if (matchedCalls.has(tc)) continue;
|
|
1762
|
+
if (matchedCalls.has(tc) || isAdjudicatedRow(tc)) continue;
|
|
1718
1763
|
const id = toolIdentity(tc.name, tc.mcpServerSlug, toolCallArgs(tc));
|
|
1719
1764
|
if (normalizedFileSalient(id.key, id.salient, workspaceRoot) === wanted) {
|
|
1720
1765
|
return tc;
|
|
@@ -2189,7 +2234,7 @@ function toolCallArgs(tc: ToolCall): Record<string, unknown> {
|
|
|
2189
2234
|
*/
|
|
2190
2235
|
function markWaitingApproval(
|
|
2191
2236
|
tc: ToolCall,
|
|
2192
|
-
mergedPolicies?:
|
|
2237
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>,
|
|
2193
2238
|
): void {
|
|
2194
2239
|
tc.status = ToolCallStatus.TOOL_CALL_WAITING_APPROVAL;
|
|
2195
2240
|
tc.requiresApproval = true;
|
|
@@ -2209,7 +2254,7 @@ function synthesizeWaitingApprovalToolCall(
|
|
|
2209
2254
|
salient: string,
|
|
2210
2255
|
digest: string,
|
|
2211
2256
|
token: string,
|
|
2212
|
-
mergedPolicies?:
|
|
2257
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>,
|
|
2213
2258
|
): ToolCall {
|
|
2214
2259
|
const tc = create(ToolCallSchema, {
|
|
2215
2260
|
id: `approval:${token}`,
|
|
@@ -2255,7 +2300,7 @@ function resolveDeniedApprovalMessage(
|
|
|
2255
2300
|
name: string,
|
|
2256
2301
|
mcpServerSlug: string,
|
|
2257
2302
|
args: Record<string, unknown>,
|
|
2258
|
-
mergedPolicies?:
|
|
2303
|
+
mergedPolicies?: ReadonlyMap<string, MergedToolPolicy>,
|
|
2259
2304
|
): string {
|
|
2260
2305
|
if (mergedPolicies && mcpServerSlug) {
|
|
2261
2306
|
const policy = lookupMcpToolPolicy(name, mcpServerSlug, mergedPolicies);
|
|
@@ -48,6 +48,8 @@ import {
|
|
|
48
48
|
type DownloadUrlKind,
|
|
49
49
|
} from "../../shared/attachment-download-urls.js";
|
|
50
50
|
import { formatTurnRecoveryText } from "./turn-recovery.js";
|
|
51
|
+
import type { SkillMetadata } from "../../shared/skill-resolver.js";
|
|
52
|
+
import type { AgentResolution, AgentResolutionReason } from "./session-lifecycle.js";
|
|
51
53
|
import { PLAN_MODE_DIRECTIVE } from "../../shared/plan-mode-prompt.js";
|
|
52
54
|
import {
|
|
53
55
|
buildImplementPlanDirective,
|
|
@@ -66,12 +68,6 @@ const RUNNER_PATH_MARKERS = [
|
|
|
66
68
|
"/dist/main.js",
|
|
67
69
|
] as const;
|
|
68
70
|
|
|
69
|
-
export interface SkillMetadata {
|
|
70
|
-
name: string;
|
|
71
|
-
description: string;
|
|
72
|
-
path: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
71
|
/**
|
|
76
72
|
* Vision facts about this turn's attachments, rendered inside the
|
|
77
73
|
* input-files section: which images the model can see inline (in send
|
|
@@ -80,7 +76,7 @@ export interface SkillMetadata {
|
|
|
80
76
|
*/
|
|
81
77
|
export interface VisionPromptInfo {
|
|
82
78
|
inlineFilenames: string[];
|
|
83
|
-
notViewable: NotViewableEntry[];
|
|
79
|
+
notViewable: readonly NotViewableEntry[];
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
/**
|
|
@@ -104,13 +100,13 @@ export interface AttachmentPromptEntry {
|
|
|
104
100
|
export interface EnhancedPromptOptions {
|
|
105
101
|
instructions: string;
|
|
106
102
|
userMessage: string;
|
|
107
|
-
skills: SkillMetadata[];
|
|
103
|
+
skills: readonly SkillMetadata[];
|
|
108
104
|
/**
|
|
109
105
|
* Serving proactive channels + their approved templates — rendered as
|
|
110
106
|
* the `<available_channel_templates>` section (proactive-messaging
|
|
111
107
|
* DD-003 D5) beside the synthesized send_channel_message tool.
|
|
112
108
|
*/
|
|
113
|
-
channelMessaging?: ChannelMessagingInfo[];
|
|
109
|
+
channelMessaging?: readonly ChannelMessagingInfo[];
|
|
114
110
|
subAgents: SubAgent[];
|
|
115
111
|
workspaceDirs: string[];
|
|
116
112
|
workspaceFileRefs: string[];
|
|
@@ -326,7 +322,7 @@ export function buildEnhancedPrompt(options: EnhancedPromptOptions): string {
|
|
|
326
322
|
*/
|
|
327
323
|
export function buildReinvocationPrompt(
|
|
328
324
|
pendingApprovals: PendingApproval[],
|
|
329
|
-
approvalDecisions:
|
|
325
|
+
approvalDecisions: ReadonlyMap<string, ApprovalAction>,
|
|
330
326
|
appliedToolCallIds: ReadonlySet<string> = new Set(),
|
|
331
327
|
): string {
|
|
332
328
|
const approved: string[] = [];
|
|
@@ -415,7 +411,7 @@ export function buildHitlRecoveryPrompt(
|
|
|
415
411
|
recovery: {
|
|
416
412
|
turnDigest: string | undefined;
|
|
417
413
|
pendingApprovals: PendingApproval[];
|
|
418
|
-
approvalDecisions:
|
|
414
|
+
approvalDecisions: ReadonlyMap<string, ApprovalAction>;
|
|
419
415
|
appliedToolCallIds?: ReadonlySet<string>;
|
|
420
416
|
},
|
|
421
417
|
): string {
|
|
@@ -508,7 +504,7 @@ export function formatConversationCatchupSection(digest: string): string {
|
|
|
508
504
|
return `<conversation_catchup>\n${formatConversationCatchupText(digest)}\n</conversation_catchup>`;
|
|
509
505
|
}
|
|
510
506
|
|
|
511
|
-
export function formatSkillsSection(skills: SkillMetadata[]): string {
|
|
507
|
+
export function formatSkillsSection(skills: readonly SkillMetadata[]): string {
|
|
512
508
|
const entries = skills.map(
|
|
513
509
|
(s) => `- **${s.name}**: ${s.description}\n Path: \`${s.path}\``,
|
|
514
510
|
);
|
|
@@ -810,3 +806,322 @@ export function buildToolApprovalRuleFile(): string {
|
|
|
810
806
|
"",
|
|
811
807
|
].join("\n");
|
|
812
808
|
}
|
|
809
|
+
|
|
810
|
+
// ---------------------------------------------------------------------------
|
|
811
|
+
// Prompt selection — which of the four shapes a turn sends, from how the
|
|
812
|
+
// agent resolved and whether the turn carries adjudicated approvals. Moved
|
|
813
|
+
// from `index.ts` at S2 M3b, body unchanged; `__tests__/build-prompt.test.ts`
|
|
814
|
+
// pins every branch.
|
|
815
|
+
// ---------------------------------------------------------------------------
|
|
816
|
+
|
|
817
|
+
export interface BuildPromptInput {
|
|
818
|
+
resolution: AgentResolution;
|
|
819
|
+
/** Empty when the turn carries no adjudicated approvals (see isHitlReinvocation). */
|
|
820
|
+
approvalDecisions: ReadonlyMap<string, ApprovalAction>;
|
|
821
|
+
instructions: string;
|
|
822
|
+
userMessage: string;
|
|
823
|
+
skills: readonly SkillMetadata[];
|
|
824
|
+
/**
|
|
825
|
+
* Serving proactive channels + their templates (the DD-006 D2
|
|
826
|
+
* discovery read) — the `<available_channel_templates>` section.
|
|
827
|
+
*/
|
|
828
|
+
channelMessaging?: readonly ChannelMessagingInfo[];
|
|
829
|
+
subAgents: SubAgent[];
|
|
830
|
+
workspaceDirs: string[];
|
|
831
|
+
workspaceFileRefs: string[];
|
|
832
|
+
/**
|
|
833
|
+
* This turn's resolved attachments for the `<input_files>` section —
|
|
834
|
+
* final paths plus duplicate-rename disclosure (attachment-resolver.ts).
|
|
835
|
+
*/
|
|
836
|
+
attachments: AttachmentPromptEntry[];
|
|
837
|
+
/**
|
|
838
|
+
* Vision facts for the input-files section (T04): which attachments the
|
|
839
|
+
* model sees inline and which degraded to path-only. PER-TURN like the
|
|
840
|
+
* catchup — it rides both the enhanced prompt and a resumed turn's prefix.
|
|
841
|
+
*/
|
|
842
|
+
vision?: VisionPromptInfo;
|
|
843
|
+
/**
|
|
844
|
+
* What kind of URL the turn's storage backend mints (issue #532) — keys
|
|
845
|
+
* the input-files hand-off wording. Sourced from the resolved
|
|
846
|
+
* artifactStorage's self-description; absent when no storage resolved.
|
|
847
|
+
*/
|
|
848
|
+
downloadUrlKind?: DownloadUrlKind;
|
|
849
|
+
pendingApprovals: PendingApproval[];
|
|
850
|
+
/**
|
|
851
|
+
* Approved whole-file writes the runner already applied itself (exact-apply).
|
|
852
|
+
* The reinvocation prompt marks these as done so the model does not redo them;
|
|
853
|
+
* the remaining approved actions are the ones it must still carry out.
|
|
854
|
+
*/
|
|
855
|
+
appliedToolCallIds?: ReadonlySet<string>;
|
|
856
|
+
interactionMode?: InteractionMode;
|
|
857
|
+
/**
|
|
858
|
+
* The execution is a Build-from-plan turn (spec.execution_config
|
|
859
|
+
* .build_from_plan): both prompt paths carry the implement-plan directive.
|
|
860
|
+
*/
|
|
861
|
+
buildFromPlan?: boolean;
|
|
862
|
+
/**
|
|
863
|
+
* Rollover context bridge from `SessionSpec.metadata` (cloud DD-013).
|
|
864
|
+
* Only the enhanced-prompt path consumes it — a resumed agent's native
|
|
865
|
+
* context IS the previous conversation, so it needs no bridge.
|
|
866
|
+
*/
|
|
867
|
+
contextBridge?: string;
|
|
868
|
+
/**
|
|
869
|
+
* Channel sender identity from `SessionSpec.metadata`. Like the bridge,
|
|
870
|
+
* only the enhanced-prompt path consumes it — a resumed agent's native
|
|
871
|
+
* context already carries it from the session's first turn.
|
|
872
|
+
*/
|
|
873
|
+
senderIdentity?: SenderIdentity;
|
|
874
|
+
/**
|
|
875
|
+
* Embedder-supplied session context from `SessionSpec.metadata`. Like
|
|
876
|
+
* the bridge, only the enhanced-prompt path consumes it — a resumed
|
|
877
|
+
* agent's native context already carries it from the session's first
|
|
878
|
+
* turn.
|
|
879
|
+
*/
|
|
880
|
+
sessionContext?: string;
|
|
881
|
+
/**
|
|
882
|
+
* Platform-declared standing preferences from the execution spec's
|
|
883
|
+
* `declared_preferences` (stigmer/stigmer#293). Like the bridge, only
|
|
884
|
+
* the enhanced-prompt path consumes it — deliberately frozen per Cursor
|
|
885
|
+
* session (DD-002 D3): the first turn delivers it into the agent's own
|
|
886
|
+
* conversation store, and repeating it on resumed turns would bloat the
|
|
887
|
+
* store with identical content.
|
|
888
|
+
*/
|
|
889
|
+
declaredPreferences?: DeclaredPreferencesContent;
|
|
890
|
+
/**
|
|
891
|
+
* The subject's confirmed memories from the execution spec's
|
|
892
|
+
* `recalled_memories` (stigmer/stigmer#293 Phase 2, DD-006). Like the
|
|
893
|
+
* preferences, only the enhanced-prompt path consumes it — deliberately
|
|
894
|
+
* frozen per Cursor session (DD-002 D3, inherited by DD-006 D4): the
|
|
895
|
+
* first turn delivers it into the agent's own conversation store, and
|
|
896
|
+
* repeating it on resumed turns would bloat the store with identical
|
|
897
|
+
* content.
|
|
898
|
+
*/
|
|
899
|
+
recalledMemories?: RecalledMemoriesContent;
|
|
900
|
+
/**
|
|
901
|
+
* Conversation catchup from the execution spec's `conversation_catchup`
|
|
902
|
+
* (cloud DD-006): what happened on the channel conversation that the
|
|
903
|
+
* agent has not seen. PER-TURN, so unlike the standing values
|
|
904
|
+
* above it rides BOTH prompt paths — the enhanced prompt and a resumed
|
|
905
|
+
* turn's prefix (the `interaction_mode` shape). Handback lands
|
|
906
|
+
* mid-session on a resumed agent: the resumed path is the one that
|
|
907
|
+
* matters. Once delivered, the digest persists in the agent's own
|
|
908
|
+
* conversation store; the next turn's field is composed fresh and is
|
|
909
|
+
* usually blank.
|
|
910
|
+
*/
|
|
911
|
+
conversationCatchup?: string;
|
|
912
|
+
/**
|
|
913
|
+
* The turn's recorded transcript rendered as digest lines
|
|
914
|
+
* (turn-recovery.ts), composed from `status.messages` at the call site.
|
|
915
|
+
* Consumed ONLY by the HITL-recovery shape — a fresh agent that replaced
|
|
916
|
+
* a lost one mid-HITL needs the story of the work it no longer remembers
|
|
917
|
+
* (issue #366); every other shape either has native context or no prior
|
|
918
|
+
* work to tell.
|
|
919
|
+
*/
|
|
920
|
+
turnRecoveryDigest?: string;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Select and build the appropriate prompt based on resolution reason and
|
|
925
|
+
* HITL state.
|
|
926
|
+
*
|
|
927
|
+
* Conversation continuation is carried entirely by the Cursor SDK's native
|
|
928
|
+
* agent state (the local SQLite store persisted on the durable workspace
|
|
929
|
+
* volume, or cloud server-side state) — there is no separate continuation
|
|
930
|
+
* store. The prompt therefore depends only on how the agent was resolved:
|
|
931
|
+
*
|
|
932
|
+
* 1. HITL reinvocation, -> buildReinvocationPrompt (approval decisions
|
|
933
|
+
* resumed agent only; the resumed agent's native context
|
|
934
|
+
* carries the prior conversation)
|
|
935
|
+
* 2. HITL reinvocation, -> buildHitlRecoveryPrompt (full context +
|
|
936
|
+
* fresh agent after the turn's recorded transcript + decisions;
|
|
937
|
+
* resume failure the replacement agent's conversation is
|
|
938
|
+
* empty, and both fresh-agent crossings —
|
|
939
|
+
* resolution-time resume failure and mid-send
|
|
940
|
+
* poisoned-handle recovery — land here by
|
|
941
|
+
* keying on the reason, issue #366)
|
|
942
|
+
* 3. resumed_successfully -> raw userMessage (native context carries it)
|
|
943
|
+
* 4. first execution / fresh -> buildEnhancedPrompt (full instructions +
|
|
944
|
+
* agent after resume failure skills; no prior conversation to inherit)
|
|
945
|
+
*/
|
|
946
|
+
/**
|
|
947
|
+
* Whether this activity invocation is a HITL re-invocation — the turn resumes
|
|
948
|
+
* an agent purely to convey approval decisions, carrying NO user message.
|
|
949
|
+
* Discriminates the two surfaces that depend on the agent already holding
|
|
950
|
+
* this turn's content natively — the prompt shape (below) and the primary
|
|
951
|
+
* send's vision payload — but never alone: both pair it with
|
|
952
|
+
* `resolution.reason`, because a FRESH agent mid-HITL holds nothing and
|
|
953
|
+
* needs the full re-delivery (issue #366).
|
|
954
|
+
*/
|
|
955
|
+
export function isHitlReinvocation(
|
|
956
|
+
approvalDecisions: ReadonlyMap<string, ApprovalAction>,
|
|
957
|
+
): boolean {
|
|
958
|
+
return approvalDecisions.size > 0;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Whether the PRIMARY send delivers the turn's vision payload. The invariant
|
|
963
|
+
* is "images accompany the user's turn message, wherever the conversation
|
|
964
|
+
* does not already hold them" — so the only send that skips them is a HITL
|
|
965
|
+
* re-invocation of a successfully RESUMED agent, whose native conversation
|
|
966
|
+
* carries the images from the original send. A fresh agent mid-HITL
|
|
967
|
+
* (resolution-time resume failure — issue #366's vision corollary) holds
|
|
968
|
+
* nothing and needs the re-delivery. The mid-send recovery retries always
|
|
969
|
+
* run on a fresh agent, so their send sites carry the payload
|
|
970
|
+
* unconditionally rather than consulting this.
|
|
971
|
+
*/
|
|
972
|
+
export function primarySendCarriesImages(
|
|
973
|
+
approvalDecisions: ReadonlyMap<string, ApprovalAction>,
|
|
974
|
+
reason: AgentResolutionReason,
|
|
975
|
+
): boolean {
|
|
976
|
+
return !(isHitlReinvocation(approvalDecisions) && reason === "resumed_successfully");
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* Whether a prompt built for this resolution carries the STANDING context —
|
|
981
|
+
* instructions, skills, declared preferences, recalled memories, session
|
|
982
|
+
* context. Exactly one resolution shape does not: a successfully RESUMED
|
|
983
|
+
* agent, whose native conversation already holds the first message's
|
|
984
|
+
* context (both its prompt shapes — the raw follow-up and the
|
|
985
|
+
* decisions-only HITL reinvocation — send no standing sections).
|
|
986
|
+
*
|
|
987
|
+
* The named authority for that routing property (the
|
|
988
|
+
* primarySendCarriesImages idiom): buildPrompt's internal routing and the
|
|
989
|
+
* activity's standing-context preparation (e.g. the memory selection gate)
|
|
990
|
+
* both consult THIS predicate, so the two can never drift.
|
|
991
|
+
*/
|
|
992
|
+
export function promptCarriesStandingContext(reason: AgentResolutionReason): boolean {
|
|
993
|
+
return reason !== "resumed_successfully";
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Append the structured-output contract to a prompt when the execution
|
|
998
|
+
* requests one. A per-turn directive (the buildFromPlan rule): it must ride
|
|
999
|
+
* every prompt this turn sends — the primary send AND the poisoned-handle
|
|
1000
|
+
* recovery rebuild, which previously lost it (issue #366 ride-along).
|
|
1001
|
+
*/
|
|
1002
|
+
export function appendStructuredOutputDirective(
|
|
1003
|
+
basePrompt: string,
|
|
1004
|
+
schema: Record<string, unknown> | undefined,
|
|
1005
|
+
): string {
|
|
1006
|
+
if (!schema) return basePrompt;
|
|
1007
|
+
const schemaStr = JSON.stringify(schema, null, 2);
|
|
1008
|
+
return basePrompt + `\n\n---\nCRITICAL OUTPUT REQUIREMENT:\nYour final response MUST be a single valid JSON object (no markdown, no commentary, no code fences) that matches this schema:\n${schemaStr}\n\nRespond with ONLY the JSON object. Nothing else.`;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
export function buildPrompt(input: BuildPromptInput): string {
|
|
1012
|
+
const {
|
|
1013
|
+
resolution,
|
|
1014
|
+
approvalDecisions,
|
|
1015
|
+
instructions,
|
|
1016
|
+
userMessage,
|
|
1017
|
+
skills,
|
|
1018
|
+
subAgents,
|
|
1019
|
+
workspaceDirs,
|
|
1020
|
+
workspaceFileRefs,
|
|
1021
|
+
attachments,
|
|
1022
|
+
interactionMode,
|
|
1023
|
+
buildFromPlan,
|
|
1024
|
+
conversationCatchup,
|
|
1025
|
+
} = input;
|
|
1026
|
+
|
|
1027
|
+
// HITL reinvocation: the decisions-only prompt is correct ONLY while the
|
|
1028
|
+
// agent's native context still carries the prior conversation — which only
|
|
1029
|
+
// resumed_successfully guarantees. Any other reason means a fresh agent
|
|
1030
|
+
// mid-HITL (in practice created_after_resume_failure: the stored handle
|
|
1031
|
+
// failed to resume, or a poisoned handle was replaced mid-send), which
|
|
1032
|
+
// gets the full recovery shape instead — enhanced context + the turn's
|
|
1033
|
+
// recorded transcript + the same decisions — because the bare decisions on
|
|
1034
|
+
// an empty conversation strand the agent with instructions and no story,
|
|
1035
|
+
// and the session inherits that amnesia permanently (issue #366).
|
|
1036
|
+
if (isHitlReinvocation(approvalDecisions)) {
|
|
1037
|
+
if (promptCarriesStandingContext(resolution.reason)) {
|
|
1038
|
+
return buildHitlRecoveryPrompt(
|
|
1039
|
+
{
|
|
1040
|
+
instructions,
|
|
1041
|
+
userMessage,
|
|
1042
|
+
skills,
|
|
1043
|
+
channelMessaging: input.channelMessaging ?? [],
|
|
1044
|
+
subAgents,
|
|
1045
|
+
workspaceDirs,
|
|
1046
|
+
workspaceFileRefs,
|
|
1047
|
+
attachments,
|
|
1048
|
+
vision: input.vision,
|
|
1049
|
+
downloadUrlKind: input.downloadUrlKind,
|
|
1050
|
+
interactionMode,
|
|
1051
|
+
buildFromPlan,
|
|
1052
|
+
contextBridge: input.contextBridge,
|
|
1053
|
+
senderIdentity: input.senderIdentity,
|
|
1054
|
+
sessionContext: input.sessionContext,
|
|
1055
|
+
declaredPreferences: input.declaredPreferences,
|
|
1056
|
+
recalledMemories: input.recalledMemories,
|
|
1057
|
+
conversationCatchup,
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
turnDigest: input.turnRecoveryDigest,
|
|
1061
|
+
pendingApprovals: input.pendingApprovals,
|
|
1062
|
+
approvalDecisions,
|
|
1063
|
+
appliedToolCallIds: input.appliedToolCallIds,
|
|
1064
|
+
},
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
return buildReinvocationPrompt(
|
|
1068
|
+
input.pendingApprovals,
|
|
1069
|
+
approvalDecisions,
|
|
1070
|
+
input.appliedToolCallIds,
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// A successfully resumed agent carries its own conversation context via the
|
|
1075
|
+
// SDK's native store — send the raw user message with no preamble. The
|
|
1076
|
+
// exceptions are the per-EXECUTION values, which never inherit from the
|
|
1077
|
+
// session's first turn: the interaction-mode prefix (a follow-up can switch
|
|
1078
|
+
// Agent→Plan mid-session, and for Cursor the prompt is the only plan-mode
|
|
1079
|
+
// enforcement), the implement-plan directive (the build turn is usually a
|
|
1080
|
+
// follow-up on a resumed agent), THIS turn's attachments (spec.attachments
|
|
1081
|
+
// is per-execution — a file sent on a follow-up turn materializes for this
|
|
1082
|
+
// turn and would otherwise never be announced at all), and the conversation
|
|
1083
|
+
// catchup (handback ALWAYS lands mid-session on a resumed agent — this
|
|
1084
|
+
// prefix is the property the metadata lane structurally cannot deliver,
|
|
1085
|
+
// cloud DD-006). Catchup last: it is context, and context sits closest to
|
|
1086
|
+
// the task (the enhanced prompt's own ordering doctrine); the input files
|
|
1087
|
+
// precede it because they are this turn's payload, not background.
|
|
1088
|
+
if (!promptCarriesStandingContext(resolution.reason)) {
|
|
1089
|
+
const prefixes = [
|
|
1090
|
+
formatInteractionModePrefix(interactionMode),
|
|
1091
|
+
formatImplementPlanSection(buildFromPlan, attachments),
|
|
1092
|
+
attachments.length > 0
|
|
1093
|
+
? formatInputFiles(attachments, input.vision, input.downloadUrlKind)
|
|
1094
|
+
: undefined,
|
|
1095
|
+
conversationCatchup !== undefined
|
|
1096
|
+
? formatConversationCatchupSection(conversationCatchup)
|
|
1097
|
+
: undefined,
|
|
1098
|
+
].filter((p): p is string => p !== undefined);
|
|
1099
|
+
return prefixes.length > 0
|
|
1100
|
+
? [...prefixes, userMessage].join("\n\n")
|
|
1101
|
+
: userMessage;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// First execution, or a fresh agent created after a resume failure: there is
|
|
1105
|
+
// no prior conversation to inherit, so start a new turn with full context —
|
|
1106
|
+
// including the rollover bridge, when the session carries one.
|
|
1107
|
+
return buildEnhancedPrompt({
|
|
1108
|
+
instructions,
|
|
1109
|
+
userMessage,
|
|
1110
|
+
skills,
|
|
1111
|
+
channelMessaging: input.channelMessaging ?? [],
|
|
1112
|
+
subAgents,
|
|
1113
|
+
workspaceDirs,
|
|
1114
|
+
workspaceFileRefs,
|
|
1115
|
+
attachments,
|
|
1116
|
+
vision: input.vision,
|
|
1117
|
+
downloadUrlKind: input.downloadUrlKind,
|
|
1118
|
+
interactionMode,
|
|
1119
|
+
buildFromPlan,
|
|
1120
|
+
contextBridge: input.contextBridge,
|
|
1121
|
+
senderIdentity: input.senderIdentity,
|
|
1122
|
+
sessionContext: input.sessionContext,
|
|
1123
|
+
declaredPreferences: input.declaredPreferences,
|
|
1124
|
+
recalledMemories: input.recalledMemories,
|
|
1125
|
+
conversationCatchup,
|
|
1126
|
+
});
|
|
1127
|
+
}
|