@stigmer/runner 3.15.3-dev.20260914121148 → 3.16.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/README.md +2 -1
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/approval-contract/types.d.ts +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +61 -7
- package/dist/__test-utils__/hermetic-activity.js +100 -9
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +22 -3
- package/dist/__test-utils__/model-registry-fixture.js +22 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +2 -2
- package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +61 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +1 -1
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +47 -12
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +41 -10
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +15 -6
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +17 -4
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +4 -4
- package/dist/activities/execute-cursor/adapter.js +4 -4
- package/dist/activities/execute-cursor/approval-policy.d.ts +10 -10
- package/dist/activities/execute-cursor/approval-policy.js +12 -23
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +35 -1
- package/dist/activities/execute-cursor/approval-state.js +65 -0
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/{message-translator.d.ts → boundary-rows.d.ts} +45 -341
- package/dist/activities/execute-cursor/boundary-rows.js +1018 -0
- package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.js +1 -1
- package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +33 -14
- package/dist/activities/execute-cursor/cursor-event-recorder.js +43 -21
- package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-cursor/prompt-builder.js +4 -4
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/service-tier.js +1 -2
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
- package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
- package/dist/activities/execute-cursor/tool-result.js +130 -0
- package/dist/activities/execute-cursor/tool-result.js.map +1 -0
- package/dist/activities/execute-cursor/translator.d.ts +178 -0
- package/dist/activities/execute-cursor/translator.js +485 -0
- package/dist/activities/execute-cursor/translator.js.map +1 -0
- package/dist/activities/execute-cursor/turn-boundary.d.ts +15 -5
- package/dist/activities/execute-cursor/turn-boundary.js +10 -14
- 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 +47 -34
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +2 -2
- package/dist/activities/execute-cursor/turn-setup.js +5 -5
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +23 -14
- package/dist/activities/execute-cursor/turn-stream.js +41 -28
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.d.ts +4 -4
- package/dist/activities/execute-cursor/turn.js +5 -5
- package/dist/activities/execute-cursor/usage-pricing.d.ts +2 -2
- package/dist/activities/execute-cursor/usage-pricing.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +16 -11
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -10
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +12 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +18 -4
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +10 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +24 -11
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +1 -1
- package/dist/activities/execute-deep-agent/adapter.js +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +19 -19
- package/dist/activities/execute-deep-agent/approval-file-change.js +16 -15
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +2 -2
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +2 -2
- package/dist/activities/execute-deep-agent/hitl.d.ts +2 -2
- package/dist/activities/execute-deep-agent/hitl.js +2 -2
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +13 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js +3 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-deep-agent/prompt-builder.js +6 -7
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +16 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +20 -33
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +3 -3
- package/dist/activities/execute-deep-agent/subagent-transformer.js +1 -1
- package/dist/activities/execute-deep-agent/translator.d.ts +134 -0
- package/dist/activities/execute-deep-agent/translator.js +418 -0
- package/dist/activities/execute-deep-agent/translator.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +13 -7
- package/dist/activities/execute-deep-agent/turn-settle.js +34 -45
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +8 -8
- package/dist/activities/execute-deep-agent/turn-setup.js +7 -7
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +13 -10
- package/dist/activities/execute-deep-agent/turn-stream.js +44 -41
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn.d.ts +3 -3
- package/dist/activities/execute-deep-agent/turn.js +3 -3
- package/dist/activities/generate-session-subject.d.ts +25 -4
- package/dist/activities/generate-session-subject.js +17 -7
- package/dist/activities/generate-session-subject.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +17 -6
- package/dist/client/stigmer-client.js +47 -14
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/config.d.ts +6 -3
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/harness/approval-decisions.d.ts +1 -1
- package/dist/harness/approval-decisions.js +1 -1
- package/dist/harness/capabilities.d.ts +21 -11
- package/dist/harness/capabilities.js +2 -2
- package/dist/harness/capture.d.ts +4 -4
- package/dist/harness/capture.js +4 -4
- package/dist/harness/persist-chokepoint.d.ts +3 -3
- package/dist/harness/persist-chokepoint.js +3 -3
- package/dist/harness/registry.d.ts +2 -2
- package/dist/harness/registry.js +2 -2
- package/dist/harness/run-turn.d.ts +6 -4
- package/dist/harness/run-turn.js +31 -9
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/stop-controller.d.ts +1 -1
- package/dist/harness/stop-controller.js +1 -1
- package/dist/harness/terminal-table.d.ts +7 -7
- package/dist/harness/terminal-table.js +7 -7
- package/dist/harness/transcript/builder.d.ts +182 -0
- package/dist/harness/transcript/builder.js +693 -0
- package/dist/harness/transcript/builder.js.map +1 -0
- package/dist/harness/transcript/events.d.ts +218 -0
- package/dist/harness/transcript/events.js +50 -0
- package/dist/harness/transcript/events.js.map +1 -0
- package/dist/harness/transcript/state.d.ts +110 -0
- package/dist/harness/transcript/state.js +148 -0
- package/dist/harness/transcript/state.js.map +1 -0
- package/dist/harness/turn-context.d.ts +54 -38
- package/dist/harness/turn-context.js +42 -43
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +63 -22
- package/dist/harness/types.js +12 -11
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage-accumulator.d.ts +2 -2
- package/dist/harness/usage-accumulator.js +2 -2
- package/dist/harness-adapters.d.ts +5 -4
- package/dist/harness-adapters.js +5 -4
- package/dist/harness-adapters.js.map +1 -1
- package/dist/interceptors/run-credential-activity.d.ts +28 -0
- package/dist/interceptors/run-credential-activity.js +56 -0
- package/dist/interceptors/run-credential-activity.js.map +1 -0
- package/dist/middleware/approval-gate.d.ts +6 -0
- package/dist/middleware/approval-gate.js +7 -57
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +3 -3
- package/dist/middleware/cost-advisory.js +3 -3
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/runner-manager.js +10 -4
- package/dist/runner-manager.js.map +1 -1
- package/dist/shared/activity-input.d.ts +9 -0
- package/dist/shared/activity-input.js +17 -0
- package/dist/shared/activity-input.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +53 -0
- package/dist/shared/approval-policy.js +76 -0
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/args-preview.d.ts +45 -22
- package/dist/shared/args-preview.js +51 -41
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +4 -4
- package/dist/shared/attachment-resolver.js +4 -4
- package/dist/shared/attachment-zip.d.ts +2 -2
- package/dist/shared/attachment-zip.js +2 -2
- package/dist/shared/channel-attachment.d.ts +8 -5
- package/dist/shared/channel-attachment.js +10 -6
- package/dist/shared/channel-attachment.js.map +1 -1
- package/dist/shared/cost-guard.d.ts +2 -2
- package/dist/shared/cost-guard.js +2 -2
- package/dist/shared/exact-apply.d.ts +1 -1
- package/dist/shared/exact-apply.js +1 -1
- package/dist/shared/execution-context.d.ts +2 -2
- package/dist/shared/execution-context.js +2 -2
- package/dist/shared/extract-structured-output.d.ts +2 -2
- package/dist/shared/extract-structured-output.js +2 -2
- package/dist/shared/filereview/cas-touched.d.ts +2 -2
- package/dist/shared/filereview/cas-touched.js +2 -2
- package/dist/shared/filereview/progress.d.ts +13 -0
- package/dist/shared/filereview/progress.js +13 -0
- package/dist/shared/filereview/progress.js.map +1 -1
- package/dist/shared/heartbeat.d.ts +1 -1
- package/dist/shared/heartbeat.js +1 -1
- package/dist/shared/llm-backend.d.ts +0 -4
- package/dist/shared/llm-backend.js +0 -4
- package/dist/shared/llm-backend.js.map +1 -1
- package/dist/shared/memory-attachment.d.ts +16 -9
- package/dist/shared/memory-attachment.js +18 -10
- package/dist/shared/memory-attachment.js.map +1 -1
- package/dist/shared/model-error.d.ts +1 -2
- package/dist/shared/model-error.js +1 -2
- package/dist/shared/model-error.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +18 -24
- package/dist/shared/persist-decision.js +19 -11
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/prompt-sections.d.ts +4 -4
- package/dist/shared/prompt-sections.js +4 -4
- package/dist/shared/run-credential-store.d.ts +32 -0
- package/dist/shared/run-credential-store.js +39 -0
- package/dist/shared/run-credential-store.js.map +1 -0
- package/dist/shared/run-credential.d.ts +61 -0
- package/dist/shared/run-credential.js +68 -0
- package/dist/shared/run-credential.js.map +1 -0
- package/dist/shared/skill-resolver.d.ts +3 -3
- package/dist/shared/skill-resolver.js +3 -3
- package/dist/shared/status-offload.d.ts +1 -1
- package/dist/shared/status-offload.js +2 -2
- package/dist/shared/status-offload.js.map +1 -1
- package/dist/shared/streaming-scheduler.d.ts +2 -7
- package/dist/shared/streaming-scheduler.js +6 -14
- package/dist/shared/streaming-scheduler.js.map +1 -1
- package/dist/shared/subagent-rows.d.ts +2 -2
- package/dist/shared/subagent-rows.js +2 -2
- package/dist/shared/synthesized-attachment.d.ts +30 -3
- package/dist/shared/synthesized-attachment.js +26 -0
- package/dist/shared/synthesized-attachment.js.map +1 -1
- package/dist/shared/todos.d.ts +3 -3
- package/dist/shared/todos.js +3 -3
- package/dist/shared/tool-row.d.ts +19 -1
- package/dist/shared/tool-row.js +36 -2
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/worker-shutdown.d.ts +1 -1
- package/dist/shared/worker-shutdown.js +1 -1
- package/dist/shared/workspace/session-provision.d.ts +1 -1
- package/dist/shared/workspace/session-provision.js +1 -1
- package/dist/shared/workspace/sources/empty.d.ts +1 -1
- package/dist/shared/workspace/sources/empty.js +1 -2
- package/dist/shared/workspace/sources/empty.js.map +1 -1
- package/dist/shared/workspace/sources/git.js +4 -4
- package/dist/shared/workspace/sources/git.js.map +1 -1
- package/dist/shared/workspace/sources/local-path.js +6 -6
- package/dist/shared/workspace/sources/local-path.js.map +1 -1
- package/dist/shared/workspace/stigmer-link.d.ts +1 -1
- package/dist/shared/workspace/stigmer-link.js +1 -1
- package/dist/shared/workspace/types.d.ts +2 -5
- package/dist/shared/workspace/types.js +0 -6
- package/dist/shared/workspace/types.js.map +1 -1
- package/dist/shared/workspace/writeback-coordinator.d.ts +17 -4
- package/dist/shared/workspace/writeback-coordinator.js +7 -9
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/dist/worker.js +10 -3
- package/dist/worker.js.map +1 -1
- package/dist/workflow-source.d.ts +10 -0
- package/dist/workflow-source.js +12 -0
- package/dist/workflow-source.js.map +1 -1
- package/dist/workflows/execute-from-execution.d.ts +15 -0
- package/dist/workflows/execute-from-execution.js +11 -0
- package/dist/workflows/execute-from-execution.js.map +1 -1
- package/dist/workflows/index.d.ts +5 -3
- package/dist/workflows/index.js +5 -3
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/interceptors/run-credential.d.ts +34 -0
- package/dist/workflows/interceptors/run-credential.js +71 -0
- package/dist/workflows/interceptors/run-credential.js.map +1 -0
- package/package.json +4 -4
- package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +70 -0
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +35 -1
- package/src/__test-utils__/approval-contract/contract.ts +1 -1
- package/src/__test-utils__/approval-contract/types.ts +1 -1
- package/src/__test-utils__/harness-boot-order-child.ts +1 -1
- package/src/__test-utils__/harness-contract/contract.ts +8 -8
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +52 -16
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +47 -43
- package/src/__test-utils__/hermetic-activity.ts +113 -9
- package/src/__test-utils__/model-registry-fixture.ts +31 -7
- package/src/__test-utils__/module-specifiers.ts +32 -3
- package/src/__tests__/harness-boot-order.test.ts +1 -1
- package/src/__tests__/harness-contract.test.ts +1 -1
- package/src/__tests__/run-credential-e2e.test.ts +233 -0
- package/src/__tests__/run-credential-registration.test.ts +80 -0
- package/src/__tests__/runner-manager.test.ts +1 -1
- package/src/activities/__tests__/generate-session-subject-wire.test.ts +119 -0
- package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +2 -2
- package/src/activities/execute-cursor/__test-utils__/fold.ts +116 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +67 -17
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +19 -5
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/approval-state.test.ts +14 -21
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
- package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +19 -8
- package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +10 -8
- package/src/activities/execute-cursor/__tests__/cursor-transcript-live.test.ts +298 -0
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +4 -2
- package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +1 -1
- 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/mcp-tool-call.status.json +71 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +73 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +109 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +119 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +68 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +67 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +7 -7
- package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +146 -0
- package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +5 -5
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +122 -0
- package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +276 -0
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +8 -8
- package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +196 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +145 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +165 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +138 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +130 -0
- package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +13 -1
- package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +2 -2
- package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +43 -60
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +23 -28
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +5 -5
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +11 -13
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +8 -11
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +8 -22
- package/src/activities/execute-cursor/__tests__/translator.test.ts +594 -0
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +8 -5
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +87 -63
- package/src/activities/execute-cursor/adapter.ts +4 -4
- package/src/activities/execute-cursor/approval-policy.ts +12 -24
- package/src/activities/execute-cursor/approval-state.ts +66 -1
- package/src/activities/execute-cursor/boundary-rows.ts +1132 -0
- package/src/activities/execute-cursor/cursor-capabilities.ts +1 -1
- package/src/activities/execute-cursor/cursor-event-recorder.ts +57 -28
- package/src/activities/execute-cursor/fetch-interceptor.ts +1 -1
- package/src/activities/execute-cursor/http2-interceptor.ts +1 -1
- package/src/activities/execute-cursor/prompt-builder.ts +6 -6
- package/src/activities/execute-cursor/service-tier.ts +1 -2
- package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
- package/src/activities/execute-cursor/tool-result.ts +128 -0
- package/src/activities/execute-cursor/translator.ts +541 -0
- package/src/activities/execute-cursor/turn-boundary.ts +21 -14
- package/src/activities/execute-cursor/turn-settle.ts +46 -34
- package/src/activities/execute-cursor/turn-setup.ts +5 -5
- package/src/activities/execute-cursor/turn-stream.ts +49 -46
- package/src/activities/execute-cursor/turn.ts +5 -5
- package/src/activities/execute-cursor/usage-pricing.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +23 -11
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +1 -1
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +2 -3
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +25 -4
- package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +25 -11
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +6 -17
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +25 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +2 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +4 -14
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +4 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +109 -76
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +3 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +92 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +9 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +7 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +10 -11
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +4 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +9 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +21 -13
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +7 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +28 -12
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +21 -21
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +35 -30
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +3 -4
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +12 -10
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +13 -3
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +26 -18
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/{subagent-tracker.test.ts → translator-subagents.test.ts} +76 -57
- package/src/activities/execute-deep-agent/__tests__/{v3-status-builder.test.ts → translator-through-builder.test.ts} +213 -299
- package/src/activities/execute-deep-agent/__tests__/translator.test.ts +505 -0
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +11 -29
- package/src/activities/execute-deep-agent/adapter.ts +1 -1
- package/src/activities/execute-deep-agent/approval-file-change.ts +20 -22
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +2 -2
- package/src/activities/execute-deep-agent/hitl.ts +2 -2
- package/src/activities/execute-deep-agent/inline-publisher.ts +16 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +6 -7
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +22 -31
- package/src/activities/execute-deep-agent/subagent-transformer.ts +3 -3
- package/src/activities/execute-deep-agent/translator.ts +463 -0
- package/src/activities/execute-deep-agent/turn-settle.ts +35 -43
- package/src/activities/execute-deep-agent/turn-setup.ts +8 -8
- package/src/activities/execute-deep-agent/turn-stream.ts +53 -51
- package/src/activities/execute-deep-agent/turn.ts +3 -3
- package/src/activities/generate-session-subject.ts +29 -4
- package/src/client/__tests__/stigmer-client.test.ts +92 -0
- package/src/client/stigmer-client.ts +48 -14
- package/src/config.ts +6 -3
- package/src/harness/README.md +335 -0
- package/src/harness/__tests__/approval-decisions.test.ts +2 -2
- package/src/harness/__tests__/capture.test.ts +3 -3
- package/src/harness/__tests__/import-direction.test.ts +3 -2
- package/src/harness/__tests__/mount-skills.test.ts +4 -1
- package/src/harness/__tests__/readme-index.test.ts +339 -0
- package/src/harness/__tests__/run-turn.test.ts +131 -6
- package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
- package/src/harness/__tests__/transcript-writers.test.ts +191 -0
- package/src/harness/__tests__/turn-attachments-vision.test.ts +5 -2
- package/src/harness/__tests__/turn-context.test.ts +5 -5
- package/src/harness/approval-decisions.ts +1 -1
- package/src/harness/capabilities.ts +21 -11
- package/src/harness/capture.ts +4 -4
- package/src/harness/persist-chokepoint.ts +3 -3
- package/src/harness/registry.ts +2 -2
- package/src/harness/run-turn.ts +33 -9
- package/src/harness/stop-controller.ts +1 -1
- package/src/harness/terminal-table.ts +7 -7
- package/src/harness/transcript/__tests__/builder.test.ts +975 -0
- package/src/harness/transcript/__tests__/state.test.ts +143 -0
- package/src/harness/transcript/builder.ts +755 -0
- package/src/harness/transcript/events.ts +262 -0
- package/src/harness/transcript/state.ts +167 -0
- package/src/harness/turn-context.ts +61 -46
- package/src/harness/types.ts +64 -22
- package/src/harness/usage-accumulator.ts +2 -2
- package/src/harness-adapters.ts +5 -4
- package/src/interceptors/__tests__/run-credential-activity.test.ts +133 -0
- package/src/interceptors/run-credential-activity.ts +67 -0
- package/src/middleware/__tests__/cost-advisory.test.ts +2 -2
- package/src/middleware/approval-gate.ts +7 -74
- package/src/middleware/cost-advisory.ts +3 -3
- package/src/middleware/index.ts +1 -1
- package/src/runner-manager.ts +14 -4
- package/src/shared/__tests__/approval-policy.test.ts +45 -0
- package/src/shared/__tests__/args-preview.test.ts +40 -20
- package/src/shared/__tests__/attachment-naming.test.ts +1 -1
- package/src/shared/__tests__/attachment-resolver.test.ts +5 -5
- package/src/shared/__tests__/attachment-zip.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +1 -1
- package/src/shared/__tests__/channel-attachment.test.ts +12 -0
- package/src/shared/__tests__/cost-guard.test.ts +1 -1
- package/src/shared/__tests__/exact-apply.test.ts +2 -1
- package/src/shared/__tests__/memory-attachment.test.ts +17 -0
- package/src/shared/__tests__/persist-decision.test.ts +19 -33
- package/src/shared/__tests__/prompt-sections.test.ts +1 -1
- package/src/shared/__tests__/run-credential.test.ts +111 -0
- package/src/shared/__tests__/stamp-flowed-rows.test.ts +1 -1
- package/src/shared/__tests__/status-offload.test.ts +1 -1
- package/src/shared/__tests__/streaming-scheduler.test.ts +8 -9
- package/src/shared/__tests__/todos.test.ts +1 -1
- package/src/shared/__tests__/tool-row.test.ts +1 -1
- package/src/shared/activity-input.ts +21 -0
- package/src/shared/approval-policy.ts +95 -0
- package/src/shared/args-preview.ts +51 -42
- package/src/shared/attachment-resolver.ts +4 -4
- package/src/shared/attachment-zip.ts +2 -2
- package/src/shared/channel-attachment.ts +14 -6
- package/src/shared/cost-guard.ts +2 -2
- package/src/shared/exact-apply.ts +1 -1
- package/src/shared/execution-context.ts +2 -2
- package/src/shared/extract-structured-output.ts +2 -2
- package/src/shared/filereview/__tests__/capture.test.ts +9 -5
- package/src/shared/filereview/__tests__/git-substrate.test.ts +4 -1
- package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +3 -3
- package/src/shared/filereview/cas-touched.ts +2 -2
- package/src/shared/filereview/progress.ts +13 -0
- package/src/shared/heartbeat.ts +1 -1
- package/src/shared/llm-backend.ts +0 -4
- package/src/shared/memory-attachment.ts +22 -10
- package/src/shared/model-error.ts +1 -2
- package/src/shared/persist-decision.ts +19 -28
- package/src/shared/prompt-sections.ts +4 -4
- package/src/shared/run-credential-store.ts +45 -0
- package/src/shared/run-credential.ts +70 -0
- package/src/shared/skill-resolver.ts +3 -3
- package/src/shared/status-offload.ts +2 -2
- package/src/shared/streaming-scheduler.ts +8 -13
- package/src/shared/subagent-rows.ts +2 -2
- package/src/shared/synthesized-attachment.ts +38 -3
- package/src/shared/todos.ts +3 -3
- package/src/shared/tool-row.ts +38 -2
- package/src/shared/worker-shutdown.ts +1 -1
- package/src/shared/workspace/__tests__/git-source.test.ts +3 -3
- package/src/shared/workspace/__tests__/provisioner.test.ts +5 -5
- package/src/shared/workspace/__tests__/session-provision.test.ts +2 -2
- package/src/shared/workspace/__tests__/writeback-coordinator.integration.test.ts +8 -9
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +25 -25
- package/src/shared/workspace/provisioner.ts +1 -1
- package/src/shared/workspace/session-provision.ts +1 -1
- package/src/shared/workspace/sources/empty.ts +2 -2
- package/src/shared/workspace/sources/git.ts +3 -4
- package/src/shared/workspace/sources/local-path.ts +5 -6
- package/src/shared/workspace/stigmer-link.ts +1 -1
- package/src/shared/workspace/types.ts +2 -5
- package/src/shared/workspace/writeback-coordinator.ts +23 -12
- package/src/worker.ts +15 -3
- package/src/workflow-source.ts +15 -0
- package/src/workflows/__tests__/run-credential-interceptor.test.ts +178 -0
- package/src/workflows/execute-from-execution.ts +17 -0
- package/src/workflows/index.ts +5 -3
- package/src/workflows/interceptors/run-credential.ts +101 -0
- package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
- package/dist/activities/execute-cursor/delta-enricher.js +0 -265
- package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
- package/dist/activities/execute-cursor/message-translator.js +0 -2040
- package/dist/activities/execute-cursor/message-translator.js.map +0 -1
- package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
- package/dist/activities/execute-cursor/todo-tracker.js +0 -80
- package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
- package/dist/activities/execute-deep-agent/execution-state.js +0 -68
- package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
- package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
- package/dist/activities/execute-deep-agent/v3-events.js +0 -35
- package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
- package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
- package/dist/shared/execution-status-writer.d.ts +0 -31
- package/dist/shared/execution-status-writer.js +0 -43
- package/dist/shared/execution-status-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
- package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
- package/src/activities/execute-cursor/delta-enricher.ts +0 -307
- package/src/activities/execute-cursor/message-translator.ts +0 -2319
- package/src/activities/execute-cursor/todo-tracker.ts +0 -91
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
- package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
- package/src/activities/execute-deep-agent/execution-state.ts +0 -78
- package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
- package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
- package/src/activities/execute-deep-agent/v3-events.ts +0 -153
- package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
- package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
- package/src/shared/execution-status-writer.ts +0 -56
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The native translator's own arms (`execute-deep-agent/translator.ts`): one
|
|
3
|
+
* raw LangGraph v3 protocol event in, the `TranscriptEvent`s out. Two layers,
|
|
4
|
+
* tested apart: `normalize`, the stateless core that reads the wire's shape
|
|
5
|
+
* (root-scoped, unattributed), and `DeepAgentTranslator`, which lays scope
|
|
6
|
+
* and the gate's answers on top and speaks a sub-agent's lifecycle.
|
|
7
|
+
* Beside them, what `usageOf` reads off the same wire for the loop.
|
|
8
|
+
* The events the wire carries and the transcript does not
|
|
9
|
+
* (`lifecycle`, `provider`, the standalone `usage`) are pinned as producing
|
|
10
|
+
* NOTHING, so a member cannot creep back into the union unnoticed.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
14
|
+
import { DeepAgentTranslator, normalize, usageOf } from "../translator.js";
|
|
15
|
+
import {
|
|
16
|
+
resetSeq,
|
|
17
|
+
makeProtocolEvent,
|
|
18
|
+
makeMessageStart,
|
|
19
|
+
makeMessageFinish,
|
|
20
|
+
makeTextDelta,
|
|
21
|
+
makeReasoningDelta,
|
|
22
|
+
makeToolCallArgDelta,
|
|
23
|
+
makeToolStarted,
|
|
24
|
+
makeToolFinished,
|
|
25
|
+
makeToolError,
|
|
26
|
+
makeToolOutputDelta,
|
|
27
|
+
makeUsageEvent,
|
|
28
|
+
makeProviderEvent,
|
|
29
|
+
makeLifecycleRunning,
|
|
30
|
+
makeLifecycleCompleted,
|
|
31
|
+
makeContentBlockStartText,
|
|
32
|
+
makeContentBlockFinish,
|
|
33
|
+
makeCheckpointEvent,
|
|
34
|
+
makeTasksEvent,
|
|
35
|
+
makeValuesEvent,
|
|
36
|
+
makeUpdatesEvent,
|
|
37
|
+
} from "../__test-utils__/v3-event-fixtures.js";
|
|
38
|
+
|
|
39
|
+
beforeEach(() => resetSeq());
|
|
40
|
+
|
|
41
|
+
describe("V3ProtocolNormalizer", () => {
|
|
42
|
+
|
|
43
|
+
// ── Message channel ──────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
describe("messages channel", () => {
|
|
46
|
+
it("normalizes message-start to the run id alone (the wire's message id is not a transcript fact)", () => {
|
|
47
|
+
const result = normalize(makeMessageStart("run-1", { messageId: "msg_abc" }));
|
|
48
|
+
expect(result).toHaveLength(1);
|
|
49
|
+
expect(result[0]).toEqual({ kind: "message_start", runId: "run-1" });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("normalizes text-delta", () => {
|
|
53
|
+
const result = normalize(makeTextDelta("run-1", "Hello "));
|
|
54
|
+
expect(result).toHaveLength(1);
|
|
55
|
+
expect(result[0]).toMatchObject({
|
|
56
|
+
kind: "text_delta",
|
|
57
|
+
runId: "run-1",
|
|
58
|
+
text: "Hello ",
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("normalizes reasoning-delta", () => {
|
|
63
|
+
const result = normalize(makeReasoningDelta("run-1", "Let me think..."));
|
|
64
|
+
expect(result).toHaveLength(1);
|
|
65
|
+
expect(result[0]).toMatchObject({
|
|
66
|
+
kind: "reasoning_delta",
|
|
67
|
+
runId: "run-1",
|
|
68
|
+
text: "Let me think...",
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("normalizes tool_call_chunk via block-delta", () => {
|
|
73
|
+
const result = normalize(makeToolCallArgDelta("run-1", "toolu_123", '{"path":'));
|
|
74
|
+
expect(result).toHaveLength(1);
|
|
75
|
+
expect(result[0]).toMatchObject({
|
|
76
|
+
kind: "tool_arg_delta",
|
|
77
|
+
callId: "toolu_123",
|
|
78
|
+
argsChunk: '{"path":',
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("normalizes message-finish to the run id alone — its usage and reason are the loop's, not the transcript's", () => {
|
|
83
|
+
const result = normalize(makeMessageFinish("run-1", {
|
|
84
|
+
reason: "end_turn",
|
|
85
|
+
usage: { input_tokens: 100, output_tokens: 20, total_tokens: 120 },
|
|
86
|
+
}));
|
|
87
|
+
expect(result).toHaveLength(1);
|
|
88
|
+
expect(result[0]).toEqual({ kind: "message_finish", runId: "run-1" });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("emits nothing for the standalone usage event", () => {
|
|
92
|
+
expect(normalize(makeUsageEvent("run-1", { input_tokens: 50, output_tokens: 10 }))).toHaveLength(0);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("emits nothing for the provider event", () => {
|
|
96
|
+
expect(normalize(makeProviderEvent("run-1", "anthropic", "claude-sonnet-4-6"))).toHaveLength(0);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("returns empty for content-block-start", () => {
|
|
100
|
+
const result = normalize(makeContentBlockStartText("run-1"));
|
|
101
|
+
expect(result).toHaveLength(0);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("returns empty for content-block-finish", () => {
|
|
105
|
+
const result = normalize(makeContentBlockFinish("run-1"));
|
|
106
|
+
expect(result).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("ignores empty text-delta", () => {
|
|
110
|
+
const result = normalize(makeTextDelta("run-1", ""));
|
|
111
|
+
expect(result).toHaveLength(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("ignores empty reasoning-delta", () => {
|
|
115
|
+
const result = normalize(makeReasoningDelta("run-1", ""));
|
|
116
|
+
expect(result).toHaveLength(0);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ── Tools channel ────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
describe("tools channel", () => {
|
|
123
|
+
it("normalizes tool-started with snake_case fields", () => {
|
|
124
|
+
const result = normalize(makeToolStarted("toolu_abc", "read_file", '{"path":"/src/main.ts"}'));
|
|
125
|
+
expect(result).toHaveLength(1);
|
|
126
|
+
expect(result[0]).toMatchObject({
|
|
127
|
+
kind: "tool_started",
|
|
128
|
+
callId: "toolu_abc",
|
|
129
|
+
name: "read_file",
|
|
130
|
+
input: { path: "/src/main.ts" },
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("normalizes tool-started with camelCase fields", () => {
|
|
135
|
+
const event = makeProtocolEvent("tools", {
|
|
136
|
+
event: "tool-started",
|
|
137
|
+
toolCallId: "toolu_abc",
|
|
138
|
+
toolName: "read_file",
|
|
139
|
+
input: { path: "/src/main.ts" },
|
|
140
|
+
}, { namespace: ["tools:toolu_abc"] });
|
|
141
|
+
const result = normalize(event);
|
|
142
|
+
expect(result).toHaveLength(1);
|
|
143
|
+
expect(result[0]).toMatchObject({
|
|
144
|
+
kind: "tool_started",
|
|
145
|
+
callId: "toolu_abc",
|
|
146
|
+
name: "read_file",
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("normalizes tool-finished to the row's result string", () => {
|
|
151
|
+
const result = normalize(makeToolFinished("toolu_abc", "file content here"));
|
|
152
|
+
expect(result).toHaveLength(1);
|
|
153
|
+
expect(result[0]).toMatchObject({
|
|
154
|
+
kind: "tool_finished",
|
|
155
|
+
callId: "toolu_abc",
|
|
156
|
+
result: "file content here",
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("normalizes tool-error", () => {
|
|
161
|
+
const result = normalize(makeToolError("toolu_abc", "permission denied"));
|
|
162
|
+
expect(result).toHaveLength(1);
|
|
163
|
+
expect(result[0]).toMatchObject({
|
|
164
|
+
kind: "tool_error",
|
|
165
|
+
callId: "toolu_abc",
|
|
166
|
+
message: "permission denied",
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("normalizes tool-output-delta", () => {
|
|
171
|
+
const result = normalize(makeToolOutputDelta("toolu_abc", "partial output"));
|
|
172
|
+
expect(result).toHaveLength(1);
|
|
173
|
+
expect(result[0]).toMatchObject({
|
|
174
|
+
kind: "tool_output_delta",
|
|
175
|
+
callId: "toolu_abc",
|
|
176
|
+
delta: "partial output",
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("parses string JSON input into object", () => {
|
|
181
|
+
const result = normalize(makeToolStarted("toolu_abc", "think", '{"thought":"test"}'));
|
|
182
|
+
expect(result[0]).toMatchObject({
|
|
183
|
+
kind: "tool_started",
|
|
184
|
+
input: { thought: "test" },
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("handles malformed JSON input gracefully", () => {
|
|
189
|
+
const result = normalize(makeToolStarted("toolu_abc", "think", "not json"));
|
|
190
|
+
expect(result[0]).toMatchObject({
|
|
191
|
+
kind: "tool_started",
|
|
192
|
+
input: {},
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// ── The tool result: the engine's envelope, rendered here ──
|
|
198
|
+
|
|
199
|
+
describe("tool-finished output → result string", () => {
|
|
200
|
+
// Image/mixed content blocks (e.g. a computer-use screenshot). The result
|
|
201
|
+
// must be the BLOCKS ARRAY serialized — not the LangChain envelope around
|
|
202
|
+
// it — so the persist-time offload can detect the image and lift it into
|
|
203
|
+
// a renderable ToolCallOutputRef.
|
|
204
|
+
const imageBlock = { type: "image_url", image_url: { url: "data:image/png;base64,AAAA" } };
|
|
205
|
+
const resultOf = (output: unknown): string => {
|
|
206
|
+
const [event] = normalize(makeToolFinished("toolu_x", output));
|
|
207
|
+
if (event?.kind !== "tool_finished") throw new Error("expected one tool_finished");
|
|
208
|
+
return event.result;
|
|
209
|
+
};
|
|
210
|
+
const envelope = (content: unknown) => ({
|
|
211
|
+
lc: 1,
|
|
212
|
+
type: "constructor",
|
|
213
|
+
id: ["langchain_core", "messages", "ToolMessage"],
|
|
214
|
+
kwargs: { status: "success", content },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("passes a plain string output through unchanged", () => {
|
|
218
|
+
expect(resultOf("just text")).toBe("just text");
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("unwraps a ToolMessage envelope to its text content", () => {
|
|
222
|
+
expect(resultOf(envelope("hello"))).toBe("hello");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("serializes the blocks array (not the envelope) when the content is an array", () => {
|
|
226
|
+
const result = resultOf(envelope([{ type: "text", text: "shot" }, imageBlock]));
|
|
227
|
+
expect(JSON.parse(result)).toEqual([{ type: "text", text: "shot" }, imageBlock]);
|
|
228
|
+
expect(result).not.toContain("constructor");
|
|
229
|
+
expect(result).not.toContain("langchain_core");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("serializes the blocks array on a live ToolMessage-shaped object (obj.content)", () => {
|
|
233
|
+
expect(JSON.parse(resultOf({ content: [imageBlock] }))).toEqual([imageBlock]);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("falls back to JSON.stringify for unrecognized shapes", () => {
|
|
237
|
+
expect(resultOf({ foo: "bar" })).toBe(JSON.stringify({ foo: "bar" }));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Since #1097: a state-mutating tool (deepagents' write_todos,
|
|
241
|
+
// task) returns a LangGraph Command with its ToolMessage nested in the
|
|
242
|
+
// update; the row shows that message's content, never the whole Command.
|
|
243
|
+
it("unwraps a LangGraph Command to its ToolMessage's content", () => {
|
|
244
|
+
const command = {
|
|
245
|
+
lg_name: "Command",
|
|
246
|
+
update: {
|
|
247
|
+
todos: [{ content: "Read the fixture", status: "pending" }],
|
|
248
|
+
messages: [envelope("Updated todo list to [...]")],
|
|
249
|
+
},
|
|
250
|
+
goto: [],
|
|
251
|
+
};
|
|
252
|
+
expect(resultOf(command)).toBe("Updated todo list to [...]");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("unwraps a Command whose ToolMessage carries a blocks array to the array (the task tool's shape)", () => {
|
|
256
|
+
const command = { lg_name: "Command", update: { files: {}, messages: [envelope([{ type: "text", text: "forty-two" }])] }, goto: [] };
|
|
257
|
+
expect(JSON.parse(resultOf(command))).toEqual([{ type: "text", text: "forty-two" }]);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it("reads the LAST message of a Command that carries several, and serializes a Command with none as it came", () => {
|
|
261
|
+
const several = { lg_name: "Command", update: { messages: [envelope("first"), envelope("the tool's reply")] } };
|
|
262
|
+
expect(resultOf(several)).toBe("the tool's reply");
|
|
263
|
+
const none = { lg_name: "Command", update: { todos: [] }, goto: [] };
|
|
264
|
+
expect(resultOf(none)).toBe(JSON.stringify(none));
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// ── Usage, read beside the transcript ────────────────────────────
|
|
269
|
+
|
|
270
|
+
describe("usageOf — what the loop reads off the wire", () => {
|
|
271
|
+
it("reads a message-finish's usage, the cache buckets included", () => {
|
|
272
|
+
expect(usageOf(makeMessageFinish("run-1", {
|
|
273
|
+
usage: { input_tokens: 100, output_tokens: 20, total_tokens: 120, input_token_details: { cache_creation: 40, cache_read: 5 } },
|
|
274
|
+
}))).toEqual({
|
|
275
|
+
input_tokens: 100,
|
|
276
|
+
output_tokens: 20,
|
|
277
|
+
total_tokens: 120,
|
|
278
|
+
input_token_details: { cache_creation: 40, cache_read: 5 },
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("is undefined for a message-finish without usage", () => {
|
|
283
|
+
expect(usageOf(makeMessageFinish("run-1"))).toBeUndefined();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("ignores the standalone usage event — v3 emits both for one turn, and reading both would double-count", () => {
|
|
287
|
+
expect(usageOf(makeUsageEvent("run-1", { input_tokens: 50, output_tokens: 10 }))).toBeUndefined();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("reads a sub-agent's finish too — its spend is the execution's", () => {
|
|
291
|
+
expect(usageOf(makeMessageFinish("sub-run", {
|
|
292
|
+
namespace: ["tools:task-1", "model_request:sub-run"],
|
|
293
|
+
usage: { input_tokens: 600, output_tokens: 12 },
|
|
294
|
+
}))).toMatchObject({ input_tokens: 600, output_tokens: 12 });
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("is undefined for every other channel", () => {
|
|
298
|
+
expect(usageOf(makeTextDelta("run-1", "hi"))).toBeUndefined();
|
|
299
|
+
expect(usageOf(makeToolFinished("toolu_abc", "ok"))).toBeUndefined();
|
|
300
|
+
expect(usageOf(makeLifecycleCompleted("root"))).toBeUndefined();
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// ── Lifecycle channel: carried by the wire, not the transcript ───
|
|
305
|
+
|
|
306
|
+
describe("lifecycle channel", () => {
|
|
307
|
+
it("emits nothing for running", () => {
|
|
308
|
+
expect(normalize(makeLifecycleRunning("root"))).toHaveLength(0);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it("emits nothing for completed", () => {
|
|
312
|
+
expect(normalize(makeLifecycleCompleted("model_request", ["model_request:abc"]))).toHaveLength(0);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// ── Ignored channels ─────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
describe("ignored channels", () => {
|
|
319
|
+
it("returns empty for checkpoints", () => {
|
|
320
|
+
expect(normalize(makeCheckpointEvent())).toHaveLength(0);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("returns empty for tasks", () => {
|
|
324
|
+
expect(normalize(makeTasksEvent())).toHaveLength(0);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it("returns empty for values", () => {
|
|
328
|
+
expect(normalize(makeValuesEvent())).toHaveLength(0);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it("returns empty for updates", () => {
|
|
332
|
+
expect(normalize(makeUpdatesEvent())).toHaveLength(0);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// ── Edge cases ───────────────────────────────────────────────────
|
|
337
|
+
|
|
338
|
+
describe("edge cases", () => {
|
|
339
|
+
it("returns empty for unknown method", () => {
|
|
340
|
+
const event = makeProtocolEvent("input", { event: "something" });
|
|
341
|
+
expect(normalize(event)).toHaveLength(0);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it("returns empty for missing data", () => {
|
|
345
|
+
const event = makeProtocolEvent("messages", undefined);
|
|
346
|
+
expect(normalize(event)).toHaveLength(0);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("returns empty for unknown message event type", () => {
|
|
350
|
+
const event = makeProtocolEvent("messages", { event: "brand-new-thing", run_id: "r" });
|
|
351
|
+
expect(normalize(event)).toHaveLength(0);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it("carries no namespace and no scope — the core is root-scoped; scope is the translator's", () => {
|
|
355
|
+
const result = normalize(makeTextDelta("run-1", "hi", { namespace: ["tools:x", "model_request:y"] }));
|
|
356
|
+
expect(result[0]).not.toHaveProperty("namespace");
|
|
357
|
+
expect(result[0]).not.toHaveProperty("subAgentId");
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("carries neither seq nor node — the recorder keeps them on the raw event; no handler reads them", () => {
|
|
361
|
+
const event = makeTextDelta("run-1", "hi");
|
|
362
|
+
const result = normalize(event);
|
|
363
|
+
expect(result[0]).not.toHaveProperty("seq");
|
|
364
|
+
expect(result[0]).not.toHaveProperty("node");
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("handles delta with no type gracefully", () => {
|
|
368
|
+
const event = makeProtocolEvent("messages", {
|
|
369
|
+
event: "content-block-delta",
|
|
370
|
+
index: 0,
|
|
371
|
+
delta: {},
|
|
372
|
+
run_id: "run-1",
|
|
373
|
+
});
|
|
374
|
+
expect(normalize(event)).toHaveLength(0);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it("handles missing tool_call_id in tool-started", () => {
|
|
378
|
+
const event = makeProtocolEvent("tools", {
|
|
379
|
+
event: "tool-started",
|
|
380
|
+
tool_name: "read_file",
|
|
381
|
+
}, { namespace: ["tools:abc"] });
|
|
382
|
+
const result = normalize(event);
|
|
383
|
+
expect(result).toHaveLength(1);
|
|
384
|
+
expect(result[0]).toMatchObject({ kind: "tool_started", callId: "" });
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// ── Scope and the sub-agent lifecycle: the translator over the core ──
|
|
389
|
+
|
|
390
|
+
describe("DeepAgentTranslator — scope by LangGraph namespace, a sub-agent per task call", () => {
|
|
391
|
+
const TASK_NS = ["tools:pregel-1"];
|
|
392
|
+
const CHILD_NS = ["tools:pregel-1", "model_request:inner-1"];
|
|
393
|
+
const CHILD_TOOL_NS = ["tools:pregel-1", "tools:inner-tool"];
|
|
394
|
+
|
|
395
|
+
function translator(): DeepAgentTranslator {
|
|
396
|
+
return new DeepAgentTranslator(null);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
it("a root event carries no subAgentId", () => {
|
|
400
|
+
const [event] = translator().translate(makeTextDelta("run-1", "hi"));
|
|
401
|
+
expect(event).toEqual({ kind: "text_delta", runId: "run-1", text: "hi" });
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it("a task start at depth 1 opens a sub-agent BEFORE its own row, keyed by the call id, named from its args", () => {
|
|
405
|
+
const events = translator().translate(
|
|
406
|
+
makeToolStarted("task-1", "task", { subagent_type: "helper", description: "Look it up." }, { namespace: TASK_NS }),
|
|
407
|
+
);
|
|
408
|
+
expect(events.map((e) => e.kind)).toEqual(["sub_agent_started", "tool_started"]);
|
|
409
|
+
expect(events[0]).toEqual({
|
|
410
|
+
kind: "sub_agent_started",
|
|
411
|
+
subAgentId: "task-1",
|
|
412
|
+
name: "helper",
|
|
413
|
+
subject: "Look it up.",
|
|
414
|
+
input: "Look it up.",
|
|
415
|
+
});
|
|
416
|
+
expect(events[1]).toMatchObject({ kind: "tool_started", callId: "task-1", name: "task" });
|
|
417
|
+
expect(events[1]).not.toHaveProperty("subAgentId");
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it("a task start with no subagent_type is named after the tool", () => {
|
|
421
|
+
const [opened] = translator().translate(makeToolStarted("task-2", "task", {}, { namespace: TASK_NS }));
|
|
422
|
+
expect(opened).toMatchObject({ kind: "sub_agent_started", name: "task", subject: "", input: "" });
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it("events under a registered prefix, two or more segments deep, are the sub-agent's", () => {
|
|
426
|
+
const t = translator();
|
|
427
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
428
|
+
const [text] = t.translate(makeTextDelta("inner-1", "Working.", { namespace: CHILD_NS }));
|
|
429
|
+
expect(text).toEqual({ kind: "text_delta", runId: "inner-1", text: "Working.", subAgentId: "task-1" });
|
|
430
|
+
const [tool] = t.translate(makeToolStarted("inner-tool", "grep", { pattern: "x" }, { namespace: CHILD_TOOL_NS }));
|
|
431
|
+
expect(tool).toMatchObject({ kind: "tool_started", callId: "inner-tool", subAgentId: "task-1", mcpServerSlug: "" });
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it("a task start INSIDE a sub-agent is an ordinary row of that sub-agent — one level of delegation is tracked", () => {
|
|
435
|
+
const t = translator();
|
|
436
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
437
|
+
const events = t.translate(makeToolStarted("nested", "task", { subagent_type: "deeper" }, { namespace: CHILD_TOOL_NS }));
|
|
438
|
+
expect(events.map((e) => e.kind)).toEqual(["tool_started"]);
|
|
439
|
+
expect(events[0]).toMatchObject({ subAgentId: "task-1" });
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it("a nested namespace whose prefix nobody registered folds into the root", () => {
|
|
443
|
+
const [event] = translator().translate(makeTextDelta("r", "hi", { namespace: ["tools:unknown", "model_request:x"] }));
|
|
444
|
+
expect(event).not.toHaveProperty("subAgentId");
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("a one-segment event under a registered prefix is the ROOT's — the task row's own lifecycle", () => {
|
|
448
|
+
const t = translator();
|
|
449
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
450
|
+
const [finished] = t.translate(makeToolOutputDelta("task-1", "…", { namespace: TASK_NS }));
|
|
451
|
+
expect(finished).not.toHaveProperty("subAgentId");
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("the task's finish closes the sub-agent AFTER the row's own finish, with the same result as its output", () => {
|
|
455
|
+
const t = translator();
|
|
456
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
457
|
+
const events = t.translate(makeToolFinished("task-1", "forty-two", { namespace: TASK_NS }));
|
|
458
|
+
expect(events).toEqual([
|
|
459
|
+
{ kind: "tool_finished", callId: "task-1", result: "forty-two" },
|
|
460
|
+
{ kind: "sub_agent_finished", subAgentId: "task-1", output: "forty-two" },
|
|
461
|
+
]);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it("the task's error fails the sub-agent after the row's own error", () => {
|
|
465
|
+
const t = translator();
|
|
466
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
467
|
+
const events = t.translate(makeToolError("task-1", "boom", { namespace: TASK_NS }));
|
|
468
|
+
expect(events).toEqual([
|
|
469
|
+
{ kind: "tool_error", callId: "task-1", message: "boom" },
|
|
470
|
+
{ kind: "sub_agent_failed", subAgentId: "task-1", error: "boom" },
|
|
471
|
+
]);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it("an ordinary tool's finish closes no sub-agent", () => {
|
|
475
|
+
const t = translator();
|
|
476
|
+
const events = t.translate(makeToolFinished("toolu_1", "ok"));
|
|
477
|
+
expect(events.map((e) => e.kind)).toEqual(["tool_finished"]);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
it("a depth-0 task start (no namespace) still opens a sub-agent, under a synthetic prefix its children can name", () => {
|
|
481
|
+
const t = translator();
|
|
482
|
+
const events = t.translate(makeToolStarted("task-0", "task", { subagent_type: "w" }, { namespace: [] }));
|
|
483
|
+
expect(events[0]).toMatchObject({ kind: "sub_agent_started", subAgentId: "task-0" });
|
|
484
|
+
const [child] = t.translate(makeTextDelta("in", "hi", { namespace: ["tools:task-0", "model_request:in"] }));
|
|
485
|
+
expect(child).toMatchObject({ subAgentId: "task-0" });
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it("attributes root calls only: a sub-agent's tool start carries no server and no provenance even under a gate", () => {
|
|
489
|
+
const t = new DeepAgentTranslator({
|
|
490
|
+
policies: new Map(),
|
|
491
|
+
toolServerMap: new Map([["grep", "search-server"]]),
|
|
492
|
+
leasedCategories: new Set(),
|
|
493
|
+
globalBypass: false,
|
|
494
|
+
unattended: false,
|
|
495
|
+
unattendedSkips: new Set(),
|
|
496
|
+
});
|
|
497
|
+
t.translate(makeToolStarted("task-1", "task", { subagent_type: "helper" }, { namespace: TASK_NS }));
|
|
498
|
+
const [root] = t.translate(makeToolStarted("root-grep", "grep", {}));
|
|
499
|
+
expect(root).toMatchObject({ mcpServerSlug: "search-server", provenance: "classifier_default" });
|
|
500
|
+
const [sub] = t.translate(makeToolStarted("sub-grep", "grep", {}, { namespace: CHILD_TOOL_NS }));
|
|
501
|
+
expect(sub).toMatchObject({ subAgentId: "task-1", mcpServerSlug: "" });
|
|
502
|
+
expect(sub).not.toHaveProperty("provenance");
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
});
|
|
@@ -6,21 +6,25 @@
|
|
|
6
6
|
*
|
|
7
7
|
* - how the graph is invoked (the two-arg v3 `streamEvents` shape, the
|
|
8
8
|
* runtime's `langgraphConfig` carried whole, the loop's own abort signal);
|
|
9
|
-
* - what each event becomes (the
|
|
9
|
+
* - what each event becomes (the translator feeds the builder; the sink
|
|
10
10
|
* learns of activity per event, with the tool's name as the detail);
|
|
11
11
|
* - what the sink is told and when (usage priced per `message_finish`;
|
|
12
12
|
* a persist requested on the shared cadence rule, a tool start forcing it);
|
|
13
|
-
* - how the loop ends: `completed` with the run's output, `
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* - how the loop ends: `completed` with the run's output, `interrupted` when
|
|
14
|
+
* the runtime stops it — taken at the NEXT event, the engine's own step
|
|
15
|
+
* boundary, and before the first if the stop came
|
|
16
|
+
* earlier. (`awaiting_approval` from the stream itself has no producer
|
|
17
|
+
* on native since #1097: a held call never emits a
|
|
18
|
+
* `tool_started`, so the builder never leaves a row WAITING during the
|
|
19
|
+
* stream; the gate's hold reaches the transcript at the settle. The arm
|
|
20
|
+
* that pinned that path went with it.)
|
|
17
21
|
* - what it refuses and what it tolerates: an empty stream throws; the
|
|
18
22
|
* engine's own error propagates; a `run.output` that rejects is logged
|
|
19
23
|
* and the turn completes without a final state;
|
|
20
24
|
* - the recorder exists only under `V3_EVENT_RECORD_DIR`.
|
|
21
25
|
*
|
|
22
26
|
* Carried from the legacy v3 loop's suite (`streaming-v3.test.ts`, retired
|
|
23
|
-
* with the loop
|
|
27
|
+
* with the loop in #1096): the arms whose rule the adapter's loop
|
|
24
28
|
* still has, re-stated against the sink. The loop-specific arms it dropped
|
|
25
29
|
* (the in-band heartbeat timer, the 120 s stall, STOP read from the persist,
|
|
26
30
|
* pause as a terminal status) are the turn runtime's now and pinned in
|
|
@@ -39,7 +43,6 @@ import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifa
|
|
|
39
43
|
import { turnInputFixture } from "../../../__test-utils__/turn-input-fixture.js";
|
|
40
44
|
import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
|
|
41
45
|
import type { ModelPricing } from "../../../shared/model-pricing.js";
|
|
42
|
-
import type { MergedToolPolicy } from "../../../shared/approval-policy.js";
|
|
43
46
|
import { CasCaptureObserver } from "../cas-capture-observer.js";
|
|
44
47
|
import type { DeepAgentEngine, DeepAgentGateState, DeepAgentGraphInput, DeepAgentWorkspace } from "../turn-setup.js";
|
|
45
48
|
import { consumeDeepAgentStream, createDeepAgentTranscript, type StreamableRun } from "../turn-stream.js";
|
|
@@ -185,7 +188,7 @@ describe("consumeDeepAgentStream — how the graph is invoked", () => {
|
|
|
185
188
|
});
|
|
186
189
|
|
|
187
190
|
describe("consumeDeepAgentStream — what each event becomes", () => {
|
|
188
|
-
it("feeds every event through the
|
|
191
|
+
it("feeds every event through the translator into the transcript and completes with the run's output", async () => {
|
|
189
192
|
const h = harness();
|
|
190
193
|
const result = await h.run(
|
|
191
194
|
scriptedRun(
|
|
@@ -258,27 +261,6 @@ describe("consumeDeepAgentStream — what each event becomes", () => {
|
|
|
258
261
|
});
|
|
259
262
|
|
|
260
263
|
describe("consumeDeepAgentStream — how the loop ends", () => {
|
|
261
|
-
it("ends awaiting_approval when the builder leaves a gated tool WAITING, without awaiting the run's output", async () => {
|
|
262
|
-
const policy: MergedToolPolicy = {
|
|
263
|
-
toolName: "dangerous_tool",
|
|
264
|
-
mcpServerSlug: "my-server",
|
|
265
|
-
requiresApproval: true,
|
|
266
|
-
approvalMessage: "Approve?",
|
|
267
|
-
source: "classifier_default",
|
|
268
|
-
};
|
|
269
|
-
const h = harness({
|
|
270
|
-
gate: openGate({ policies: new Map([["my-server/dangerous_tool", policy]]), toolServerMap: new Map([["dangerous_tool", "my-server"]]) }),
|
|
271
|
-
});
|
|
272
|
-
const neverResolves = new Promise<unknown>(() => undefined);
|
|
273
|
-
const result = await h.run(
|
|
274
|
-
scriptedRun([...textTurn("run-1", "Gated."), makeToolStarted("toolu_g", "dangerous_tool", { target: "prod" })], { output: () => neverResolves }),
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
expect(result.reason).toBe("awaiting_approval");
|
|
278
|
-
expect(result.runOutput).toBeUndefined();
|
|
279
|
-
expect(h.sink.status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
264
|
it("a stop before the first event settles interrupted without invoking the graph", async () => {
|
|
283
265
|
const h = harness();
|
|
284
266
|
h.sink.abort("stopped before start");
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* (the thread id is the runtime's, `deterministic`), or import
|
|
31
31
|
* `@temporalio/*` (`__tests__/adapter-is-temporal-free.test.ts`).
|
|
32
32
|
*
|
|
33
|
-
* Extracted from `index.ts` `createDeepAgentActivities`
|
|
33
|
+
* Extracted from `index.ts` `createDeepAgentActivities` in #1096 on the
|
|
34
34
|
* Cursor adapter's layout (`execute-cursor/adapter.ts`).
|
|
35
35
|
*/
|
|
36
36
|
|
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pre-execution args capture for the HITL approval gate (native harness).
|
|
3
3
|
*
|
|
4
|
-
* When the graph pauses for approval — before the tool runs — this
|
|
5
|
-
*
|
|
6
|
-
* the native-specific seam: correlating a gated `tool_call_id` to
|
|
7
|
-
* from graph state (the authoritative single source of truth at
|
|
8
|
-
* since the streamed input cache is empty and the interrupt
|
|
9
|
-
* few fields). The approval card renders the proposed
|
|
10
|
-
* these args; there is no separate captured
|
|
11
|
-
* Slice 4 — the args are the single
|
|
12
|
-
* exact-apply reads the same args on
|
|
4
|
+
* When the graph pauses for approval — before the tool runs — this recovers
|
|
5
|
+
* the proposed call's arguments so the gate can show the proposed change. It
|
|
6
|
+
* owns only the native-specific seam: correlating a gated `tool_call_id` to
|
|
7
|
+
* its arguments from graph state (the authoritative single source of truth at
|
|
8
|
+
* the interrupt, since the streamed input cache is empty and the interrupt
|
|
9
|
+
* value carries only a few fields). The approval card renders the proposed
|
|
10
|
+
* write/edit content from these args; there is no separate captured
|
|
11
|
+
* `file_changes` (removed in Phase 5 Slice 4 — the args are the single
|
|
12
|
+
* source, and the Cursor deny-gate's exact-apply reads the same args on
|
|
13
|
+
* resume; see shared/exact-apply.ts). The row's `args_preview` is the
|
|
14
|
+
* builder's to write from these args (since #1097; until then this module
|
|
15
|
+
* rendered it too, a second call of the one sanitizer).
|
|
13
16
|
*
|
|
14
17
|
* @since First-Class Diff Review (#186), approval-gate phase
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
/** What the gate capture contributes to a `WAITING_APPROVAL` `ToolCall`. */
|
|
18
21
|
export interface ApprovalCaptureResult {
|
|
19
|
-
/** Sanitized JSON args preview, omitted when there are no args to show. */
|
|
20
|
-
readonly argsPreview?: string;
|
|
21
22
|
/**
|
|
22
23
|
* The secret-redacted args object, for stamping `ToolCall.args` on the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* exposure the preview sanitizer bounds.
|
|
24
|
+
* proposed row. Without it the row carried ONLY the preview string, so
|
|
25
|
+
* every args-driven UI read — the row header's filename-first path above
|
|
26
|
+
* all — rendered nothing for a pending gate (issue #754). Redacted (never
|
|
27
|
+
* raw): the row must not widen the exposure the preview sanitizer bounds.
|
|
28
28
|
*/
|
|
29
29
|
readonly args?: Record<string, unknown>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
import { sanitizeArgsPreview } from "./status-builder-shared.js";
|
|
33
32
|
import { redactSensitiveArgs } from "../../shared/args-preview.js";
|
|
34
33
|
|
|
35
34
|
/**
|
|
@@ -72,11 +71,11 @@ export function findAiMessageToolCallArgs(
|
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
/**
|
|
75
|
-
* Capture the gate's args
|
|
76
|
-
* call site thin.
|
|
74
|
+
* Capture the gate's redacted args from a single correlation lookup, keeping
|
|
75
|
+
* the call site thin.
|
|
77
76
|
*
|
|
78
77
|
* Returns an empty result when the tool call cannot be correlated or took no
|
|
79
|
-
* arguments, so the
|
|
78
|
+
* arguments, so the proposed row carries no args for that interrupt.
|
|
80
79
|
*/
|
|
81
80
|
export function captureApprovalArtifacts(opts: {
|
|
82
81
|
readonly toolCallId: string;
|
|
@@ -85,6 +84,5 @@ export function captureApprovalArtifacts(opts: {
|
|
|
85
84
|
const args = findAiMessageToolCallArgs(opts.messages, opts.toolCallId);
|
|
86
85
|
if (!args || Object.keys(args).length === 0) return {};
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
return { argsPreview, args: redactSensitiveArgs(args) };
|
|
87
|
+
return { args: redactSensitiveArgs(args) };
|
|
90
88
|
}
|