@stigmer/runner 3.15.0 → 3.15.2-dev.20260913223433
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/README.md +2 -4
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
- package/dist/__test-utils__/execution-record-fixture.js +4 -0
- package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
- package/dist/__test-utils__/file-review-projection.d.ts +40 -0
- package/dist/__test-utils__/file-review-projection.js +136 -0
- package/dist/__test-utils__/file-review-projection.js.map +1 -0
- package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
- package/dist/__test-utils__/harness-contract/types.js +15 -0
- package/dist/__test-utils__/harness-contract/types.js.map +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
- package/dist/__test-utils__/hermetic-activity.js +52 -14
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
- package/dist/__test-utils__/model-registry-fixture.js +31 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
- package/dist/__test-utils__/turn-input-fixture.js +1 -1
- package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
- package/dist/activities/call-agent.js +2 -2
- package/dist/activities/call-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +7 -5
- package/dist/activities/execute-cursor/adapter.js +7 -5
- package/dist/activities/execute-cursor/adapter.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
- package/dist/activities/execute-cursor/approval-policy.js +5 -2
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
- package/dist/activities/execute-cursor/approval-state.js +6 -3
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
- package/dist/activities/execute-cursor/cas-observations.js +19 -2
- package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
- package/dist/activities/execute-cursor/message-translator.js +19 -32
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
- package/dist/activities/execute-cursor/prompt-builder.js +76 -95
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
- package/dist/activities/execute-cursor/turn-boundary.js +30 -90
- package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
- package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
- package/dist/activities/execute-cursor/turn-settle.js +37 -49
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
- package/dist/activities/execute-cursor/turn-setup.js +29 -59
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
- package/dist/activities/execute-cursor/turn-stream.js +9 -22
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.js +5 -1
- package/dist/activities/execute-cursor/turn.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
- package/dist/activities/execute-deep-agent/adapter.js +78 -0
- package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
- package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
- package/dist/activities/execute-deep-agent/execution-state.js +4 -12
- package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
- package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
- package/dist/activities/execute-deep-agent/hitl.js +77 -103
- package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
- package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
- package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
- package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
- package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
- package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
- package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
- package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn.js +116 -0
- package/dist/activities/execute-deep-agent/turn.js.map +1 -0
- package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
- package/dist/activities/execute-deep-agent/v3-events.js +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
- package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/harness/approval-decisions.d.ts +61 -0
- package/dist/harness/approval-decisions.js +102 -0
- package/dist/harness/approval-decisions.js.map +1 -0
- package/dist/harness/capabilities.d.ts +16 -5
- package/dist/harness/capabilities.js +9 -0
- package/dist/harness/capabilities.js.map +1 -1
- package/dist/harness/capture.d.ts +144 -0
- package/dist/harness/capture.js +219 -0
- package/dist/harness/capture.js.map +1 -0
- package/dist/harness/persist-chokepoint.d.ts +19 -4
- package/dist/harness/persist-chokepoint.js +17 -4
- package/dist/harness/persist-chokepoint.js.map +1 -1
- package/dist/harness/run-turn.js +115 -29
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/terminal-table.d.ts +40 -11
- package/dist/harness/terminal-table.js +58 -19
- package/dist/harness/terminal-table.js.map +1 -1
- package/dist/harness/turn-context.d.ts +141 -76
- package/dist/harness/turn-context.js +194 -99
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +65 -12
- package/dist/harness/types.js +8 -2
- package/dist/harness/types.js.map +1 -1
- package/dist/harness-adapters.d.ts +12 -8
- package/dist/harness-adapters.js +17 -9
- package/dist/harness-adapters.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +1 -1
- package/dist/middleware/approval-gate.js +1 -1
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +39 -0
- package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
- package/dist/middleware/cost-advisory.js.map +1 -0
- package/dist/middleware/index.d.ts +23 -12
- package/dist/middleware/index.js +26 -18
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -2
- package/dist/runner-manager.js +1 -5
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +1 -5
- package/dist/runner.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +41 -18
- package/dist/shared/attachment-resolver.js +178 -46
- package/dist/shared/attachment-resolver.js.map +1 -1
- package/dist/shared/attachment-zip.d.ts +85 -0
- package/dist/shared/attachment-zip.js +185 -0
- package/dist/shared/attachment-zip.js.map +1 -0
- package/dist/shared/connect-backfill.js +5 -4
- package/dist/shared/connect-backfill.js.map +1 -1
- package/dist/shared/cost-guard.d.ts +3 -3
- package/dist/shared/cost-guard.js +3 -3
- package/dist/shared/execution-status-writer.d.ts +5 -5
- package/dist/shared/execution-status-writer.js +5 -5
- package/dist/shared/extract-structured-output.d.ts +8 -7
- package/dist/shared/extract-structured-output.js +8 -7
- package/dist/shared/extract-structured-output.js.map +1 -1
- package/dist/shared/filereview/cas-progress.d.ts +1 -18
- package/dist/shared/filereview/cas-progress.js +4 -0
- package/dist/shared/filereview/cas-progress.js.map +1 -1
- package/dist/shared/filereview/cas-touched.d.ts +56 -0
- package/dist/shared/filereview/cas-touched.js +63 -0
- package/dist/shared/filereview/cas-touched.js.map +1 -0
- package/dist/shared/filereview/index.d.ts +2 -1
- package/dist/shared/filereview/index.js +2 -1
- package/dist/shared/filereview/index.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +4 -5
- package/dist/shared/mcp-resolver.js +4 -5
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +3 -4
- package/dist/shared/persist-decision.js +3 -4
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +2 -2
- package/dist/shared/plan-mode-permissions.js +2 -2
- package/dist/shared/plan-mode-prompt.d.ts +1 -1
- package/dist/shared/plan-mode-prompt.js +1 -1
- package/dist/shared/prompt-sections.d.ts +163 -0
- package/dist/shared/prompt-sections.js +164 -0
- package/dist/shared/prompt-sections.js.map +1 -0
- package/dist/shared/skill-resolver.d.ts +4 -2
- package/dist/shared/skill-resolver.js +4 -2
- package/dist/shared/skill-resolver.js.map +1 -1
- package/dist/shared/tool-rounds.d.ts +32 -0
- package/dist/shared/tool-rounds.js +43 -0
- package/dist/shared/tool-rounds.js.map +1 -1
- package/dist/shared/tool-row.d.ts +34 -0
- package/dist/shared/tool-row.js +52 -0
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/workspace/session-provision.d.ts +3 -3
- package/dist/shared/workspace/session-provision.js +3 -3
- package/dist/shared/workspace/stigmer-link.d.ts +3 -3
- package/dist/shared/workspace/stigmer-link.js +3 -3
- package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
- package/dist/shared/workspace/writeback-coordinator.js +16 -53
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/package.json +4 -4
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
- package/src/__test-utils__/execution-record-fixture.ts +18 -2
- package/src/__test-utils__/file-review-projection.ts +156 -0
- package/src/__test-utils__/git-workspace-fixture.ts +58 -0
- package/src/__test-utils__/harness-boot-order-child.ts +7 -2
- package/src/__test-utils__/harness-contract/contract.ts +33 -20
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
- package/src/__test-utils__/harness-contract/types.ts +27 -3
- package/src/__test-utils__/hermetic-activity.ts +52 -14
- package/src/__test-utils__/model-registry-fixture.ts +32 -7
- package/src/__test-utils__/module-specifiers.ts +24 -0
- package/src/__test-utils__/turn-input-fixture.ts +2 -2
- package/src/__tests__/harness-boot-order.test.ts +9 -2
- package/src/activities/call-agent.ts +2 -2
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
- package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
- package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
- package/src/activities/execute-cursor/adapter.ts +7 -5
- package/src/activities/execute-cursor/approval-policy.ts +5 -2
- package/src/activities/execute-cursor/approval-state.ts +16 -8
- package/src/activities/execute-cursor/cas-observations.ts +20 -2
- package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
- package/src/activities/execute-cursor/message-translator.ts +29 -41
- package/src/activities/execute-cursor/prompt-builder.ts +99 -157
- package/src/activities/execute-cursor/turn-boundary.ts +34 -140
- package/src/activities/execute-cursor/turn-settle.ts +37 -51
- package/src/activities/execute-cursor/turn-setup.ts +30 -70
- package/src/activities/execute-cursor/turn-stream.ts +8 -31
- package/src/activities/execute-cursor/turn.ts +5 -1
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
- package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
- package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
- package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
- package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
- package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
- package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
- package/src/activities/execute-deep-agent/adapter.ts +94 -0
- package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
- package/src/activities/execute-deep-agent/execution-state.ts +4 -13
- package/src/activities/execute-deep-agent/hitl.ts +100 -123
- package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
- package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
- package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
- package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
- package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
- package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
- package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
- package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
- package/src/activities/execute-deep-agent/turn.ts +131 -0
- package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
- package/src/activities/execute-deep-agent/v3-events.ts +1 -1
- package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
- package/src/harness/__tests__/approval-decisions.test.ts +116 -0
- package/src/harness/__tests__/capture.test.ts +268 -0
- package/src/harness/__tests__/mount-skills.test.ts +169 -0
- package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
- package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
- package/src/harness/__tests__/run-turn.test.ts +39 -23
- package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
- package/src/harness/__tests__/turn-context.test.ts +73 -26
- package/src/harness/approval-decisions.ts +104 -0
- package/src/harness/capabilities.ts +16 -5
- package/src/harness/capture.ts +301 -0
- package/src/harness/persist-chokepoint.ts +24 -4
- package/src/harness/run-turn.ts +120 -29
- package/src/harness/terminal-table.ts +61 -20
- package/src/harness/turn-context.ts +208 -111
- package/src/harness/types.ts +66 -12
- package/src/harness-adapters.ts +17 -9
- package/src/middleware/__tests__/approval-gate.test.ts +1 -1
- package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
- package/src/middleware/approval-gate.ts +2 -2
- package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
- package/src/middleware/index.ts +29 -29
- package/src/middleware/types.ts +3 -2
- package/src/runner-manager.ts +0 -8
- package/src/runner.ts +0 -8
- package/src/shared/__tests__/attachment-naming.test.ts +6 -19
- package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
- package/src/shared/__tests__/attachment-zip.test.ts +236 -0
- package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
- package/src/shared/__tests__/cost-guard.test.ts +3 -3
- package/src/shared/__tests__/prompt-sections.test.ts +167 -0
- package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
- package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
- package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
- package/src/shared/attachment-resolver.ts +218 -55
- package/src/shared/attachment-zip.ts +281 -0
- package/src/shared/connect-backfill.ts +9 -11
- package/src/shared/cost-guard.ts +3 -3
- package/src/shared/execution-status-writer.ts +5 -5
- package/src/shared/extract-structured-output.ts +8 -7
- package/src/shared/filereview/__tests__/capture.test.ts +86 -4
- package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
- package/src/shared/filereview/cas-progress.ts +5 -19
- package/src/shared/filereview/cas-touched.ts +89 -0
- package/src/shared/filereview/index.ts +4 -2
- package/src/shared/mcp-resolver.ts +4 -5
- package/src/shared/persist-decision.ts +3 -4
- package/src/shared/plan-mode-permissions.ts +2 -2
- package/src/shared/plan-mode-prompt.ts +1 -1
- package/src/shared/prompt-sections.ts +256 -0
- package/src/shared/skill-resolver.ts +4 -2
- package/src/shared/tool-rounds.ts +48 -0
- package/src/shared/tool-row.ts +61 -0
- package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
- package/src/shared/workspace/session-provision.ts +3 -3
- package/src/shared/workspace/stigmer-link.ts +3 -3
- package/src/shared/workspace/writeback-coordinator.ts +16 -64
- package/src/tools/index.ts +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
- package/dist/activities/execute-cursor/capture-flow.js +0 -285
- package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
- package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
- package/dist/activities/execute-cursor/command-provenance.js +0 -38
- package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
- package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
- package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
- package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
- package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
- package/dist/activities/execute-deep-agent/environment.js +0 -58
- package/dist/activities/execute-deep-agent/environment.js.map +0 -1
- package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
- package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
- package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
- package/dist/activities/execute-deep-agent/index.d.ts +0 -15
- package/dist/activities/execute-deep-agent/index.js +0 -918
- package/dist/activities/execute-deep-agent/index.js.map +0 -1
- package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
- package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
- package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
- package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
- package/dist/activities/execute-deep-agent/post-stream.js +0 -71
- package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
- package/dist/activities/execute-deep-agent/setup.js +0 -767
- package/dist/activities/execute-deep-agent/setup.js.map +0 -1
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
- package/dist/activities/execute-deep-agent/status-builder.js +0 -365
- package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
- package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
- package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
- package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
- package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
- package/dist/activities/execute-deep-agent/streaming.js +0 -160
- package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
- package/dist/middleware/cost-cap.d.ts +0 -22
- package/dist/middleware/cost-cap.js.map +0 -1
- package/dist/middleware/graceful-stop.d.ts +0 -17
- package/dist/middleware/graceful-stop.js +0 -63
- package/dist/middleware/graceful-stop.js.map +0 -1
- package/dist/shared/skill-writer.d.ts +0 -75
- package/dist/shared/skill-writer.js +0 -207
- package/dist/shared/skill-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
- package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
- package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
- package/src/activities/execute-cursor/capture-flow.ts +0 -379
- package/src/activities/execute-cursor/command-provenance.ts +0 -73
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
- package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
- package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
- package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
- package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
- package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
- package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
- package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
- package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
- package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
- package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
- package/src/activities/execute-deep-agent/environment.ts +0 -76
- package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
- package/src/activities/execute-deep-agent/index.ts +0 -1072
- package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
- package/src/activities/execute-deep-agent/post-stream.ts +0 -109
- package/src/activities/execute-deep-agent/setup.ts +0 -1081
- package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
- package/src/activities/execute-deep-agent/status-builder.ts +0 -481
- package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
- package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
- package/src/activities/execute-deep-agent/streaming.ts +0 -313
- package/src/middleware/__tests__/cost-cap.test.ts +0 -192
- package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
- package/src/middleware/graceful-stop.ts +0 -86
- package/src/shared/__tests__/skill-writer.test.ts +0 -372
- package/src/shared/skill-writer.ts +0 -266
|
@@ -3,22 +3,78 @@
|
|
|
3
3
|
* parent-checkpoint interrupt reader.
|
|
4
4
|
*
|
|
5
5
|
* These two helpers are what every "drive a real deepagents/LangGraph graph
|
|
6
|
-
* through the approval gate" test needs
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* through the approval gate" test needs. They are shared by the graph-level
|
|
7
|
+
* tests (`__tests__/subagent-approval-propagation.test.ts`,
|
|
8
|
+
* `shell-execute-gate.test.ts`, …), the gateway Contract Test Kit adapter
|
|
9
|
+
* (`gateway-substrate.ts`), and the hermetic activity driver
|
|
10
|
+
* (`hermetic-deep-agent.ts`), which runs the REAL `ExecuteDeepAgent` activity
|
|
11
|
+
* with this model as the only LLM. Keeping one copy means a change to how the
|
|
12
|
+
* runner reads pending interrupts (or how a scripted run is driven) updates
|
|
13
|
+
* every consumer at once.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* The one rule the model keeps: it is a PURE FUNCTION of (bound tools,
|
|
16
|
+
* transcript). A script is a sequence of turns per role, and the turn to play
|
|
17
|
+
* is chosen by how many tool rounds the transcript already holds (AI messages
|
|
18
|
+
* carrying `tool_calls`), never by a call counter. That is what lets one
|
|
19
|
+
* script serve both checkpointers the runner ships: under `memory` a HITL
|
|
20
|
+
* reinvocation REPLAYS the graph from the first message (the saver is
|
|
21
|
+
* recreated empty per invocation), so the same transcript indices produce the
|
|
22
|
+
* same proposals; under `sqlite` the graph RESUMES after the interrupt and the
|
|
23
|
+
* next call sees one more completed round. A call-counted script would emit
|
|
24
|
+
* the wrong turn on replay.
|
|
25
|
+
*
|
|
26
|
+
* A script may also be a {@link TurnPlayer}: a function of the whole
|
|
27
|
+
* transcript that returns the one turn to play now. The same rule, with the
|
|
28
|
+
* indexing left to the caller — for a consumer whose plan is not "turn k on
|
|
29
|
+
* round k" but "the first step the conversation does not yet show" (the
|
|
30
|
+
* harness contract kit's native subject, whose one execution spans many
|
|
31
|
+
* kit turns on one sqlite thread, S3 M3).
|
|
32
|
+
*
|
|
33
|
+
* A turn may END the model call instead of finishing the message
|
|
34
|
+
* ({@link TurnEnding}): `fail` throws after its chunks (a provider error
|
|
35
|
+
* mid-stream); `hang` parks on the call's abort signal after its chunks and
|
|
36
|
+
* throws the abort when it fires (a provider stream that stalls and is then
|
|
37
|
+
* cancelled). A hang never parks on a timer: `@langchain/core` hands the
|
|
38
|
+
* graph run's signal to `_streamResponseChunks` as `options.signal`
|
|
39
|
+
* (`_separateRunnableConfigFromCallOptionsCompat`), and LangGraph threads
|
|
40
|
+
* its composite abort signal into every task's config, so the runtime's one
|
|
41
|
+
* stop is what unparks it. The `onPark` hook is how a test learns the engine
|
|
42
|
+
* is silent before it stops the turn from the outside.
|
|
43
|
+
*
|
|
44
|
+
* The model STREAMS. With LangGraph's v3 messages handler attached, LangChain
|
|
45
|
+
* Core streams a model internally when it implements `_streamResponseChunks`
|
|
46
|
+
* and otherwise falls back to a synthesized final-message event sequence
|
|
47
|
+
* (`@langchain/langgraph` `pregel/messages-v2.js` `emitFinalMessage`). The
|
|
48
|
+
* fallback spreads a `tool_call` block's `args` OBJECT into the
|
|
49
|
+
* `tool_call_chunk` fields the runner's normalizer reads as a JSON STRING
|
|
50
|
+
* (`v3-protocol-normalizer.ts` `argsChunk`), which no real provider does.
|
|
51
|
+
* Streaming keeps the double on the production event path: `@langchain/core`
|
|
52
|
+
* `language_models/compat.js` `convertChunksToEvents` turns the chunks below
|
|
53
|
+
* into `message-start`, per-block `content-block-start` / `-delta` /
|
|
54
|
+
* `-finish`, and `message-finish` with usage — the same events `ChatAnthropic`
|
|
55
|
+
* produces. The chunk shapes are chosen from that converter: a string chunk
|
|
56
|
+
* opens block 0 and emits a text delta in one step; an array-content part
|
|
57
|
+
* opens its block with NO delta on first sight, so a reasoning block is sent
|
|
58
|
+
* as an empty opener followed by the text; a `tool_call_chunk` always emits a
|
|
59
|
+
* delta carrying the accumulated JSON args; `usage_metadata` rides the LAST
|
|
60
|
+
* chunk so it lands on `message-finish` (the one place the runner reads it),
|
|
61
|
+
* not on `message-start`.
|
|
15
62
|
*/
|
|
16
63
|
|
|
17
64
|
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
18
|
-
import {
|
|
19
|
-
import type {
|
|
65
|
+
import type { BaseChatModelCallOptions } from "@langchain/core/language_models/chat_models";
|
|
66
|
+
import type { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
|
|
67
|
+
import {
|
|
68
|
+
AIMessageChunk,
|
|
69
|
+
isAIMessage,
|
|
70
|
+
isSystemMessage,
|
|
71
|
+
type BaseMessage,
|
|
72
|
+
type ContentBlock,
|
|
73
|
+
type UsageMetadata,
|
|
74
|
+
} from "@langchain/core/messages";
|
|
75
|
+
import { ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
|
|
20
76
|
|
|
21
|
-
/** A single tool call the scripted model proposes on a
|
|
77
|
+
/** A single tool call the scripted model proposes on a turn. */
|
|
22
78
|
export interface ScriptedToolCall {
|
|
23
79
|
name: string;
|
|
24
80
|
args: Record<string, unknown>;
|
|
@@ -26,8 +82,62 @@ export interface ScriptedToolCall {
|
|
|
26
82
|
}
|
|
27
83
|
|
|
28
84
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
85
|
+
* Token usage a turn reports; fixed round numbers keep `streamingUsage`
|
|
86
|
+
* legible in a golden. The cache buckets ride `input_token_details` the way
|
|
87
|
+
* the Anthropic adapter reports them (`cache_read`, `cache_creation`);
|
|
88
|
+
* `inputTokens` is the total the provider states, cache included.
|
|
89
|
+
*/
|
|
90
|
+
export interface ScriptedUsage {
|
|
91
|
+
readonly inputTokens: number;
|
|
92
|
+
readonly outputTokens: number;
|
|
93
|
+
readonly cacheReadTokens?: number;
|
|
94
|
+
readonly cacheWriteTokens?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* How a turn ends the model call instead of finishing its message.
|
|
99
|
+
* - `fail`: throw `error` after the turn's chunks — a provider error
|
|
100
|
+
* mid-stream; the graph propagates it and the adapter classifies it.
|
|
101
|
+
* - `hang`: after the turn's chunks, park on the call's abort signal and
|
|
102
|
+
* throw the abort when it fires — a stalled provider stream, cancelled by
|
|
103
|
+
* the run's one stop. Refused (thrown, diagnosing) when the call carries
|
|
104
|
+
* no signal: a hang outside an abortable run would park forever.
|
|
105
|
+
*/
|
|
106
|
+
export type TurnEnding = { readonly kind: "fail"; readonly error: Error } | { readonly kind: "hang" };
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* One assistant turn, rendered in the standard content-block shape a
|
|
110
|
+
* streaming provider produces: an optional leading reasoning block, an
|
|
111
|
+
* optional text block, and one `tool_call` per entry of `toolCalls` (which is
|
|
112
|
+
* also what the graph executes). A turn with neither text nor tool calls is
|
|
113
|
+
* an empty assistant message — legal, and what a script that has said all it
|
|
114
|
+
* has to say looks like. A turn with `ends` never finishes its message: its
|
|
115
|
+
* chunks are streamed, then the ending takes the call.
|
|
116
|
+
*/
|
|
117
|
+
export interface ScriptedTurn {
|
|
118
|
+
readonly reasoning?: string;
|
|
119
|
+
readonly text?: string;
|
|
120
|
+
readonly toolCalls?: readonly ScriptedToolCall[];
|
|
121
|
+
readonly usage?: ScriptedUsage;
|
|
122
|
+
readonly ends?: TurnEnding;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A role's script: `turns[k]` is played when the transcript already holds `k`
|
|
127
|
+
* completed tool rounds. Running past the end throws (a script that runs out
|
|
128
|
+
* is a test bug) unless `repeatLast` is set, in which case the final turn
|
|
129
|
+
* plays again — the shape of a model that keeps calling a tool until the
|
|
130
|
+
* graph's recursion limit stops it.
|
|
131
|
+
*/
|
|
132
|
+
export interface RoleScript {
|
|
133
|
+
readonly turns: readonly ScriptedTurn[];
|
|
134
|
+
readonly repeatLast?: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The two-turn sugar most graph-level tests use: propose `toolCalls` on the
|
|
139
|
+
* first round, then say `done` on every round after. Exactly
|
|
140
|
+
* `{ turns: [{ toolCalls }, { text: done }], repeatLast: true }`.
|
|
31
141
|
*/
|
|
32
142
|
export interface ScriptStep {
|
|
33
143
|
toolCalls: ScriptedToolCall[];
|
|
@@ -35,18 +145,65 @@ export interface ScriptStep {
|
|
|
35
145
|
}
|
|
36
146
|
|
|
37
147
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
148
|
+
* What a selector can tell one role from another by. `createDeepAgent` gives
|
|
149
|
+
* a declared sub-agent the SAME tool set as its parent (`task` included), so
|
|
150
|
+
* tool names alone cannot separate them; the system prompt can — it carries
|
|
151
|
+
* the role's own instructions.
|
|
42
152
|
*/
|
|
43
|
-
export
|
|
153
|
+
export interface ScriptRoleContext {
|
|
154
|
+
/** The transcript's leading system message, or "" when there is none. */
|
|
155
|
+
readonly systemPrompt: string;
|
|
156
|
+
}
|
|
44
157
|
|
|
45
158
|
/**
|
|
46
|
-
* A
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
159
|
+
* A script as a function of the whole transcript: called on every model turn
|
|
160
|
+
* with the messages the model was asked with, returns the turn to play. The
|
|
161
|
+
* round-indexed `RoleScript` is the common case; this is for a plan whose
|
|
162
|
+
* progress is read off the conversation itself (see the header).
|
|
163
|
+
*/
|
|
164
|
+
export type TurnPlayer = (transcript: readonly BaseMessage[]) => ScriptedTurn;
|
|
165
|
+
|
|
166
|
+
/** The three shapes a selector may answer with. */
|
|
167
|
+
export type Script = ScriptStep | RoleScript | TurnPlayer;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Picks the script for the role being asked. A single-agent test ignores both
|
|
171
|
+
* arguments; a parent/sub-agent test keys the role on a tool unique to one
|
|
172
|
+
* role when there is one (a custom counting tool), or on the role's
|
|
173
|
+
* instructions in `context.systemPrompt` when both roles bind the same tools
|
|
174
|
+
* (the hermetic delegation arm). Called at `_generate` time, never at bind
|
|
175
|
+
* time, so a role that is compiled but never invoked (the default
|
|
176
|
+
* general-purpose sub-agent) needs no script.
|
|
177
|
+
*/
|
|
178
|
+
export type ScriptSelector = (boundToolNames: string[], context: ScriptRoleContext) => Script;
|
|
179
|
+
|
|
180
|
+
/** What the driver learns before a turn is rendered: which role, which round. */
|
|
181
|
+
export interface ScriptedTurnInfo {
|
|
182
|
+
readonly boundToolNames: readonly string[];
|
|
183
|
+
readonly round: number;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface ScriptedModelOptions {
|
|
187
|
+
/**
|
|
188
|
+
* Called once per model turn, before it is rendered. The hermetic driver
|
|
189
|
+
* ticks its clock here and runs a scenario's scheduled effect (a user pause,
|
|
190
|
+
* a worker shutdown) — from a model turn, never from a timer, so the
|
|
191
|
+
* interruption lands at the same instant every run.
|
|
192
|
+
*/
|
|
193
|
+
readonly onTurn?: (info: ScriptedTurnInfo) => void | Promise<void>;
|
|
194
|
+
/**
|
|
195
|
+
* Called the moment a `hang` turn parks on its abort signal — the engine
|
|
196
|
+
* is silent from here until the signal fires. A test that must stop the
|
|
197
|
+
* turn from the outside (the contract kit's `whenHanging`) listens here,
|
|
198
|
+
* so the stop lands in the hang and never in the adapter's setup.
|
|
199
|
+
*/
|
|
200
|
+
readonly onPark?: () => void;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A deterministic chat model driven by a per-role script. No LLM, no network.
|
|
205
|
+
* The role is keyed on the bound tool names so the same instance drives a
|
|
206
|
+
* parent and its sub-agents.
|
|
50
207
|
*/
|
|
51
208
|
export class ScriptedModel extends BaseChatModel {
|
|
52
209
|
toolNames: string[] = [];
|
|
@@ -59,11 +216,13 @@ export class ScriptedModel extends BaseChatModel {
|
|
|
59
216
|
*/
|
|
60
217
|
readonly boundTools: unknown[];
|
|
61
218
|
private readonly select: ScriptSelector;
|
|
219
|
+
private readonly options: ScriptedModelOptions;
|
|
62
220
|
|
|
63
|
-
constructor(select: ScriptSelector, boundTools: unknown[] = []) {
|
|
221
|
+
constructor(select: ScriptSelector, boundTools: unknown[] = [], options: ScriptedModelOptions = {}) {
|
|
64
222
|
super({});
|
|
65
223
|
this.select = select;
|
|
66
224
|
this.boundTools = boundTools;
|
|
225
|
+
this.options = options;
|
|
67
226
|
}
|
|
68
227
|
|
|
69
228
|
_llmType(): string {
|
|
@@ -71,29 +230,217 @@ export class ScriptedModel extends BaseChatModel {
|
|
|
71
230
|
}
|
|
72
231
|
|
|
73
232
|
bindTools(tools: unknown[]): this {
|
|
74
|
-
const next = new ScriptedModel(this.select, this.boundTools);
|
|
75
|
-
next.toolNames =
|
|
233
|
+
const next = new ScriptedModel(this.select, this.boundTools, this.options);
|
|
234
|
+
next.toolNames = tools.map(boundToolName);
|
|
76
235
|
this.boundTools.length = 0;
|
|
77
236
|
this.boundTools.push(...tools);
|
|
78
237
|
return next as unknown as this;
|
|
79
238
|
}
|
|
80
239
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
240
|
+
/** The turn for this transcript, after the driver hook has run. */
|
|
241
|
+
private async turnFor(messages: BaseMessage[]): Promise<ScriptedTurn> {
|
|
242
|
+
const round = completedToolRounds(messages);
|
|
243
|
+
await this.options.onTurn?.({ boundToolNames: this.toolNames, round });
|
|
244
|
+
const context: ScriptRoleContext = { systemPrompt: systemPromptOf(messages) };
|
|
245
|
+
return resolveTurn(this.select(this.toolNames, context), { round, transcript: messages, toolNames: this.toolNames });
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The non-streaming path (`invoke` outside a graph — the runtime's tier-2
|
|
250
|
+
* structured-output extractor is the one caller): the SAME chunks the
|
|
251
|
+
* streaming path yields, merged, which is the `AIMessageChunk` a streaming
|
|
252
|
+
* provider's `invoke` returns. `@langchain/core`'s base `withStructuredOutput`
|
|
253
|
+
* pipeline reads exactly that shape (`AIMessageChunk.isInstance`, then
|
|
254
|
+
* `tool_calls`); a plain `AIMessage` here would fail it with "Input is not
|
|
255
|
+
* an AIMessageChunk" where the real provider succeeds. An ending turn ends
|
|
256
|
+
* this call the same way it ends the stream.
|
|
257
|
+
*/
|
|
258
|
+
async _generate(messages: BaseMessage[], options: this["ParsedCallOptions"]): Promise<ChatResult> {
|
|
259
|
+
const turn = await this.turnFor(messages);
|
|
260
|
+
if (turn.ends) await this.takeEnding(turn.ends, options.signal);
|
|
261
|
+
const message = renderTurnChunks(turn).reduce((merged, chunk) => merged.concat(chunk));
|
|
262
|
+
return { generations: [{ message, text: turn.text ?? "" }] };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async *_streamResponseChunks(
|
|
266
|
+
messages: BaseMessage[],
|
|
267
|
+
options: this["ParsedCallOptions"] & BaseChatModelCallOptions,
|
|
268
|
+
_runManager?: CallbackManagerForLLMRun,
|
|
269
|
+
): AsyncGenerator<ChatGenerationChunk> {
|
|
270
|
+
const turn = await this.turnFor(messages);
|
|
271
|
+
for (const chunk of renderTurnChunks(turn)) {
|
|
272
|
+
yield new ChatGenerationChunk({ message: chunk, text: typeof chunk.content === "string" ? chunk.content : "" });
|
|
273
|
+
}
|
|
274
|
+
if (turn.ends) await this.takeEnding(turn.ends, options.signal);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Never returns: throws the ending's error, or parks on the signal and throws its abort. */
|
|
278
|
+
private async takeEnding(ending: TurnEnding, signal: AbortSignal | undefined): Promise<never> {
|
|
279
|
+
switch (ending.kind) {
|
|
280
|
+
case "fail":
|
|
281
|
+
throw ending.error;
|
|
282
|
+
case "hang": {
|
|
283
|
+
if (!signal) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
"ScriptedModel: a `hang` turn parks on the call's abort signal and this call carried none; " +
|
|
286
|
+
"a hang is only meaningful inside a run that can be aborted",
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
this.options.onPark?.();
|
|
290
|
+
if (!signal.aborted) {
|
|
291
|
+
await new Promise<void>((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
292
|
+
}
|
|
293
|
+
throw abortErrorOf(signal);
|
|
294
|
+
}
|
|
295
|
+
default: {
|
|
296
|
+
const exhaustive: never = ending;
|
|
297
|
+
throw new Error(`ScriptedModel: unknown turn ending ${String(exhaustive)}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
84
302
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
303
|
+
/** What a provider SDK throws when its in-flight request is aborted: the signal's own reason, or an `AbortError` naming it. */
|
|
304
|
+
function abortErrorOf(signal: AbortSignal): Error {
|
|
305
|
+
if (signal.reason instanceof Error) return signal.reason;
|
|
306
|
+
const err = new Error(`ScriptedModel: the hang was aborted (${String(signal.reason)})`);
|
|
307
|
+
err.name = "AbortError";
|
|
308
|
+
return err;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
// Script resolution
|
|
313
|
+
// ---------------------------------------------------------------------------
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* The name a bound tool answers to: a LangChain tool's `name`, or an
|
|
317
|
+
* OpenAI-style function definition's `function.name` (how langchain binds the
|
|
318
|
+
* structured-output schema tool of `toolStrategy`). A real provider client
|
|
319
|
+
* accepts both shapes; so does this double.
|
|
320
|
+
*/
|
|
321
|
+
function boundToolName(tool: unknown): string {
|
|
322
|
+
const t = tool as { name?: unknown; function?: { name?: unknown } } | null | undefined;
|
|
323
|
+
if (typeof t?.name === "string") return t.name;
|
|
324
|
+
if (typeof t?.function?.name === "string") return t.function.name;
|
|
325
|
+
return "";
|
|
326
|
+
}
|
|
91
327
|
|
|
92
|
-
|
|
93
|
-
|
|
328
|
+
function systemPromptOf(messages: readonly BaseMessage[]): string {
|
|
329
|
+
const system = messages.find((m) => isSystemMessage(m));
|
|
330
|
+
if (!system) return "";
|
|
331
|
+
return typeof system.content === "string" ? system.content : system.text;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function normalizeScript(script: ScriptStep | RoleScript): RoleScript {
|
|
335
|
+
if ("done" in script) {
|
|
336
|
+
return { turns: [{ toolCalls: script.toolCalls }, { text: script.done }], repeatLast: true };
|
|
337
|
+
}
|
|
338
|
+
return script;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** Tool rounds the transcript already holds: AI messages that proposed at least one tool call. */
|
|
342
|
+
export function completedToolRounds(messages: readonly BaseMessage[]): number {
|
|
343
|
+
let rounds = 0;
|
|
344
|
+
for (const m of messages) {
|
|
345
|
+
if (isAIMessage(m) && (m.tool_calls?.length ?? 0) > 0) rounds += 1;
|
|
94
346
|
}
|
|
347
|
+
return rounds;
|
|
95
348
|
}
|
|
96
349
|
|
|
350
|
+
/** What one model call knows when it picks its turn. */
|
|
351
|
+
interface TurnRequest {
|
|
352
|
+
readonly round: number;
|
|
353
|
+
readonly transcript: readonly BaseMessage[];
|
|
354
|
+
readonly toolNames: readonly string[];
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function resolveTurn(script: Script, request: TurnRequest): ScriptedTurn {
|
|
358
|
+
if (typeof script === "function") return script(request.transcript);
|
|
359
|
+
const role = normalizeScript(script);
|
|
360
|
+
const { round, toolNames } = request;
|
|
361
|
+
if (round < role.turns.length) return role.turns[round];
|
|
362
|
+
if (role.repeatLast && role.turns.length > 0) return role.turns[role.turns.length - 1];
|
|
363
|
+
throw new Error(
|
|
364
|
+
`ScriptedModel: the script for role [${toolNames.join(", ")}] has ${role.turns.length} turn(s) ` +
|
|
365
|
+
`but the transcript already holds ${round} completed tool round(s); ` +
|
|
366
|
+
"add a turn or set repeatLast.",
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Rendering: the chunk sequence (stream), merged into one message for invoke
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
|
|
374
|
+
function usageMetadataOf(usage: ScriptedUsage | undefined): UsageMetadata | undefined {
|
|
375
|
+
if (!usage) return undefined;
|
|
376
|
+
const hasCacheBuckets = usage.cacheReadTokens !== undefined || usage.cacheWriteTokens !== undefined;
|
|
377
|
+
return {
|
|
378
|
+
input_tokens: usage.inputTokens,
|
|
379
|
+
output_tokens: usage.outputTokens,
|
|
380
|
+
total_tokens: usage.inputTokens + usage.outputTokens,
|
|
381
|
+
...(hasCacheBuckets
|
|
382
|
+
? { input_token_details: { cache_read: usage.cacheReadTokens ?? 0, cache_creation: usage.cacheWriteTokens ?? 0 } }
|
|
383
|
+
: {}),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function reasoningBlock(reasoning: string, index?: number): ContentBlock.Reasoning {
|
|
388
|
+
return { type: "reasoning", reasoning, ...(index !== undefined ? { index } : {}) };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function textBlock(text: string, index?: number): ContentBlock.Text {
|
|
392
|
+
return { type: "text", text, ...(index !== undefined ? { index } : {}) };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* The chunk sequence `convertChunksToEvents` turns into the production event
|
|
397
|
+
* stream (see the header). An ending turn gets NO closing chunk: its message
|
|
398
|
+
* never finishes — the ending takes the call after these chunks.
|
|
399
|
+
*/
|
|
400
|
+
function renderTurnChunks(turn: ScriptedTurn): AIMessageChunk[] {
|
|
401
|
+
const chunks: AIMessageChunk[] = [];
|
|
402
|
+
let nextIndex = 0;
|
|
403
|
+
|
|
404
|
+
if (turn.reasoning) {
|
|
405
|
+
const index = nextIndex++;
|
|
406
|
+
chunks.push(new AIMessageChunk({ content: [reasoningBlock("", index)] }));
|
|
407
|
+
chunks.push(new AIMessageChunk({ content: [reasoningBlock(turn.reasoning, index)] }));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (turn.text) {
|
|
411
|
+
if (turn.reasoning) {
|
|
412
|
+
const index = nextIndex++;
|
|
413
|
+
chunks.push(new AIMessageChunk({ content: [textBlock("", index)] }));
|
|
414
|
+
chunks.push(new AIMessageChunk({ content: [textBlock(turn.text, index)] }));
|
|
415
|
+
} else {
|
|
416
|
+
nextIndex++;
|
|
417
|
+
chunks.push(new AIMessageChunk({ content: turn.text }));
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
for (const tc of turn.toolCalls ?? []) {
|
|
422
|
+
const index = nextIndex++;
|
|
423
|
+
chunks.push(
|
|
424
|
+
new AIMessageChunk({
|
|
425
|
+
content: "",
|
|
426
|
+
tool_call_chunks: [{ type: "tool_call_chunk", id: tc.id, name: tc.name, args: JSON.stringify(tc.args), index }],
|
|
427
|
+
}),
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (turn.ends) return chunks;
|
|
432
|
+
|
|
433
|
+
const usage = usageMetadataOf(turn.usage);
|
|
434
|
+
// The closing chunk: carries usage onto message-finish, and guarantees at
|
|
435
|
+
// least one chunk so an empty turn is still a message.
|
|
436
|
+
chunks.push(new AIMessageChunk({ content: "", ...(usage ? { usage_metadata: usage } : {}) }));
|
|
437
|
+
return chunks;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
// Pending interrupts
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
|
|
97
444
|
/** A pending approval interrupt surfaced at the parent checkpoint. */
|
|
98
445
|
export interface PendingInterrupt {
|
|
99
446
|
taskId: string;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins that the native adapter's lifecycle module loads no engine: nothing
|
|
3
|
+
* on `adapter.ts`'s STATIC graph — the module and every relative module it
|
|
4
|
+
* loads at import time, transitively — names `deepagents`, `@langchain/*`
|
|
5
|
+
* or `@temporalio/*`.
|
|
6
|
+
*
|
|
7
|
+
* Why it matters: the composition roots import the harness table
|
|
8
|
+
* (`src/harness-adapters.ts`) BEFORE they boot it, and that table must stay
|
|
9
|
+
* connect- and SDK-free (the Cursor adapter's boot patches `node:http2`
|
|
10
|
+
* before anything dials the control plane; `harness-adapters.ts` states the
|
|
11
|
+
* rule). An adapter that imported its SDK at the top of its module would
|
|
12
|
+
* defeat it: this adapter's row is the table's second (S3 M2b, 2026-09-13).
|
|
13
|
+
* This fence is THE proof that the engine is not on the static graph — it
|
|
14
|
+
* walks every relative module transitively and records every package the
|
|
15
|
+
* graph names; the boot ORDER (native's `boot` runs after the Cursor patch)
|
|
16
|
+
* is proven in a real process by `src/__tests__/harness-boot-order.test.ts`,
|
|
17
|
+
* which boots both rows.
|
|
18
|
+
*
|
|
19
|
+
* Read off the syntax tree (`__test-utils__/module-specifiers.ts`): a
|
|
20
|
+
* `import type` is erased and a dynamic `import()` runs only inside `boot`,
|
|
21
|
+
* so neither is on the static graph; a package name in a header comment
|
|
22
|
+
* cannot trip it.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { describe, it, expect } from "vitest";
|
|
26
|
+
import { existsSync } from "node:fs";
|
|
27
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
|
|
30
|
+
import { readSource, staticRuntimeSpecifiers } from "../../../__test-utils__/module-specifiers.js";
|
|
31
|
+
|
|
32
|
+
const SRC_ROOT = fileURLToPath(new URL("../../../", import.meta.url));
|
|
33
|
+
const ADAPTER = join(SRC_ROOT, "activities", "execute-deep-agent", "adapter.ts");
|
|
34
|
+
const FORBIDDEN = ["deepagents", "@langchain/", "@temporalio/"] as const;
|
|
35
|
+
|
|
36
|
+
/** Every file on the static graph rooted at `entry`, and every package the graph names. */
|
|
37
|
+
function walkStaticGraph(entry: string): { files: string[]; packages: string[] } {
|
|
38
|
+
const files: string[] = [];
|
|
39
|
+
const packages: string[] = [];
|
|
40
|
+
const seen = new Set<string>();
|
|
41
|
+
const visit = (file: string): void => {
|
|
42
|
+
if (seen.has(file)) return;
|
|
43
|
+
seen.add(file);
|
|
44
|
+
files.push(file);
|
|
45
|
+
for (const specifier of staticRuntimeSpecifiers(file, readSource(file))) {
|
|
46
|
+
if (!specifier.startsWith(".")) {
|
|
47
|
+
packages.push(specifier);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// `.js` specifiers name `.ts` sources (NodeNext); a directory specifier is not used here.
|
|
51
|
+
const target = resolve(dirname(file), specifier.replace(/\.js$/, ".ts"));
|
|
52
|
+
if (existsSync(target)) visit(target);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
visit(entry);
|
|
56
|
+
return { files, packages };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe("the native adapter's static graph is SDK-free", () => {
|
|
60
|
+
const graph = walkStaticGraph(ADAPTER);
|
|
61
|
+
|
|
62
|
+
it("walked the lifecycle module and stayed out of the engine slice", () => {
|
|
63
|
+
const walked = graph.files.map((f) => relative(SRC_ROOT, f));
|
|
64
|
+
expect(walked).toContain("activities/execute-deep-agent/adapter.ts");
|
|
65
|
+
expect(walked).toContain("activities/execute-deep-agent/deep-agent-capabilities.ts");
|
|
66
|
+
// The engine slice is reached only through the dynamic import inside `boot`.
|
|
67
|
+
expect(walked).not.toContain("activities/execute-deep-agent/turn.ts");
|
|
68
|
+
expect(walked).not.toContain("activities/execute-deep-agent/turn-setup.ts");
|
|
69
|
+
expect(walked).not.toContain("activities/execute-deep-agent/deepagents-profiles.ts");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("names no engine or Temporal package anywhere on the graph", () => {
|
|
73
|
+
const offences = graph.packages.filter((p) => FORBIDDEN.some((root) => p === root.replace(/\/$/, "") || p.startsWith(root)));
|
|
74
|
+
expect(offences, `adapter.ts's static graph must stay SDK-free; found: ${offences.join(", ")}`).toEqual([]);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins that the native adapter is an engine slice and nothing more: no
|
|
3
|
+
* production module under `activities/execute-deep-agent/` 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. The Cursor adapter's fence
|
|
14
|
+
* (`execute-cursor/__tests__/adapter-is-temporal-free.test.ts`) is the
|
|
15
|
+
* precedent; this is its native twin.
|
|
16
|
+
*
|
|
17
|
+
* Until S3 M2b (2026-09-13) one module was tolerated here: `index.ts`, the
|
|
18
|
+
* orchestrator the adapter replaced, which imported `@temporalio/activity`
|
|
19
|
+
* while it still served production. It is deleted; the list is empty and
|
|
20
|
+
* stays empty.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { describe, it, expect } from "vitest";
|
|
24
|
+
import { join, relative } from "node:path";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
|
|
27
|
+
import { packageImports, readSource, typeScriptFilesUnder } from "../../../__test-utils__/module-specifiers.js";
|
|
28
|
+
|
|
29
|
+
const SRC_ROOT = fileURLToPath(new URL("../../../", import.meta.url));
|
|
30
|
+
const ADAPTER_ROOT = join(SRC_ROOT, "activities", "execute-deep-agent");
|
|
31
|
+
|
|
32
|
+
describe("the native adapter never imports @temporalio", () => {
|
|
33
|
+
const files = typeScriptFilesUnder(ADAPTER_ROOT, new Set(["__tests__", "__test-utils__"]));
|
|
34
|
+
const offences = files.flatMap((file) =>
|
|
35
|
+
packageImports(file, readSource(file), "@temporalio").map((specifier) => ` ${relative(SRC_ROOT, file)} imports "${specifier}"`),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
it("inspected the adapter's own files (the walk is rooted where it claims)", () => {
|
|
39
|
+
expect(files.map((f) => relative(ADAPTER_ROOT, f))).toEqual(
|
|
40
|
+
expect.arrayContaining(["adapter.ts", "turn.ts", "turn-setup.ts", "turn-stream.ts", "turn-settle.ts", "deep-agent-capabilities.ts"]),
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("finds no @temporalio import in any production module", () => {
|
|
45
|
+
expect(offences, `the native adapter must not import @temporalio/*:\n${offences.join("\n")}`).toEqual([]);
|
|
46
|
+
});
|
|
47
|
+
});
|