@stigmer/runner 3.14.1 → 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 +28 -5
- package/dist/__test-utils__/hermetic-activity.js +23 -7
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- 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 +38 -62
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +47 -121
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +17 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -4
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +52 -11
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +66 -7
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
- 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 +16 -0
- package/dist/harness/capabilities.js +1 -0
- package/dist/harness/capabilities.js.map +1 -1
- 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 +44 -5
- package/dist/harness/registry.js +61 -5
- package/dist/harness/registry.js.map +1 -1
- 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 +232 -52
- package/dist/harness/types.js +17 -8
- package/dist/harness/types.js.map +1 -1
- 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 +110 -14
- 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 +128 -83
- package/src/__test-utils__/harness-contract/recording-sink.ts +15 -4
- package/src/__test-utils__/harness-contract/runtime-contract.ts +666 -0
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +92 -32
- package/src/__test-utils__/harness-contract/types.ts +85 -9
- package/src/__test-utils__/hermetic-activity.ts +33 -8
- package/src/__test-utils__/model-registry-fixture.ts +72 -0
- package/src/__test-utils__/module-specifiers.ts +82 -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 +7 -5
- 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 +65 -145
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +30 -4
- package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +96 -8
- 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 +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +53 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +1 -6
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +56 -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/unattributed-hook-block.status.json +79 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +2 -7
- 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 +22 -18
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +1 -1
- 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 +1 -1
- 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 +1 -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 +17 -0
- package/src/harness/persist-chokepoint.ts +112 -0
- package/src/harness/registry.ts +79 -5
- 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 +248 -53
- 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
|
@@ -21,17 +21,24 @@
|
|
|
21
21
|
* (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule());
|
|
22
22
|
* ```
|
|
23
23
|
*
|
|
24
|
-
* Network: the
|
|
25
|
-
* (`
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* one registry document — and to THROW for any other URL, so a new network
|
|
29
|
-
* dependency on the activity path fails the hermetic run instead of leaking.
|
|
24
|
+
* Network: the registry document and the `fetch` stub that serves it are
|
|
25
|
+
* the runtime's fixtures (`src/__test-utils__/model-registry-fixture.ts`);
|
|
26
|
+
* the record's four resources come from `execution-record-fixture.ts` with
|
|
27
|
+
* this harness's ids and model laid over the defaults.
|
|
30
28
|
*
|
|
31
29
|
* The fixture model is `composer-2.5`, pinned (not Auto) on purpose: Auto short-
|
|
32
30
|
* circuits `resolveServiceTierParams` before the catalog, and a pinned model runs
|
|
33
31
|
* the catalog path, the variant-param pinning, and the `run.wait()` model echo
|
|
34
32
|
* check — more of the production path under the golden.
|
|
33
|
+
*
|
|
34
|
+
* Where a scenario reaches the knobs that drive the terminal table, each on
|
|
35
|
+
* the object that models the thing deciding it: the execution's cost budget
|
|
36
|
+
* and the control plane's STOP answer on the record (`CursorRecordOptions`);
|
|
37
|
+
* a control-plane fault on the client (`clientOverrides`); the runner's stall
|
|
38
|
+
* and lock windows on the scenario's `Config` (`config`); an SDK failure on
|
|
39
|
+
* the SDK double (`ScriptedSdkOptions`); an SDK-side cancel or a mid-stream
|
|
40
|
+
* wedge as an `effect` step on the run. Nothing here is a switch in production
|
|
41
|
+
* code — every knob is a value the production path already reads.
|
|
35
42
|
*/
|
|
36
43
|
|
|
37
44
|
import { execFileSync } from "node:child_process";
|
|
@@ -39,31 +46,13 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
39
46
|
import { dirname, join } from "node:path";
|
|
40
47
|
import { create } from "@bufbuild/protobuf";
|
|
41
48
|
import type { ModelListItem } from "@cursor/sdk";
|
|
42
|
-
import { vi } from "vitest";
|
|
43
|
-
import {
|
|
44
|
-
AgentExecutionSchema,
|
|
45
|
-
type AgentExecution,
|
|
46
|
-
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
47
|
-
import {
|
|
48
|
-
AgentExecutionSpecSchema,
|
|
49
|
-
ExecutionConfigSchema,
|
|
50
|
-
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
|
|
51
|
-
import { SessionSchema, type Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
52
|
-
import { SessionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/spec_pb";
|
|
53
49
|
import {
|
|
54
50
|
LocalPathSourceSchema,
|
|
55
51
|
WorkspaceEntrySchema,
|
|
56
52
|
WorkspaceSourceSchema,
|
|
57
53
|
type WorkspaceEntry,
|
|
58
54
|
} from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
|
|
59
|
-
import {
|
|
60
|
-
import { AgentSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
61
|
-
import {
|
|
62
|
-
AgentInstanceSchema,
|
|
63
|
-
type AgentInstance,
|
|
64
|
-
} from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
|
|
65
|
-
import { AgentInstanceSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/spec_pb";
|
|
66
|
-
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
55
|
+
import type { StigmerClient } from "../../../client/stigmer-client.js";
|
|
67
56
|
import type { Config } from "../../../config.js";
|
|
68
57
|
import type { ExecuteActivityInput } from "../../../shared/activity-input.js";
|
|
69
58
|
import {
|
|
@@ -75,6 +64,8 @@ import {
|
|
|
75
64
|
type HermeticEnvironment,
|
|
76
65
|
type InvocationControls,
|
|
77
66
|
} from "../../../__test-utils__/hermetic-activity.js";
|
|
67
|
+
import { executionRecordFixture, type ExecutionRecordOptions } from "../../../__test-utils__/execution-record-fixture.js";
|
|
68
|
+
import { FIXTURE_MODEL } from "../../../__test-utils__/model-registry-fixture.js";
|
|
78
69
|
import { _resetAgentSessionCacheForTests } from "../agent-session-cache.js";
|
|
79
70
|
import { _resetPricingCache } from "../model-pricing-data.js";
|
|
80
71
|
import { resetCatalogCacheForTests } from "../service-tier.js";
|
|
@@ -92,8 +83,8 @@ export const FIXTURE = {
|
|
|
92
83
|
agentInstanceId: "ain_hermetic_0001",
|
|
93
84
|
agentId: "agt_hermetic_0001",
|
|
94
85
|
agentName: "hermetic-agent",
|
|
95
|
-
/** The pinned model; in the registry
|
|
96
|
-
model:
|
|
86
|
+
/** The pinned model; in the registry fixture AND the SDK catalog below. */
|
|
87
|
+
model: FIXTURE_MODEL,
|
|
97
88
|
cursorApiKey: "hermetic-cursor-api-key",
|
|
98
89
|
} as const;
|
|
99
90
|
|
|
@@ -101,105 +92,29 @@ export const FIXTURE = {
|
|
|
101
92
|
// The record
|
|
102
93
|
// ---------------------------------------------------------------------------
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
readonly message: string;
|
|
107
|
-
/** The agent's instructions (system prompt body). */
|
|
108
|
-
readonly instructions?: string;
|
|
109
|
-
/** Session workspace entries (a `local_path` entry turns on capture mode). */
|
|
110
|
-
readonly workspaceEntries?: WorkspaceEntry[];
|
|
111
|
-
readonly modelName?: string;
|
|
112
|
-
readonly autoApproveAll?: boolean;
|
|
113
|
-
}
|
|
95
|
+
/** The record's knobs; the ids and the default model are this harness's fixture. */
|
|
96
|
+
export type CursorRecordOptions = Omit<ExecutionRecordOptions, "ids">;
|
|
114
97
|
|
|
115
|
-
/** The four resources of one execution, wired by id into a chain. */
|
|
98
|
+
/** The four resources of one execution, wired by id into a chain, under the Cursor fixture ids. */
|
|
116
99
|
export function cursorExecutionRecord(options: CursorRecordOptions): ExecutionRecord {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
100
|
+
return executionRecordFixture({
|
|
101
|
+
...options,
|
|
102
|
+
modelName: options.modelName ?? FIXTURE.model,
|
|
103
|
+
ids: {
|
|
120
104
|
org: FIXTURE.org,
|
|
121
|
-
|
|
122
|
-
}),
|
|
123
|
-
spec: create(AgentExecutionSpecSchema, {
|
|
105
|
+
executionId: FIXTURE.executionId,
|
|
124
106
|
sessionId: FIXTURE.sessionId,
|
|
125
|
-
message: options.message,
|
|
126
|
-
autoApproveAll: options.autoApproveAll ?? false,
|
|
127
|
-
executionConfig: create(ExecutionConfigSchema, {
|
|
128
|
-
modelName: options.modelName ?? FIXTURE.model,
|
|
129
|
-
}),
|
|
130
|
-
}),
|
|
131
|
-
});
|
|
132
|
-
const session: Session = create(SessionSchema, {
|
|
133
|
-
metadata: create(ApiResourceMetadataSchema, {
|
|
134
|
-
id: FIXTURE.sessionId,
|
|
135
|
-
org: FIXTURE.org,
|
|
136
|
-
name: FIXTURE.sessionId,
|
|
137
|
-
}),
|
|
138
|
-
spec: create(SessionSpecSchema, {
|
|
139
107
|
agentInstanceId: FIXTURE.agentInstanceId,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const agentInstance: AgentInstance = create(AgentInstanceSchema, {
|
|
144
|
-
metadata: create(ApiResourceMetadataSchema, {
|
|
145
|
-
id: FIXTURE.agentInstanceId,
|
|
146
|
-
org: FIXTURE.org,
|
|
147
|
-
name: FIXTURE.agentInstanceId,
|
|
148
|
-
}),
|
|
149
|
-
spec: create(AgentInstanceSpecSchema, { agentId: FIXTURE.agentId }),
|
|
150
|
-
});
|
|
151
|
-
const agent: Agent = create(AgentSchema, {
|
|
152
|
-
metadata: create(ApiResourceMetadataSchema, {
|
|
153
|
-
id: FIXTURE.agentId,
|
|
154
|
-
org: FIXTURE.org,
|
|
155
|
-
name: FIXTURE.agentName,
|
|
156
|
-
}),
|
|
157
|
-
spec: create(AgentSpecSchema, {
|
|
158
|
-
description: "Hermetic fixture agent",
|
|
159
|
-
instructions: options.instructions ?? "You are the hermetic fixture agent. Answer briefly.",
|
|
160
|
-
}),
|
|
108
|
+
agentId: FIXTURE.agentId,
|
|
109
|
+
agentName: FIXTURE.agentName,
|
|
110
|
+
},
|
|
161
111
|
});
|
|
162
|
-
return new ExecutionRecord({ execution, session, agentInstance, agent });
|
|
163
112
|
}
|
|
164
113
|
|
|
165
114
|
// ---------------------------------------------------------------------------
|
|
166
|
-
// The
|
|
115
|
+
// The SDK catalog
|
|
167
116
|
// ---------------------------------------------------------------------------
|
|
168
117
|
|
|
169
|
-
/**
|
|
170
|
-
* The model registry document both readers parse (`parsePricingTable` wants
|
|
171
|
-
* `harness: "cursor"` + `pricing`; `parseRegistry` wants `id` + `provider` and
|
|
172
|
-
* reads `capabilities.vision`). One entry, the fixture model, priced at round
|
|
173
|
-
* numbers so the golden's `estimatedCostUsd` is legible.
|
|
174
|
-
*/
|
|
175
|
-
export const REGISTRY_DOCUMENT = {
|
|
176
|
-
models: [
|
|
177
|
-
{
|
|
178
|
-
id: FIXTURE.model,
|
|
179
|
-
displayName: "Composer 2.5 (hermetic fixture)",
|
|
180
|
-
provider: "cursor",
|
|
181
|
-
harness: "cursor",
|
|
182
|
-
costTier: "standard",
|
|
183
|
-
featured: true,
|
|
184
|
-
capabilities: { vision: true },
|
|
185
|
-
pricing: {
|
|
186
|
-
inputPricePerMillion: 1.0,
|
|
187
|
-
outputPricePerMillion: 4.0,
|
|
188
|
-
cacheWritePricePerMillion: 1.0,
|
|
189
|
-
cacheReadPricePerMillion: 0.1,
|
|
190
|
-
},
|
|
191
|
-
pricingVariants: {
|
|
192
|
-
fast: {
|
|
193
|
-
inputPricePerMillion: 3.0,
|
|
194
|
-
outputPricePerMillion: 12.0,
|
|
195
|
-
cacheWritePricePerMillion: 3.0,
|
|
196
|
-
cacheReadPricePerMillion: 0.3,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
} as const;
|
|
202
|
-
|
|
203
118
|
/** The SDK catalog entry for the fixture model: both pinnable params declared. */
|
|
204
119
|
export const SDK_CATALOG: readonly ModelListItem[] = [
|
|
205
120
|
{
|
|
@@ -212,26 +127,6 @@ export const SDK_CATALOG: readonly ModelListItem[] = [
|
|
|
212
127
|
},
|
|
213
128
|
];
|
|
214
129
|
|
|
215
|
-
/**
|
|
216
|
-
* Stub `fetch` to answer the registry document and refuse everything else.
|
|
217
|
-
* Returns the URLs fetched, for the "no other network" assertion.
|
|
218
|
-
*/
|
|
219
|
-
export function stubRegistryFetch(): { readonly urls: string[]; restore(): void } {
|
|
220
|
-
const urls: string[] = [];
|
|
221
|
-
vi.stubGlobal(
|
|
222
|
-
"fetch",
|
|
223
|
-
vi.fn(async (input: string | URL | Request) => {
|
|
224
|
-
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
225
|
-
urls.push(url);
|
|
226
|
-
if (!url.includes("/model-registry")) {
|
|
227
|
-
throw new Error(`hermetic run attempted a non-registry network call: ${url}`);
|
|
228
|
-
}
|
|
229
|
-
return { ok: true, status: 200, json: async () => REGISTRY_DOCUMENT } as unknown as Response;
|
|
230
|
-
}),
|
|
231
|
-
);
|
|
232
|
-
return { urls, restore: () => vi.unstubAllGlobals() };
|
|
233
|
-
}
|
|
234
|
-
|
|
235
130
|
// ---------------------------------------------------------------------------
|
|
236
131
|
// Config
|
|
237
132
|
// ---------------------------------------------------------------------------
|
|
@@ -369,6 +264,8 @@ export interface CursorScenario {
|
|
|
369
264
|
readonly clock: ScriptedClock;
|
|
370
265
|
readonly record: ExecutionRecord;
|
|
371
266
|
readonly sdk: ScriptedCursorSdk;
|
|
267
|
+
/** The runner this scenario runs on: the OSS posture plus the scenario's knobs. */
|
|
268
|
+
readonly config: Config;
|
|
372
269
|
}
|
|
373
270
|
|
|
374
271
|
export interface CursorScenarioOptions {
|
|
@@ -376,6 +273,19 @@ export interface CursorScenarioOptions {
|
|
|
376
273
|
readonly clock: ScriptedClock;
|
|
377
274
|
readonly record: ExecutionRecord;
|
|
378
275
|
readonly sdk: ScriptedSdkOptions;
|
|
276
|
+
/**
|
|
277
|
+
* Control-plane facets the scenario opts INTO, or faults it injects, over
|
|
278
|
+
* the record's everyday answers (`ExecutionRecord.client`): a rejecting
|
|
279
|
+
* `getAgent` is how a blueprint-resolution failure is staged.
|
|
280
|
+
*/
|
|
281
|
+
readonly clientOverrides?: Partial<StigmerClient>;
|
|
282
|
+
/**
|
|
283
|
+
* Runner knobs over {@link hermeticCursorConfig}: a scenario that needs the
|
|
284
|
+
* stall watchdog or the workspace-lock wait to expire states the window
|
|
285
|
+
* here. A property of the runner the scenario runs on, not of one turn, so
|
|
286
|
+
* it lives on the scenario and every turn of it sees the same `Config`.
|
|
287
|
+
*/
|
|
288
|
+
readonly config?: Partial<Config>;
|
|
379
289
|
}
|
|
380
290
|
|
|
381
291
|
/** Bind the record and the SDK for a scenario; resets the harness caches first. */
|
|
@@ -383,8 +293,14 @@ export function beginCursorScenario(options: CursorScenarioOptions): CursorScena
|
|
|
383
293
|
resetCursorModuleState();
|
|
384
294
|
const sdk = new ScriptedCursorSdk(options.sdk);
|
|
385
295
|
bindScriptedSdk(sdk);
|
|
386
|
-
bindHermeticClient(options.record.client());
|
|
387
|
-
return {
|
|
296
|
+
bindHermeticClient(options.record.client(options.clientOverrides));
|
|
297
|
+
return {
|
|
298
|
+
env: options.env,
|
|
299
|
+
clock: options.clock,
|
|
300
|
+
record: options.record,
|
|
301
|
+
sdk,
|
|
302
|
+
config: { ...hermeticCursorConfig(options.env), ...options.config },
|
|
303
|
+
};
|
|
388
304
|
}
|
|
389
305
|
|
|
390
306
|
export interface CursorTurnOptions {
|
|
@@ -396,26 +312,30 @@ export interface CursorTurnOptions {
|
|
|
396
312
|
}
|
|
397
313
|
|
|
398
314
|
/**
|
|
399
|
-
* Run ONE `ExecuteCursor` invocation for the scenario
|
|
400
|
-
*
|
|
401
|
-
*
|
|
315
|
+
* Run ONE `ExecuteCursor` invocation for the scenario: the real Cursor
|
|
316
|
+
* adapter under the real turn runtime, as the composition roots wire them.
|
|
317
|
+
* Built per invocation (the registry constructs its client, which is the one
|
|
318
|
+
* bound at `beginCursorScenario`; the adapter boots on the scenario's config).
|
|
402
319
|
*/
|
|
403
320
|
export async function runCursorTurn(
|
|
404
321
|
scenario: CursorScenario,
|
|
405
322
|
options: CursorTurnOptions = {},
|
|
406
323
|
): Promise<ActivityInvocation> {
|
|
407
324
|
// Imported lazily so the scenario file's `vi.mock` declarations are in
|
|
408
|
-
// force before the
|
|
409
|
-
//
|
|
410
|
-
const {
|
|
411
|
-
const
|
|
325
|
+
// force before the adapter module is loaded and before its `boot` loads
|
|
326
|
+
// `@cursor/sdk` (through `turn.ts`) and the registry loads the client.
|
|
327
|
+
const { createCursorAdapter } = await import("../adapter.js");
|
|
328
|
+
const { createHarnessActivities } = await import("../../../harness/registry.js");
|
|
329
|
+
const adapter = createCursorAdapter();
|
|
330
|
+
await adapter.boot(scenario.config);
|
|
331
|
+
const activities = await createHarnessActivities([{ harness: "cursor", adapter }], scenario.config);
|
|
412
332
|
// The typed wire shape the control plane's workflow sends (activity-input.ts).
|
|
413
333
|
const input: ExecuteActivityInput = {
|
|
414
334
|
execution_id: scenario.record.executionId,
|
|
415
335
|
thread_id: options.threadId ?? "",
|
|
416
336
|
turn_seq: options.turnSeq ?? 0,
|
|
417
337
|
};
|
|
418
|
-
return runActivityHermetically(activities.ExecuteCursor
|
|
338
|
+
return runActivityHermetically(activities.ExecuteCursor!, [input], {
|
|
419
339
|
taskQueue: "hermetic-test-queue",
|
|
420
340
|
onControls: options.onControls,
|
|
421
341
|
});
|
|
@@ -42,7 +42,11 @@
|
|
|
42
42
|
*
|
|
43
43
|
* Every `send()` consumes the NEXT script in the agent's queue: turn 1, then
|
|
44
44
|
* the resumed turn 2 on the same parked agent. A `send()` with no script left
|
|
45
|
-
* is a test bug and throws.
|
|
45
|
+
* is a test bug and throws. A golden scenario declares every script up front
|
|
46
|
+
* (`turns`); a driver that learns what the next turn plays only just before
|
|
47
|
+
* it runs — the harness contract kit's Cursor subject — arranges it with
|
|
48
|
+
* {@link ScriptedCursorAgent.arrangeNextTurn}, which REPLACES the slot the
|
|
49
|
+
* next `send()` will consume.
|
|
46
50
|
*/
|
|
47
51
|
|
|
48
52
|
import type {
|
|
@@ -284,6 +288,11 @@ export interface RecordedSend {
|
|
|
284
288
|
readonly hasOnDelta: boolean;
|
|
285
289
|
}
|
|
286
290
|
|
|
291
|
+
/** The run id a send is given when the scenario named none: `run-<agentId>-<n>`, `n` counting sends from 1. */
|
|
292
|
+
export function defaultRunId(agentId: string, sendIndex: number): string {
|
|
293
|
+
return `run-${agentId}-${sendIndex + 1}`;
|
|
294
|
+
}
|
|
295
|
+
|
|
287
296
|
export class ScriptedCursorAgent implements SDKAgent {
|
|
288
297
|
readonly agentId: string;
|
|
289
298
|
model: ModelSelection | undefined = undefined;
|
|
@@ -291,20 +300,37 @@ export class ScriptedCursorAgent implements SDKAgent {
|
|
|
291
300
|
readonly runs: ScriptedRun[] = [];
|
|
292
301
|
closeCalls = 0;
|
|
293
302
|
private nextTurn = 0;
|
|
303
|
+
/** The scenario's scripts, one slot per send; `arrangeNextTurn` writes the slot the next send consumes. */
|
|
304
|
+
private readonly turns: TurnScript[];
|
|
294
305
|
|
|
295
306
|
constructor(private readonly options: ScriptedAgentOptions) {
|
|
296
307
|
this.agentId = options.agentId;
|
|
308
|
+
this.turns = [...options.turns];
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** The run id the NEXT `send()` will be given — so a script can be built with matching event ids before the send happens. */
|
|
312
|
+
get nextRunId(): string {
|
|
313
|
+
return this.options.runIds?.[this.nextTurn] ?? defaultRunId(this.agentId, this.nextTurn);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Set (or replace) what the NEXT `send()` plays. Scripts already consumed
|
|
318
|
+
* are untouched; a slot declared up front for a later send stays where it
|
|
319
|
+
* is.
|
|
320
|
+
*/
|
|
321
|
+
arrangeNextTurn(script: TurnScript): void {
|
|
322
|
+
this.turns[this.nextTurn] = script;
|
|
297
323
|
}
|
|
298
324
|
|
|
299
325
|
async send(message: string | SDKUserMessage, options?: SendOptions): Promise<Run> {
|
|
300
|
-
const script = this.
|
|
326
|
+
const script = this.turns[this.nextTurn];
|
|
301
327
|
if (!script) {
|
|
302
328
|
throw new Error(
|
|
303
329
|
`ScriptedCursorAgent ${this.agentId}: send() #${this.nextTurn + 1} has no script ` +
|
|
304
|
-
`(the scenario declared ${this.
|
|
330
|
+
`(the scenario declared ${this.turns.length})`,
|
|
305
331
|
);
|
|
306
332
|
}
|
|
307
|
-
const runId = this.
|
|
333
|
+
const runId = this.nextRunId;
|
|
308
334
|
this.nextTurn++;
|
|
309
335
|
this.sends.push({ message, hasOnDelta: !!options?.onDelta });
|
|
310
336
|
if (options?.model) this.model = options.model;
|
|
@@ -26,11 +26,18 @@
|
|
|
26
26
|
* scenarios with different agents against the same mocked module.
|
|
27
27
|
*
|
|
28
28
|
* Resolution rules a scenario declares, mirroring what the real SDK does:
|
|
29
|
-
* - `Agent.create` hands out the
|
|
30
|
-
*
|
|
29
|
+
* - `Agent.create` hands out the agent declared for the session it is asked
|
|
30
|
+
* for (`agentForSession`, when the scenario resolves agents per session —
|
|
31
|
+
* the harness contract kit runs several sessions concurrently on one
|
|
32
|
+
* adapter, and the order their creates arrive in is real I/O timing), else
|
|
33
|
+
* the NEXT unclaimed agent in `agents` (turn 1 of a fresh session; the fresh
|
|
34
|
+
* agent of a poisoned-handle recovery) — unless the scenario declared a
|
|
35
|
+
* `createFailure`, which the FIRST create throws instead (the SDK refusing
|
|
36
|
+
* to mint an agent: a 401 on the key, a validation error).
|
|
31
37
|
* - `Agent.resume(id)` hands back the agent with that id if the scenario
|
|
32
|
-
* declared it (in `agents` or `resumableAgents
|
|
33
|
-
* then falls back to `create`, which
|
|
38
|
+
* declared it (in `agents` or `resumableAgents`, or handed out for a
|
|
39
|
+
* session), else throws — `resolveAgent` then falls back to `create`, which
|
|
40
|
+
* is the production shape of a lost handle.
|
|
34
41
|
* - `Cursor.models.list` answers the scenario's catalog.
|
|
35
42
|
*/
|
|
36
43
|
|
|
@@ -40,11 +47,29 @@ import type { ScriptedCursorAgent } from "./scripted-agent.js";
|
|
|
40
47
|
export interface ScriptedSdkOptions {
|
|
41
48
|
/** Agents handed out by `Agent.create`, in order. Also resumable by id. */
|
|
42
49
|
readonly agents: readonly ScriptedCursorAgent[];
|
|
50
|
+
/**
|
|
51
|
+
* The agent `Agent.create` hands out for the session the create names,
|
|
52
|
+
* consulted before the ordered list. The SDK's create options carry the
|
|
53
|
+
* session as `platform.workspaceRef` (`session-lifecycle.ts`
|
|
54
|
+
* `resolvePlatformOptions`: `stigmer-session:<sessionId>`), so the resolver
|
|
55
|
+
* is keyed by that ref — a scenario computes the ref the same way the
|
|
56
|
+
* adapter does. `undefined` falls through to the list. Consulted live on
|
|
57
|
+
* every create, so a scenario may mint the session's agent only when it
|
|
58
|
+
* learns of the session.
|
|
59
|
+
*/
|
|
60
|
+
readonly agentForWorkspaceRef?: (workspaceRef: string) => ScriptedCursorAgent | undefined;
|
|
43
61
|
/**
|
|
44
62
|
* Agents `Agent.resume` finds by id but `Agent.create` never hands out — a
|
|
45
63
|
* previous turn's agent the session knows only by `harness_state_id`.
|
|
46
64
|
*/
|
|
47
65
|
readonly resumableAgents?: readonly ScriptedCursorAgent[];
|
|
66
|
+
/**
|
|
67
|
+
* Thrown by the FIRST `Agent.create` instead of handing out an agent; later
|
|
68
|
+
* creates hand out `agents` as usual. A {@link ScriptedCursorSdkError} here is
|
|
69
|
+
* the SDK's own refusal (the activity's outer catch keys on `instanceof`);
|
|
70
|
+
* a plain `Error` is anything else that can escape the SDK boundary.
|
|
71
|
+
*/
|
|
72
|
+
readonly createFailure?: Error;
|
|
48
73
|
/** What `Cursor.models.list` answers. */
|
|
49
74
|
readonly catalog: readonly ModelListItem[];
|
|
50
75
|
}
|
|
@@ -56,19 +81,47 @@ export interface RecordedResolution {
|
|
|
56
81
|
readonly options: Partial<AgentOptions> | undefined;
|
|
57
82
|
}
|
|
58
83
|
|
|
84
|
+
/**
|
|
85
|
+
* The `platform.workspaceRef` a create names, read defensively: the platform
|
|
86
|
+
* option's type re-exports from the unshipped `@anysphere/cursor-sdk-local-runtime`
|
|
87
|
+
* and resolves to `any` under `skipLibCheck` (the same gap `scripted-agent.ts`
|
|
88
|
+
* records for the delta channel), so the shape is checked here, not assumed.
|
|
89
|
+
*/
|
|
90
|
+
function workspaceRefOf(options: AgentOptions): string | undefined {
|
|
91
|
+
const platform: unknown = (options as { platform?: unknown }).platform;
|
|
92
|
+
if (typeof platform !== "object" || platform === null) return undefined;
|
|
93
|
+
const ref = (platform as { workspaceRef?: unknown }).workspaceRef;
|
|
94
|
+
return typeof ref === "string" ? ref : undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
59
97
|
export class ScriptedCursorSdk {
|
|
60
98
|
readonly resolutions: RecordedResolution[] = [];
|
|
61
99
|
readonly archived: string[] = [];
|
|
62
100
|
private nextCreate = 0;
|
|
101
|
+
private createFailurePending: boolean;
|
|
63
102
|
private readonly byId = new Map<string, ScriptedCursorAgent>();
|
|
64
103
|
|
|
65
104
|
constructor(private readonly options: ScriptedSdkOptions) {
|
|
66
105
|
for (const a of [...options.agents, ...(options.resumableAgents ?? [])]) {
|
|
67
106
|
this.byId.set(a.agentId, a);
|
|
68
107
|
}
|
|
108
|
+
this.createFailurePending = options.createFailure !== undefined;
|
|
69
109
|
}
|
|
70
110
|
|
|
71
111
|
create(options: AgentOptions): SDKAgent {
|
|
112
|
+
if (this.createFailurePending && this.options.createFailure) {
|
|
113
|
+
this.createFailurePending = false;
|
|
114
|
+
this.resolutions.push({ kind: "create", agentId: undefined, options });
|
|
115
|
+
throw this.options.createFailure;
|
|
116
|
+
}
|
|
117
|
+
const workspaceRef = workspaceRefOf(options);
|
|
118
|
+
const forSession = workspaceRef !== undefined ? this.options.agentForWorkspaceRef?.(workspaceRef) : undefined;
|
|
119
|
+
if (forSession) {
|
|
120
|
+
this.byId.set(forSession.agentId, forSession);
|
|
121
|
+
forSession.model = options.model;
|
|
122
|
+
this.resolutions.push({ kind: "create", agentId: forSession.agentId, options });
|
|
123
|
+
return forSession;
|
|
124
|
+
}
|
|
72
125
|
const agent = this.options.agents[this.nextCreate];
|
|
73
126
|
if (!agent) {
|
|
74
127
|
throw new Error(
|
|
@@ -101,20 +154,55 @@ export class ScriptedCursorSdk {
|
|
|
101
154
|
}
|
|
102
155
|
}
|
|
103
156
|
|
|
157
|
+
/** The construction options of the SDK's `CursorSdkError` (`errors.d.ts`), minus `cause`. */
|
|
158
|
+
export interface ScriptedCursorSdkErrorOptions {
|
|
159
|
+
readonly isRetryable?: boolean;
|
|
160
|
+
readonly code?: string;
|
|
161
|
+
readonly status?: number;
|
|
162
|
+
readonly endpoint?: string;
|
|
163
|
+
readonly requestId?: string;
|
|
164
|
+
readonly operation?: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
104
167
|
/**
|
|
105
168
|
* The `CursorSdkError` the mocked module exports. A real `Error` subclass with
|
|
106
|
-
* the
|
|
107
|
-
*
|
|
108
|
-
*
|
|
169
|
+
* the SDK class's public surface (`@cursor/sdk` `errors.d.ts`: `isRetryable`,
|
|
170
|
+
* `code`, `status`, `endpoint`, `requestId`, `operation`, `toJSON()`), under
|
|
171
|
+
* the SDK's class name so `err.constructor.name` and `instanceof` (against
|
|
172
|
+
* THIS module's export, which is what the activity's dynamic import resolves
|
|
173
|
+
* to) both hold. The activity's outer catch reads `code`, `status` and
|
|
174
|
+
* `message` for the classifier and logs `toJSON()`; the double must carry the
|
|
175
|
+
* whole surface or the catch arm itself throws instead of mapping the error.
|
|
109
176
|
*/
|
|
110
177
|
export class ScriptedCursorSdkError extends Error {
|
|
111
178
|
readonly isRetryable: boolean;
|
|
112
179
|
readonly code: string | undefined;
|
|
113
|
-
|
|
180
|
+
readonly status: number | undefined;
|
|
181
|
+
readonly endpoint: string | undefined;
|
|
182
|
+
readonly requestId: string | undefined;
|
|
183
|
+
readonly operation: string | undefined;
|
|
184
|
+
constructor(message: string, opts: ScriptedCursorSdkErrorOptions = {}) {
|
|
114
185
|
super(message);
|
|
115
186
|
this.name = "CursorSdkError";
|
|
116
187
|
this.isRetryable = opts.isRetryable ?? false;
|
|
117
188
|
this.code = opts.code;
|
|
189
|
+
this.status = opts.status;
|
|
190
|
+
this.endpoint = opts.endpoint;
|
|
191
|
+
this.requestId = opts.requestId;
|
|
192
|
+
this.operation = opts.operation;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
toJSON(): Record<string, unknown> {
|
|
196
|
+
return {
|
|
197
|
+
name: this.name,
|
|
198
|
+
message: this.message,
|
|
199
|
+
isRetryable: this.isRetryable,
|
|
200
|
+
code: this.code,
|
|
201
|
+
status: this.status,
|
|
202
|
+
endpoint: this.endpoint,
|
|
203
|
+
requestId: this.requestId,
|
|
204
|
+
operation: this.operation,
|
|
205
|
+
};
|
|
118
206
|
}
|
|
119
207
|
}
|
|
120
208
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins that the Cursor adapter is an SDK slice and nothing more: no
|
|
3
|
+
* production module under `activities/execute-cursor/` imports
|
|
4
|
+
* `@temporalio/*`.
|
|
5
|
+
*
|
|
6
|
+
* Why it matters: every Temporal fact a turn needs — the heartbeat, the
|
|
7
|
+
* cancellation, the throw the workflow sees — is the turn runtime's
|
|
8
|
+
* (`harness/run-turn.ts`) and reaches the adapter through the sink. The
|
|
9
|
+
* contract kit runs an adapter OUTSIDE any activity context
|
|
10
|
+
* (`__test-utils__/harness-contract/`), so a `Context.current()` anywhere
|
|
11
|
+
* in the adapter would throw there; and an adapter that threw a
|
|
12
|
+
* `CancelledFailure` would be deciding pause-vs-shutdown, which is the
|
|
13
|
+
* runtime's table. A static fence names the file in seconds where the kit
|
|
14
|
+
* would name it after a stack trace.
|
|
15
|
+
*
|
|
16
|
+
* Read off the syntax tree with the same primitive the import-direction
|
|
17
|
+
* fence uses (`__test-utils__/module-specifiers.ts`), so a package name in a
|
|
18
|
+
* comment cannot trip it and no import form can slip past it.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { describe, it, expect } from "vitest";
|
|
22
|
+
import { join, relative } from "node:path";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
|
|
25
|
+
import { packageImports, readSource, typeScriptFilesUnder } from "../../../__test-utils__/module-specifiers.js";
|
|
26
|
+
|
|
27
|
+
const SRC_ROOT = fileURLToPath(new URL("../../../", import.meta.url));
|
|
28
|
+
const ADAPTER_ROOT = join(SRC_ROOT, "activities", "execute-cursor");
|
|
29
|
+
|
|
30
|
+
describe("the Cursor adapter never imports @temporalio", () => {
|
|
31
|
+
const files = typeScriptFilesUnder(ADAPTER_ROOT, new Set(["__tests__", "__test-utils__"]));
|
|
32
|
+
const offences = files.flatMap((file) =>
|
|
33
|
+
packageImports(file, readSource(file), "@temporalio").map((specifier) => ` ${relative(SRC_ROOT, file)} imports "${specifier}"`),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
it("inspected the adapter's own files (the walk is rooted where it claims)", () => {
|
|
37
|
+
expect(files.map((f) => relative(ADAPTER_ROOT, f))).toEqual(
|
|
38
|
+
expect.arrayContaining(["adapter.ts", "turn.ts", "turn-setup.ts", "turn-stream.ts", "turn-settle.ts"]),
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("finds no @temporalio import in any production module", () => {
|
|
43
|
+
expect(offences, `the Cursor adapter must not import @temporalio/*:\n${offences.join("\n")}`).toEqual([]);
|
|
44
|
+
});
|
|
45
|
+
});
|