@earendil-works/pi-agent-core 0.84.4 → 0.85.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 +4 -0
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +9 -0
- package/dist/agent-loop.js.map +1 -1
- package/dist/harness/agent-harness.d.ts +639 -384
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +5 -251
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +12 -6
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +33 -26
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +30 -8
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +53 -63
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/config.d.ts +9 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +27 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +9 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +13 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/env/nodejs.d.ts +24 -28
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +239 -86
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +20 -38
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +240 -55
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/execution/assistant.d.ts +42 -0
- package/dist/harness/execution/assistant.d.ts.map +1 -0
- package/dist/harness/execution/assistant.js +82 -0
- package/dist/harness/execution/assistant.js.map +1 -0
- package/dist/harness/execution/effect-gate.d.ts +22 -0
- package/dist/harness/execution/effect-gate.d.ts.map +1 -0
- package/dist/harness/execution/effect-gate.js +49 -0
- package/dist/harness/execution/effect-gate.js.map +1 -0
- package/dist/harness/execution/tools.d.ts +67 -0
- package/dist/harness/execution/tools.d.ts.map +1 -0
- package/dist/harness/execution/tools.js +121 -0
- package/dist/harness/execution/tools.js.map +1 -0
- package/dist/harness/hooks.d.ts +38 -0
- package/dist/harness/hooks.d.ts.map +1 -0
- package/dist/harness/hooks.js +406 -0
- package/dist/harness/hooks.js.map +1 -0
- package/dist/harness/messages.d.ts +2 -2
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/prompt-templates.d.ts +3 -2
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +17 -17
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/result.d.ts +93 -0
- package/dist/harness/result.d.ts.map +1 -1
- package/dist/harness/result.js +40 -0
- package/dist/harness/result.js.map +1 -1
- package/dist/harness/runtime/drive/boundary.d.ts +28 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
- package/dist/harness/runtime/drive/boundary.js +170 -0
- package/dist/harness/runtime/drive/boundary.js.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.js +133 -0
- package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
- package/dist/harness/runtime/drive/deferred.d.ts +15 -0
- package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
- package/dist/harness/runtime/drive/deferred.js +179 -0
- package/dist/harness/runtime/drive/deferred.js.map +1 -0
- package/dist/harness/runtime/drive/generation.d.ts +8 -0
- package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
- package/dist/harness/runtime/drive/generation.js +205 -0
- package/dist/harness/runtime/drive/generation.js.map +1 -0
- package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
- package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
- package/dist/harness/runtime/drive/reconcile.js +140 -0
- package/dist/harness/runtime/drive/reconcile.js.map +1 -0
- package/dist/harness/runtime/drive/recovery.d.ts +8 -0
- package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
- package/dist/harness/runtime/drive/recovery.js +85 -0
- package/dist/harness/runtime/drive/recovery.js.map +1 -0
- package/dist/harness/runtime/drive/response.d.ts +23 -0
- package/dist/harness/runtime/drive/response.d.ts.map +1 -0
- package/dist/harness/runtime/drive/response.js +394 -0
- package/dist/harness/runtime/drive/response.js.map +1 -0
- package/dist/harness/runtime/drive/retry.d.ts +4 -0
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
- package/dist/harness/runtime/drive/retry.js +37 -0
- package/dist/harness/runtime/drive/retry.js.map +1 -0
- package/dist/harness/runtime/drive/structural.d.ts +32 -0
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
- package/dist/harness/runtime/drive/structural.js +929 -0
- package/dist/harness/runtime/drive/structural.js.map +1 -0
- package/dist/harness/runtime/drive/terminal.d.ts +7 -0
- package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
- package/dist/harness/runtime/drive/terminal.js +49 -0
- package/dist/harness/runtime/drive/terminal.js.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.js +244 -0
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
- package/dist/harness/runtime/drive/tools.d.ts +6 -0
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tools.js +449 -0
- package/dist/harness/runtime/drive/tools.js.map +1 -0
- package/dist/harness/runtime/drive.d.ts +6 -0
- package/dist/harness/runtime/drive.d.ts.map +1 -0
- package/dist/harness/runtime/drive.js +93 -0
- package/dist/harness/runtime/drive.js.map +1 -0
- package/dist/harness/runtime/harness.d.ts +59 -0
- package/dist/harness/runtime/harness.d.ts.map +1 -0
- package/dist/harness/runtime/harness.js +311 -0
- package/dist/harness/runtime/harness.js.map +1 -0
- package/dist/harness/runtime/index.d.ts +2 -0
- package/dist/harness/runtime/index.d.ts.map +1 -0
- package/dist/harness/runtime/index.js +2 -0
- package/dist/harness/runtime/index.js.map +1 -0
- package/dist/harness/runtime/lane.d.ts +101 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1575 -0
- package/dist/harness/runtime/lane.js.map +1 -0
- package/dist/harness/runtime/progress.d.ts +15 -0
- package/dist/harness/runtime/progress.d.ts.map +1 -0
- package/dist/harness/runtime/progress.js +66 -0
- package/dist/harness/runtime/progress.js.map +1 -0
- package/dist/harness/runtime/reducer.d.ts +5 -0
- package/dist/harness/runtime/reducer.d.ts.map +1 -0
- package/dist/harness/runtime/reducer.js +240 -0
- package/dist/harness/runtime/reducer.js.map +1 -0
- package/dist/harness/runtime/restore.d.ts +24 -0
- package/dist/harness/runtime/restore.d.ts.map +1 -0
- package/dist/harness/runtime/restore.js +117 -0
- package/dist/harness/runtime/restore.js.map +1 -0
- package/dist/harness/runtime/transcript.d.ts +21 -0
- package/dist/harness/runtime/transcript.d.ts.map +1 -0
- package/dist/harness/runtime/transcript.js +72 -0
- package/dist/harness/runtime/transcript.js.map +1 -0
- package/dist/harness/runtime/types.d.ts +105 -0
- package/dist/harness/runtime/types.d.ts.map +1 -0
- package/dist/harness/runtime/types.js +61 -0
- package/dist/harness/runtime/types.js.map +1 -0
- package/dist/harness/session/commit.d.ts +53 -0
- package/dist/harness/session/commit.d.ts.map +1 -0
- package/dist/harness/session/commit.js +57 -0
- package/dist/harness/session/commit.js.map +1 -0
- package/dist/harness/session/context.d.ts +6 -18
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +31 -49
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +13 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +22 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +18 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +127 -0
- package/dist/harness/session/fork.js.map +1 -0
- package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
- package/dist/harness/session/in-memory-storage-state.js +216 -0
- package/dist/harness/session/in-memory-storage-state.js.map +1 -0
- package/dist/harness/session/index.d.ts +9 -5
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +7 -4
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/codec.d.ts +19 -8
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
- package/dist/harness/session/jsonl/codec.js +34 -218
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/index.d.ts +4 -0
- package/dist/harness/session/jsonl/index.d.ts.map +1 -0
- package/dist/harness/session/jsonl/index.js +4 -0
- package/dist/harness/session/jsonl/index.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +18 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +383 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +26 -19
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +266 -156
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +39 -41
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +238 -181
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/jsonl/types.d.ts +23 -22
- package/dist/harness/session/jsonl/types.d.ts.map +1 -1
- package/dist/harness/session/jsonl/types.js +2 -1
- package/dist/harness/session/jsonl/types.js.map +1 -1
- package/dist/harness/session/memory.d.ts +46 -40
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +346 -113
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/mutation-line.d.ts +8 -0
- package/dist/harness/session/mutation-line.d.ts.map +1 -0
- package/dist/harness/session/mutation-line.js +21 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +78 -46
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +343 -209
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/datasets.js +24 -0
- package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
- package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.js +114 -0
- package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts +21 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +590 -0
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
- package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
- package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/storage.js +600 -0
- package/dist/harness/session/testing/conformance/storage.js.map +1 -0
- package/dist/harness/session/testing/gating-storage.d.ts +26 -0
- package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/gating-storage.js +100 -0
- package/dist/harness/session/testing/gating-storage.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +9 -2
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +8 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/instrumented-storage.js +16 -0
- package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
- package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
- package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
- package/dist/harness/session/testing/storage-decorator.js +41 -0
- package/dist/harness/session/testing/storage-decorator.js.map +1 -0
- package/dist/harness/session/testing/types.d.ts +5 -7
- package/dist/harness/session/testing/types.d.ts.map +1 -1
- package/dist/harness/session/testing/types.js.map +1 -1
- package/dist/harness/session/types.d.ts +424 -259
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -8
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/session/values.d.ts +95 -0
- package/dist/harness/session/values.d.ts.map +1 -0
- package/dist/harness/session/values.js +81 -0
- package/dist/harness/session/values.js.map +1 -0
- package/dist/harness/skills.d.ts +3 -2
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +29 -26
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +64 -43
- package/dist/harness/telemetry.d.ts.map +1 -1
- package/dist/harness/telemetry.js +45 -26
- package/dist/harness/telemetry.js.map +1 -1
- package/dist/harness/tools/bash.d.ts +4 -4
- package/dist/harness/tools/bash.d.ts.map +1 -1
- package/dist/harness/tools/bash.js +66 -93
- package/dist/harness/tools/bash.js.map +1 -1
- package/dist/harness/tools/edit.d.ts.map +1 -1
- package/dist/harness/tools/edit.js +10 -10
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
- package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/harness/tools/file-mutation-queue.js +5 -5
- package/dist/harness/tools/file-mutation-queue.js.map +1 -1
- package/dist/harness/tools/path-utils.d.ts +3 -2
- package/dist/harness/tools/path-utils.d.ts.map +1 -1
- package/dist/harness/tools/path-utils.js +5 -5
- package/dist/harness/tools/path-utils.js.map +1 -1
- package/dist/harness/tools/read.d.ts +2 -1
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +4 -6
- package/dist/harness/tools/read.js.map +1 -1
- package/dist/harness/tools/write.d.ts.map +1 -1
- package/dist/harness/tools/write.js +7 -7
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +108 -45
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
- package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/harness/utils/adaptive-publisher.js +79 -0
- package/dist/harness/utils/adaptive-publisher.js.map +1 -0
- package/dist/harness/utils/output-capture.d.ts +31 -0
- package/dist/harness/utils/output-capture.d.ts.map +1 -0
- package/dist/harness/utils/output-capture.js +217 -0
- package/dist/harness/utils/output-capture.js.map +1 -0
- package/dist/harness/utils/shell-output.d.ts +12 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +64 -174
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +1 -0
- package/dist/harness/utils/truncate.d.ts.map +1 -1
- package/dist/harness/utils/truncate.js +1 -1
- package/dist/harness/utils/truncate.js.map +1 -1
- package/dist/harness/utils/usage.d.ts +4 -0
- package/dist/harness/utils/usage.d.ts.map +1 -0
- package/dist/harness/utils/usage.js +33 -0
- package/dist/harness/utils/usage.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +2 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +40 -10
- package/dist/proxy.js.map +1 -1
- package/dist/search/index.d.ts +24 -16
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +25 -4
- package/dist/harness/reducer.d.ts +0 -100
- package/dist/harness/reducer.d.ts.map +0 -1
- package/dist/harness/reducer.js +0 -415
- package/dist/harness/reducer.js.map +0 -1
- package/dist/harness/session/jsonl/errors.d.ts +0 -9
- package/dist/harness/session/jsonl/errors.d.ts.map +0 -1
- package/dist/harness/session/jsonl/errors.js +0 -19
- package/dist/harness/session/jsonl/errors.js.map +0 -1
- package/dist/harness/session/jsonl.d.ts +0 -3
- package/dist/harness/session/jsonl.d.ts.map +0 -1
- package/dist/harness/session/jsonl.js +0 -2
- package/dist/harness/session/jsonl.js.map +0 -1
- package/dist/harness/session/state.d.ts +0 -65
- package/dist/harness/session/state.d.ts.map +0 -1
- package/dist/harness/session/state.js +0 -319
- package/dist/harness/session/state.js.map +0 -1
- package/dist/harness/session/testing/conformance.d.ts +0 -4
- package/dist/harness/session/testing/conformance.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance.js +0 -762
- package/dist/harness/session/testing/conformance.js.map +0 -1
- package/dist/search/scanning.d.ts +0 -29
- package/dist/search/scanning.d.ts.map +0 -1
- package/dist/search/scanning.js +0 -103
- package/dist/search/scanning.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-placement.js","sourceRoot":"","sources":["../../../../src/harness/runtime/drive/tool-placement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, ToolResultMessage } from \"@earendil-works/pi-ai\";\nimport type { AgentToolCall } from \"../../../types.ts\";\nimport type { HarnessEvent } from \"../../agent-harness.ts\";\nimport { insertEntry, insertUsage } from \"../../session/commit.ts\";\nimport { SessionInvariantError } from \"../../session/session.ts\";\nimport {\n\ttype CheckpointOperation,\n\ttype MessageEntry,\n\ttype NewEntry,\n\ttype OperationState,\n\toperationScopeOf,\n\ttype ToolBatch,\n\ttype ToolCall,\n\ttype ToolsOperation,\n\ttype UsageRow,\n\ttype Write,\n} from \"../../session/types.ts\";\nimport {\n\tbranchTip,\n\tdeleteValue,\n\tlaneConfig,\n\toperationToolArgsPrefix,\n\tpendingEntry,\n\tsetValue,\n} from \"../../session/values.ts\";\nimport type { Lane } from \"../lane.ts\";\nimport type { Drive } from \"../types.ts\";\n\nexport type ToolBatchSource = {\n\tassistant: AssistantMessage;\n\tcalls: Map<number, AgentToolCall>;\n};\n\nexport async function readToolBatchSource<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tbatch: ToolBatch,\n): Promise<ToolBatchSource> {\n\treturn lane.command<ToolBatchSource>(async (_state, reader) => {\n\t\tconst entry = (await reader.getEntries([batch.assistantEntryId], drive.context)).get(batch.assistantEntryId);\n\t\tif (entry?.type !== \"message\" || entry.message.role !== \"assistant\") {\n\t\t\tthrow new SessionInvariantError(\"Tool batch assistant entry is invalid\");\n\t\t}\n\t\tconst calls = new Map<number, AgentToolCall>();\n\t\tfor (const call of batch.calls) {\n\t\t\tconst block = entry.message.content[call.sourceIndex];\n\t\t\tif (block?.type !== \"toolCall\") {\n\t\t\t\tthrow new SessionInvariantError(\n\t\t\t\t\t`Tool call source index ${call.sourceIndex} does not name a tool-call block`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tcalls.set(call.sourceIndex, block);\n\t\t}\n\t\treturn { kind: \"return\", result: { assistant: entry.message, calls } };\n\t}, drive.context);\n}\n\ntype PlacementItem = {\n\tcall: Extract<ToolCall, { status: \"outcome_ready\" }>;\n\tmessage: ToolResultMessage<unknown>;\n};\n\ntype PlacementRead = {\n\titems: PlacementItem[];\n\tturnResults?: ToolResultMessage<unknown>[];\n};\n\nfunction isToolResultMessage(value: unknown): value is ToolResultMessage<unknown> {\n\treturn typeof value === \"object\" && value !== null && \"role\" in value && value.role === \"toolResult\";\n}\n\nexport function toolCallFor(sources: ToolBatchSource, call: ToolCall): AgentToolCall {\n\tconst source = sources.calls.get(call.sourceIndex);\n\tif (source === undefined) {\n\t\tthrow new SessionInvariantError(`Tool call source index ${call.sourceIndex} is invalid`);\n\t}\n\treturn source;\n}\n\nexport function withToolBatch(run: ToolsOperation, batch: ToolBatch): ToolsOperation {\n\treturn { ...operationScopeOf(run), at: \"tools\", batch };\n}\n\nasync function readPlacement<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tsources: ToolBatchSource,\n): Promise<PlacementRead | undefined> {\n\treturn lane.command<PlacementRead | undefined>(async (state, reader) => {\n\t\tconst operation = state.operation;\n\t\tif (operation?.state.at !== \"tools\") return { kind: \"return\", result: undefined };\n\t\tconst current = operation.state.batch;\n\t\tlet first = current.calls.findIndex((call) => call.status !== \"completed\");\n\t\tif (first === -1) return { kind: \"return\", result: undefined };\n\t\tconst ready: Array<Extract<ToolCall, { status: \"outcome_ready\" }>> = [];\n\t\twhile (first < current.calls.length) {\n\t\t\tconst call = current.calls[first]!;\n\t\t\tif (call.status !== \"outcome_ready\") break;\n\t\t\tready.push(call);\n\t\t\tfirst += 1;\n\t\t}\n\t\tif (ready.length === 0) return { kind: \"return\", result: undefined };\n\n\t\tconst items: PlacementItem[] = [];\n\t\tfor (const call of ready) {\n\t\t\tconst stored = await reader.getValue(pendingEntry(call.resultEntryId), drive.context);\n\t\t\tif (stored?.value.type !== \"message\" || !isToolResultMessage(stored.value.payload)) {\n\t\t\t\tthrow new SessionInvariantError(`Tool call ${call.resultEntryId} is missing its staged result`);\n\t\t\t}\n\t\t\tconst source = toolCallFor(sources, call);\n\t\t\tif (stored.value.payload.toolCallId !== source.id || stored.value.payload.toolName !== source.name) {\n\t\t\t\tthrow new SessionInvariantError(`Tool call ${call.resultEntryId} has a mismatched staged result`);\n\t\t\t}\n\t\t\titems.push({ call, message: stored.value.payload });\n\t\t}\n\n\t\tlet turnResults: ToolResultMessage<unknown>[] | undefined;\n\t\tif (first === current.calls.length) {\n\t\t\tconst placedIds = current.calls\n\t\t\t\t.filter((call) => call.status === \"completed\")\n\t\t\t\t.map((call) => call.resultEntryId);\n\t\t\tconst placed = await reader.getEntries(placedIds, drive.context);\n\t\t\tconst staged = new Map(items.map((item) => [item.call.resultEntryId, item.message]));\n\t\t\tturnResults = current.calls.map((call) => {\n\t\t\t\tconst message =\n\t\t\t\t\tstaged.get(call.resultEntryId) ??\n\t\t\t\t\t(() => {\n\t\t\t\t\t\tconst entry = placed.get(call.resultEntryId);\n\t\t\t\t\t\treturn entry?.type === \"message\" && isToolResultMessage(entry.message) ? entry.message : undefined;\n\t\t\t\t\t})();\n\t\t\t\tif (message === undefined) {\n\t\t\t\t\tthrow new SessionInvariantError(`Completed tool call ${call.resultEntryId} is missing its result entry`);\n\t\t\t\t}\n\t\t\t\treturn message;\n\t\t\t});\n\t\t}\n\t\treturn {\n\t\t\tkind: \"return\",\n\t\t\tresult: { items, ...(turnResults === undefined ? {} : { turnResults }) },\n\t\t};\n\t}, drive.context);\n}\n\nasync function commitPlacement<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tcapability: ToolsOperation,\n\tread: PlacementRead,\n): Promise<boolean> {\n\tconst usageIds = read.items.map((item) =>\n\t\titem.message.usage === undefined ? undefined : lane.session.idGenerator.next(),\n\t);\n\treturn lane.settleOperation<ToolsOperation, boolean>(\n\t\tcapability,\n\t\tasync (state, run, _meta, reader) => {\n\t\t\tconst current = run.batch;\n\t\t\tconst writes: Write[] = [];\n\t\t\tconst eventEntries: Array<{ entry: NewEntry<MessageEntry>; seqIndex: number }> = [];\n\t\t\tconst eventUsage: Array<{ row: Omit<UsageRow, \"seq\">; seqIndex: number }> = [];\n\t\t\tlet parentId = state.tipId;\n\t\t\tfor (const [index, item] of read.items.entries()) {\n\t\t\t\tconst entry: NewEntry<MessageEntry> = {\n\t\t\t\t\tid: item.call.resultEntryId,\n\t\t\t\t\tparentId,\n\t\t\t\t\ttype: \"message\",\n\t\t\t\t\tmessage: item.message,\n\t\t\t\t\t...(item.call.terminate ? { terminate: true } : {}),\n\t\t\t\t};\n\t\t\t\teventEntries.push({ entry, seqIndex: writes.length });\n\t\t\t\twrites.push(insertEntry(entry), deleteValue(pendingEntry(item.call.resultEntryId)));\n\t\t\t\tconst usageId = usageIds[index];\n\t\t\t\tif (usageId !== undefined && item.message.usage !== undefined) {\n\t\t\t\t\tconst row: Omit<UsageRow, \"seq\"> = {\n\t\t\t\t\t\tid: usageId,\n\t\t\t\t\t\tusage: item.message.usage,\n\t\t\t\t\t\tentryId: item.call.resultEntryId,\n\t\t\t\t\t\tadjustment: false,\n\t\t\t\t\t};\n\t\t\t\t\teventUsage.push({ row, seqIndex: writes.length });\n\t\t\t\t\twrites.push(insertUsage(row));\n\t\t\t\t}\n\t\t\t\tparentId = item.call.resultEntryId;\n\t\t\t}\n\n\t\t\tconst completedCalls = current.calls.map((call) => {\n\t\t\t\tconst item = read.items.find(\n\t\t\t\t\t(candidate) =>\n\t\t\t\t\t\tcandidate.call.sourceIndex === call.sourceIndex &&\n\t\t\t\t\t\tcandidate.call.resultEntryId === call.resultEntryId,\n\t\t\t\t);\n\t\t\t\treturn item === undefined\n\t\t\t\t\t? call\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tstatus: \"completed\" as const,\n\t\t\t\t\t\t\tsourceIndex: call.sourceIndex,\n\t\t\t\t\t\t\tresultEntryId: call.resultEntryId,\n\t\t\t\t\t\t\tterminate: item.call.terminate,\n\t\t\t\t\t\t};\n\t\t\t});\n\t\t\tconst complete = completedCalls.every((call) => call.status === \"completed\");\n\t\t\tlet nextConfiguration = state.configuration;\n\t\t\tconst addedNames: string[] = [];\n\t\t\tfor (const item of read.items) {\n\t\t\t\tfor (const name of item.message.addedToolNames ?? []) {\n\t\t\t\t\tif (!nextConfiguration.activeToolNames.includes(name) && !addedNames.includes(name)) {\n\t\t\t\t\t\taddedNames.push(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (addedNames.length !== 0) {\n\t\t\t\tnextConfiguration = {\n\t\t\t\t\t...nextConfiguration,\n\t\t\t\t\tactiveToolNames: [...nextConfiguration.activeToolNames, ...addedNames],\n\t\t\t\t};\n\t\t\t\twrites.push(setValue(laneConfig(lane.name), nextConfiguration));\n\t\t\t}\n\t\t\twrites.push(setValue(branchTip(lane.name), parentId));\n\n\t\t\tlet nextRun: OperationState;\n\t\t\tif (complete) {\n\t\t\t\tconst allTerminate = completedCalls.every((call) => call.status === \"completed\" && call.terminate);\n\t\t\t\tconst checkpoint: CheckpointOperation = {\n\t\t\t\t\t...operationScopeOf(run),\n\t\t\t\t\tat: \"checkpoint\",\n\t\t\t\t\tcontinuation: allTerminate\n\t\t\t\t\t\t? { kind: \"may_finish\", includeFinalAssistant: false }\n\t\t\t\t\t\t: { kind: \"need_assistant\", overflowRecoveryUsed: false },\n\t\t\t\t\ttriggerEntryId: parentId!,\n\t\t\t\t};\n\t\t\t\tnextRun = checkpoint;\n\t\t\t\tconst args = await reader.scanValues(\n\t\t\t\t\toperationToolArgsPrefix(drive.operationId, capability.batch.turnId),\n\t\t\t\t\tdrive.context,\n\t\t\t\t);\n\t\t\t\twrites.push(...args.map(({ address }) => deleteValue(address)));\n\t\t\t} else {\n\t\t\t\tnextRun = withToolBatch(run, { ...current, calls: completedCalls });\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: \"commit\",\n\t\t\t\twrites,\n\t\t\t\toperationState: nextRun,\n\t\t\t\tlane: { tipId: parentId, configuration: nextConfiguration },\n\t\t\t\tmaterialize: () => complete,\n\t\t\t\tevents: (commit) => {\n\t\t\t\t\tconst events: HarnessEvent[] = [];\n\t\t\t\t\tfor (const { entry, seqIndex } of eventEntries) {\n\t\t\t\t\t\tevents.push({\n\t\t\t\t\t\t\ttype: \"entry_added\",\n\t\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\t\tentry: { ...entry, seq: commit.seqs[seqIndex]!, timestamp: commit.timestamp },\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst usage = eventUsage.find((candidate) => candidate.row.entryId === entry.id);\n\t\t\t\t\t\tif (usage !== undefined) {\n\t\t\t\t\t\t\tevents.push({\n\t\t\t\t\t\t\t\ttype: \"usage\",\n\t\t\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\t\t\trow: { ...usage.row, seq: commit.seqs[usage.seqIndex]! },\n\t\t\t\t\t\t\t\ttotals: commit.stats.usage,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (addedNames.length !== 0) {\n\t\t\t\t\t\tevents.push({\n\t\t\t\t\t\t\ttype: \"config_update\",\n\t\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\t\tproperty: \"activeTools\",\n\t\t\t\t\t\t\tprevious: state.configuration.activeToolNames,\n\t\t\t\t\t\t\tvalue: nextConfiguration.activeToolNames,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn events;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tdrive.context,\n\t);\n}\n\nexport async function materializeReady<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tcapability: ToolsOperation,\n\tsources: ToolBatchSource,\n\trecovery: boolean,\n): Promise<void> {\n\tconst read = await readPlacement(lane, drive, sources);\n\tif (read === undefined) return;\n\tawait lane.emitBatch(\n\t\tread.items.flatMap(({ call, message }) => [\n\t\t\t{\n\t\t\t\ttype: \"message_start\" as const,\n\t\t\t\tlane: lane.name,\n\t\t\t\trunId: drive.operationId,\n\t\t\t\tmessage,\n\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: \"message_end\" as const,\n\t\t\t\tlane: lane.name,\n\t\t\t\trunId: drive.operationId,\n\t\t\t\tmessage,\n\t\t\t\tentryId: call.resultEntryId,\n\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t},\n\t\t]),\n\t\tdrive.context,\n\t);\n\tconst complete = await commitPlacement(lane, drive, capability, read);\n\tif (complete && read.turnResults !== undefined) {\n\t\tawait lane.emitBatch(\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\ttype: \"turn_end\",\n\t\t\t\t\tlane: lane.name,\n\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\tturnId: capability.batch.turnId,\n\t\t\t\t\tmessage: sources.assistant,\n\t\t\t\t\ttoolResults: read.turnResults,\n\t\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t\t},\n\t\t\t],\n\t\t\tdrive.context,\n\t\t);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ToolsOperation } from "../../session/types.ts";
|
|
2
|
+
import type { Lane } from "../lane.ts";
|
|
3
|
+
import type { Drive, ProcedureResult } from "../types.ts";
|
|
4
|
+
/** Execute, recover, stage, and source-order one complete durable tool batch. */
|
|
5
|
+
export declare function runTools<TContext extends object | undefined>(lane: Lane<TContext>, drive: Drive, run: ToolsOperation): Promise<ProcedureResult>;
|
|
6
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../src/harness/runtime/drive/tools.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAkC,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAW7F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAA2B,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAknB9F,iFAAiF;AACjF,wBAAsB,QAAQ,CAAC,QAAQ,SAAS,MAAM,GAAG,SAAS,EACjE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,EACpB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,cAAc,GACjB,OAAO,CAAC,eAAe,CAAC,CAgC1B","sourcesContent":["import type { ToolResultMessage } from \"@earendil-works/pi-ai\";\nimport type { AgentToolCall, AgentToolResult } from \"../../../types.ts\";\nimport { AbortRequested } from \"../../execution/effect-gate.ts\";\nimport {\n\tapplyBeforeToolDecision,\n\ttype ClearedToolCall,\n\tcreateToolResultMessage,\n\ttype ExecutedToolCall,\n\texecuteToolCall,\n\ttype FinalizedToolCall,\n\tfinalizeToolCall,\n\tprepareToolCall,\n\ttoolResultFromMessage,\n} from \"../../execution/tools.ts\";\nimport { SessionInvariantError } from \"../../session/session.ts\";\nimport type { JsonValue, ToolBatch, ToolCall, ToolsOperation } from \"../../session/types.ts\";\nimport {\n\tdeleteValue,\n\toperationToolArgs,\n\toperationToolMemo,\n\toperationToolMemoPrefix,\n\tpendingEntry,\n\tpendingToolOutput,\n\tsetValue,\n} from \"../../session/values.ts\";\nimport type { AgentHarnessTool, AgentHarnessToolInvocation } from \"../../types.ts\";\nimport type { Lane } from \"../lane.ts\";\nimport { openToolProgress } from \"../progress.ts\";\nimport type { ContinueOperationResult, Drive, LaneState, ProcedureResult } from \"../types.ts\";\nimport {\n\tmaterializeReady,\n\treadToolBatchSource,\n\ttype ToolBatchSource,\n\ttoolCallFor,\n\twithToolBatch,\n} from \"./tool-placement.ts\";\n\ntype ToolCallTask = { completion: Promise<void> };\ntype ToolOutcome = { toolCall: AgentToolCall; message: ToolResultMessage<unknown>; terminate: boolean };\ntype PreparedToolInvocation<TContext extends object | undefined> =\n\t| { kind: \"ready\"; cleared: ClearedToolCall<TContext> }\n\t| { kind: \"outcome\"; outcome: ToolOutcome };\n\nconst INTERRUPTION_MARKER =\n\t\"[Tool execution was interrupted. The preceding output is the latest durable progress snapshot; newer live output may be missing, and the external outcome is unknown.]\";\n\nclass ToolInvocationEnded extends Error {\n\tconstructor() {\n\t\tsuper(\"Tool invocation no longer owns its durable effect\");\n\t\tthis.name = \"ToolInvocationEnded\";\n\t}\n}\n\nfunction currentBatch<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n): { run: ToolsOperation; batch: ToolBatch } | undefined {\n\tconst operation = lane.state.operation;\n\tif (operation?.state.at !== \"tools\") return undefined;\n\treturn { run: operation.state, batch: operation.state.batch };\n}\n\nfunction findCall(batch: ToolBatch, sourceIndex: number, resultEntryId: string): ToolCall | undefined {\n\treturn batch.calls.find((call) => call.sourceIndex === sourceIndex && call.resultEntryId === resultEntryId);\n}\n\nfunction replaceCall(batch: ToolBatch, replacement: ToolCall): ToolBatch {\n\treturn {\n\t\t...batch,\n\t\tcalls: batch.calls.map((call) =>\n\t\t\tcall.sourceIndex === replacement.sourceIndex && call.resultEntryId === replacement.resultEntryId\n\t\t\t\t? replacement\n\t\t\t\t: call,\n\t\t),\n\t};\n}\n\nfunction validateMemoName(name: string): void {\n\tif (name.length === 0) throw new TypeError(\"Tool invocation memo name must not be empty\");\n\tif (name.includes(\":\")) throw new TypeError(\"Tool invocation memo name must not contain ':'\");\n}\n\nfunction invocationCapability<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tbatch: ToolBatch,\n\tcall: Extract<ToolCall, { status: \"effect_pending\" }>,\n): { invocation: AgentHarnessToolInvocation; expire(): void } {\n\tlet active = true;\n\tconst ownsEffect = (state: LaneState): boolean => {\n\t\tconst operation = state.operation;\n\t\tif (operation?.state.at !== \"tools\") return false;\n\t\treturn findCall(operation.state.batch, call.sourceIndex, call.resultEntryId)?.status === \"effect_pending\";\n\t};\n\tconst ended = (): ToolInvocationEnded => new ToolInvocationEnded();\n\treturn {\n\t\tinvocation: {\n\t\t\tinvocationId: call.resultEntryId,\n\t\t\toperationId: drive.operationId,\n\t\t\tturnId: batch.turnId,\n\t\t\tgetMemo(name) {\n\t\t\t\tvalidateMemoName(name);\n\t\t\t\tif (!active) return Promise.reject(ended());\n\t\t\t\treturn lane.command<JsonValue | undefined>(async (state, reader) => {\n\t\t\t\t\tif (!ownsEffect(state)) return { kind: \"reject\", error: ended() };\n\t\t\t\t\tconst stored = await reader.getValue(\n\t\t\t\t\t\toperationToolMemo(drive.operationId, call.resultEntryId, name),\n\t\t\t\t\t\tdrive.context,\n\t\t\t\t\t);\n\t\t\t\t\treturn { kind: \"return\", result: stored?.value };\n\t\t\t\t}, drive.context);\n\t\t\t},\n\t\t\tsetMemo(name, value) {\n\t\t\t\tvalidateMemoName(name);\n\t\t\t\tif (!active) return Promise.reject(ended());\n\t\t\t\treturn lane.command<void>((state) => {\n\t\t\t\t\tif (!ownsEffect(state)) return { kind: \"reject\", error: ended() };\n\t\t\t\t\tconst address = operationToolMemo(drive.operationId, call.resultEntryId, name);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: \"commit\",\n\t\t\t\t\t\twrites: [value === undefined ? deleteValue(address) : setValue(address, value)],\n\t\t\t\t\t\tnext: state,\n\t\t\t\t\t\tmaterialize: () => undefined,\n\t\t\t\t\t};\n\t\t\t\t}, drive.context);\n\t\t\t},\n\t\t},\n\t\texpire() {\n\t\t\tactive = false;\n\t\t},\n\t};\n}\n\nfunction syntheticMessage(\n\ttoolCall: AgentToolCall,\n\tcontent: AgentToolResult<unknown>[\"content\"],\n\toptions: { details?: unknown; usage?: AgentToolResult<unknown>[\"usage\"] } = {},\n): ToolResultMessage<unknown> {\n\treturn {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: toolCall.id,\n\t\ttoolName: toolCall.name,\n\t\tcontent,\n\t\t...(options.details === undefined ? {} : { details: options.details }),\n\t\t...(options.usage === undefined ? {} : { usage: options.usage }),\n\t\tisError: true,\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction abortedOutcome(toolCall: AgentToolCall): ToolOutcome {\n\treturn {\n\t\ttoolCall,\n\t\tmessage: syntheticMessage(toolCall, [{ type: \"text\", text: \"Tool execution was cancelled before completion.\" }]),\n\t\tterminate: false,\n\t};\n}\n\nfunction interruptedOutcome(toolCall: AgentToolCall, checkpoint: AgentToolResult<unknown> | undefined): ToolOutcome {\n\treturn {\n\t\ttoolCall,\n\t\tmessage: syntheticMessage(\n\t\t\ttoolCall,\n\t\t\t[...(checkpoint?.content ?? []), { type: \"text\", text: INTERRUPTION_MARKER }],\n\t\t\tcheckpoint === undefined ? {} : { details: checkpoint.details, usage: checkpoint.usage },\n\t\t),\n\t\tterminate: false,\n\t};\n}\n\nfunction truncatedOutcome(toolCall: AgentToolCall): ToolOutcome {\n\treturn {\n\t\ttoolCall,\n\t\tmessage: syntheticMessage(toolCall, [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: `Tool call ${JSON.stringify(toolCall.name)} was not executed because the assistant response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`,\n\t\t\t},\n\t\t]),\n\t\tterminate: false,\n\t};\n}\n\nfunction outcomeFromFinalizedCall(finalized: FinalizedToolCall): ToolOutcome {\n\treturn { toolCall: finalized.toolCall, message: createToolResultMessage(finalized), terminate: finalized.terminate };\n}\n\nasync function publishToolIntent<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n\tplanned: Extract<ToolCall, { status: \"planned\" }>,\n\ttoolCall: AgentToolCall,\n\targs: Record<string, JsonValue>,\n\treplay: \"never\" | \"safe\",\n\trecovery: boolean,\n): Promise<ContinueOperationResult<Extract<ToolCall, { status: \"effect_pending\" }>>> {\n\treturn lane.continueOperation(\n\t\trun,\n\t\t(_state, run) => {\n\t\t\tconst effectPending: Extract<ToolCall, { status: \"effect_pending\" }> = {\n\t\t\t\tstatus: \"effect_pending\",\n\t\t\t\tsourceIndex: planned.sourceIndex,\n\t\t\t\tresultEntryId: planned.resultEntryId,\n\t\t\t\treplay,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tkind: \"commit\",\n\t\t\t\twrites: [setValue(operationToolArgs(drive.operationId, run.batch.turnId, planned.sourceIndex), args)],\n\t\t\t\toperationState: withToolBatch(run, replaceCall(run.batch, effectPending)),\n\t\t\t\tmaterialize: () => effectPending,\n\t\t\t\tevents: () => [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"tool_start\",\n\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\t\tturnId: run.batch.turnId,\n\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t\tdrive.context,\n\t);\n}\n\nasync function publishToolOutcome<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tcapability: ToolsOperation,\n\tcall: Extract<ToolCall, { status: \"planned\" | \"effect_pending\" }>,\n\tfinalized: ToolOutcome,\n\trecovery: boolean,\n): Promise<void> {\n\tawait lane.settleOperation(\n\t\tcapability,\n\t\tasync (_state, run, _meta, reader) => {\n\t\t\tconst { toolCall } = finalized;\n\t\t\tconst memos = await reader.scanValues(\n\t\t\t\toperationToolMemoPrefix(drive.operationId, call.resultEntryId),\n\t\t\t\tdrive.context,\n\t\t\t);\n\t\t\tconst durableTerminate = run.control.status === \"running\" && finalized.terminate;\n\t\t\tconst outcome: Extract<ToolCall, { status: \"outcome_ready\" }> = {\n\t\t\t\tstatus: \"outcome_ready\",\n\t\t\t\tsourceIndex: call.sourceIndex,\n\t\t\t\tresultEntryId: call.resultEntryId,\n\t\t\t\tterminate: durableTerminate,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tkind: \"commit\",\n\t\t\t\twrites: [\n\t\t\t\t\tsetValue(pendingEntry(call.resultEntryId), { type: \"message\", payload: finalized.message }),\n\t\t\t\t\tdeleteValue(pendingToolOutput(drive.operationId, call.resultEntryId)),\n\t\t\t\t\t...memos.map(({ address }) => deleteValue(address)),\n\t\t\t\t],\n\t\t\t\toperationState: withToolBatch(run, replaceCall(run.batch, outcome)),\n\t\t\t\tmaterialize: () => undefined,\n\t\t\t\tevents: () => [\n\t\t\t\t\t...(call.status === \"planned\"\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"tool_start\" as const,\n\t\t\t\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\t\t\t\t\tturnId: run.batch.turnId,\n\t\t\t\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\t\t\t\targs: toolCall.arguments,\n\t\t\t\t\t\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"tool_end\",\n\t\t\t\t\t\tlane: lane.name,\n\t\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\t\tturnId: run.batch.turnId,\n\t\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\t\tresult: toolResultFromMessage(finalized.message, durableTerminate),\n\t\t\t\t\t\tisError: finalized.message.isError,\n\t\t\t\t\t\tterminate: durableTerminate,\n\t\t\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t\tdrive.context,\n\t);\n}\n\nasync function clearReplayCheckpoint<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tbatch: ToolBatch,\n\tcall: Extract<ToolCall, { status: \"effect_pending\" }>,\n\ttoolCall: AgentToolCall,\n): Promise<Record<string, JsonValue>> {\n\treturn lane.command(async (state, reader) => {\n\t\tconst stored = await reader.getValue(\n\t\t\toperationToolArgs(drive.operationId, batch.turnId, call.sourceIndex),\n\t\t\tdrive.context,\n\t\t);\n\t\tif (stored === undefined) {\n\t\t\tthrow new SessionInvariantError(`Tool call ${call.resultEntryId} is missing persisted arguments`);\n\t\t}\n\t\treturn {\n\t\t\tkind: \"commit\",\n\t\t\twrites: [deleteValue(pendingToolOutput(drive.operationId, call.resultEntryId))],\n\t\t\tnext: state,\n\t\t\tmaterialize: () => stored.value,\n\t\t\tevents: () => [\n\t\t\t\t{\n\t\t\t\t\ttype: \"tool_start\",\n\t\t\t\t\tlane: lane.name,\n\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\tturnId: batch.turnId,\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\ttoolName: toolCall.name,\n\t\t\t\t\targs: stored.value,\n\t\t\t\t\trecovery: true,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}, drive.context);\n}\n\nfunction readCheckpoint<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tcall: Extract<ToolCall, { status: \"effect_pending\" }>,\n): Promise<AgentToolResult<unknown> | undefined> {\n\treturn lane.command(async (_state, reader) => {\n\t\tconst stored = await reader.getValue(pendingToolOutput(drive.operationId, call.resultEntryId), drive.context);\n\t\treturn { kind: \"return\", result: stored?.value };\n\t}, drive.context);\n}\n\nasync function resolveToolContext<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n): Promise<TContext> {\n\tconst source = lane.readConfig().toolContext;\n\treturn (typeof source === \"function\" ? await source(drive.context) : source) as TContext;\n}\n\nasync function performToolInvocation<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tbatch: ToolBatch,\n\tcall: Extract<ToolCall, { status: \"effect_pending\" }>,\n\tcleared: ClearedToolCall<TContext>,\n\ttoolContext: TContext,\n\trecovery: boolean,\n): Promise<ToolOutcome> {\n\tconst capability = invocationCapability(lane, drive, batch, call);\n\tconst progress = openToolProgress(lane, drive, batch.turnId, call.sourceIndex, call.resultEntryId);\n\tlet latestUpdateDelivery: Promise<void> = Promise.resolve();\n\tconst publishUpdate = (partial: AgentToolResult<unknown>): void => {\n\t\tlatestUpdateDelivery = lane.emitBatch(\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\ttype: \"tool_update\",\n\t\t\t\t\tlane: lane.name,\n\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\tturnId: batch.turnId,\n\t\t\t\t\ttoolCallId: cleared.toolCall.id,\n\t\t\t\t\ttoolName: cleared.toolCall.name,\n\t\t\t\t\tpartialResult: partial,\n\t\t\t\t\t...(recovery ? { recovery: true as const } : {}),\n\t\t\t\t},\n\t\t\t],\n\t\t\tdrive.context,\n\t\t);\n\t\tvoid latestUpdateDelivery.catch(() => {});\n\t};\n\n\tlet execution: Promise<ExecutedToolCall>;\n\ttry {\n\t\texecution = executeToolCall(\n\t\t\tcleared,\n\t\t\tdrive.gate,\n\t\t\t(partial, options) => {\n\t\t\t\tpublishUpdate(partial);\n\t\t\t\tif (options?.checkpoint === true) progress.write(partial);\n\t\t\t},\n\t\t\ttoolContext,\n\t\t\tcapability.invocation,\n\t\t\tdrive.context,\n\t\t);\n\t} catch (error) {\n\t\tcapability.expire();\n\t\tprogress.seal();\n\t\tawait progress.drain();\n\t\tif (!(error instanceof AbortRequested)) throw error;\n\t\tawait error.cancellation;\n\t\treturn recovery ? interruptedOutcome(cleared.toolCall, undefined) : abortedOutcome(cleared.toolCall);\n\t}\n\n\tconst executed = await execution.finally(() => {\n\t\tcapability.expire();\n\t\tprogress.seal();\n\t});\n\tawait latestUpdateDelivery;\n\tawait progress.drain();\n\n\tlet patch: Awaited<ReturnType<typeof lane.hooks.runToolWithGate<\"after_tool\">>>;\n\ttry {\n\t\tpatch = await lane.hooks.runToolWithGate(\n\t\t\t\"after_tool\",\n\t\t\t{\n\t\t\t\tlane: lane.name,\n\t\t\t\trunId: drive.operationId,\n\t\t\t\ttoolCallId: cleared.toolCall.id,\n\t\t\t\ttoolName: cleared.toolCall.name,\n\t\t\t\targs: cleared.args,\n\t\t\t\tcontent: executed.result.content,\n\t\t\t\t...(executed.result.details === undefined ? {} : { details: executed.result.details as JsonValue }),\n\t\t\t\tisError: executed.isError,\n\t\t\t\t...(executed.result.usage === undefined ? {} : { usage: executed.result.usage }),\n\t\t\t},\n\t\t\tdrive.gate,\n\t\t\tdrive.context,\n\t\t);\n\t} catch (error) {\n\t\tif (!(error instanceof AbortRequested)) throw error;\n\t\tpatch = undefined;\n\t}\n\tconst finalized = finalizeToolCall(cleared, executed, patch);\n\treturn { toolCall: finalized.toolCall, message: createToolResultMessage(finalized), terminate: finalized.terminate };\n}\n\nasync function prepareToolInvocation<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\tsources: ToolBatchSource,\n\tcall: Extract<ToolCall, { status: \"planned\" }>,\n\ttools: AgentHarnessTool<TContext>[],\n): Promise<PreparedToolInvocation<TContext>> {\n\tconst toolCall = toolCallFor(sources, call);\n\tif (sources.assistant.stopReason === \"length\") {\n\t\treturn { kind: \"outcome\", outcome: truncatedOutcome(toolCall) };\n\t}\n\tconst prepared = prepareToolCall(toolCall, tools);\n\tif (\"kind\" in prepared) return { kind: \"outcome\", outcome: outcomeFromFinalizedCall(prepared) };\n\n\tlet decision: Awaited<ReturnType<typeof lane.hooks.runToolWithGate<\"before_tool\">>>;\n\ttry {\n\t\tdecision = await lane.hooks.runToolWithGate(\n\t\t\t\"before_tool\",\n\t\t\t{\n\t\t\t\tlane: lane.name,\n\t\t\t\trunId: drive.operationId,\n\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\ttoolName: toolCall.name,\n\t\t\t\targs: prepared.args,\n\t\t\t},\n\t\t\tdrive.gate,\n\t\t\tdrive.context,\n\t\t);\n\t} catch (error) {\n\t\tif (!(error instanceof AbortRequested)) throw error;\n\t\tawait error.cancellation;\n\t\treturn { kind: \"outcome\", outcome: abortedOutcome(toolCall) };\n\t}\n\tconst cleared = applyBeforeToolDecision(prepared, decision);\n\treturn \"kind\" in cleared\n\t\t? { kind: \"outcome\", outcome: outcomeFromFinalizedCall(cleared) }\n\t\t: { kind: \"ready\", cleared };\n}\n\nasync function startToolInvocation<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n\tsources: ToolBatchSource,\n\tcall: Extract<ToolCall, { status: \"planned\" }>,\n\ttools: AgentHarnessTool<TContext>[],\n\ttoolContext: TContext,\n\trecovery: boolean,\n): Promise<ToolCallTask> {\n\tconst prepared = await prepareToolInvocation(lane, drive, sources, call, tools);\n\tif (prepared.kind === \"outcome\") {\n\t\treturn { completion: publishToolOutcome(lane, drive, run, call, prepared.outcome, recovery) };\n\t}\n\tconst effectPending = await publishToolIntent(\n\t\tlane,\n\t\tdrive,\n\t\trun,\n\t\tcall,\n\t\tprepared.cleared.toolCall,\n\t\tprepared.cleared.args,\n\t\tprepared.cleared.tool.replay ?? \"never\",\n\t\trecovery,\n\t);\n\treturn {\n\t\tcompletion:\n\t\t\teffectPending.kind === \"cancel_requested\"\n\t\t\t\t? publishToolOutcome(lane, drive, run, call, abortedOutcome(prepared.cleared.toolCall), recovery)\n\t\t\t\t: performToolInvocation(\n\t\t\t\t\t\tlane,\n\t\t\t\t\t\tdrive,\n\t\t\t\t\t\trun.batch,\n\t\t\t\t\t\teffectPending.value,\n\t\t\t\t\t\tprepared.cleared,\n\t\t\t\t\t\ttoolContext,\n\t\t\t\t\t\trecovery,\n\t\t\t\t\t).then((outcome) => publishToolOutcome(lane, drive, run, effectPending.value, outcome, recovery)),\n\t};\n}\n\nasync function recoverToolInvocation<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n\tsources: ToolBatchSource,\n\tcall: Extract<ToolCall, { status: \"effect_pending\" }>,\n\ttoolsByName: Map<string, AgentHarnessTool<TContext>>,\n\ttoolContext: TContext,\n\tcancelled: boolean,\n): Promise<ToolCallTask> {\n\tconst toolCall = toolCallFor(sources, call);\n\tconst tool = toolsByName.get(toolCall.name);\n\tif (!cancelled && call.replay === \"safe\" && tool?.replay === \"safe\") {\n\t\tconst args = await clearReplayCheckpoint(lane, drive, run.batch, call, toolCall);\n\t\tconst cleared: ClearedToolCall<TContext> = { toolCall, tool, args };\n\t\treturn {\n\t\t\tcompletion: performToolInvocation(lane, drive, run.batch, call, cleared, toolContext, true).then((outcome) =>\n\t\t\t\tpublishToolOutcome(lane, drive, run, call, outcome, true),\n\t\t\t),\n\t\t};\n\t}\n\tconst checkpoint = await readCheckpoint(lane, drive, call);\n\treturn {\n\t\tcompletion: publishToolOutcome(lane, drive, run, call, interruptedOutcome(toolCall, checkpoint), true),\n\t};\n}\n\nasync function runSequential<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n\tsources: ToolBatchSource,\n\texecution:\n\t\t| {\n\t\t\t\ttools: AgentHarnessTool<TContext>[];\n\t\t\t\ttoolsByName: Map<string, AgentHarnessTool<TContext>>;\n\t\t\t\ttoolContext: TContext;\n\t\t }\n\t\t| undefined,\n\trecovery: boolean,\n): Promise<ProcedureResult> {\n\tconst { batch } = run;\n\tfor (let transition = 0; transition <= batch.calls.length * 2 + 1; transition += 1) {\n\t\tawait materializeReady(lane, drive, run, sources, recovery);\n\t\tconst current = currentBatch(lane);\n\t\tif (current === undefined) return { kind: \"continue\" };\n\t\tconst call = current.batch.calls.find((candidate) => candidate.status !== \"completed\");\n\t\tif (call === undefined) throw new SessionInvariantError(\"Tool batch remained open after every call completed\");\n\t\tif (call.status === \"outcome_ready\") throw new SessionInvariantError(\"Ready tool outcome was not materialized\");\n\n\t\tif (current.run.control.status === \"cancel_requested\") {\n\t\t\tconst toolCall = toolCallFor(sources, call);\n\t\t\tif (call.status === \"planned\") {\n\t\t\t\tawait publishToolOutcome(lane, drive, current.run, call, abortedOutcome(toolCall), recovery);\n\t\t\t} else {\n\t\t\t\tconst checkpoint = await readCheckpoint(lane, drive, call);\n\t\t\t\tawait publishToolOutcome(\n\t\t\t\t\tlane,\n\t\t\t\t\tdrive,\n\t\t\t\t\tcurrent.run,\n\t\t\t\t\tcall,\n\t\t\t\t\tinterruptedOutcome(toolCall, checkpoint),\n\t\t\t\t\trecovery,\n\t\t\t\t);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (execution === undefined) throw new SessionInvariantError(\"Running tool batch is missing execution context\");\n\t\tconst started =\n\t\t\tcall.status === \"planned\"\n\t\t\t\t? await startToolInvocation(\n\t\t\t\t\t\tlane,\n\t\t\t\t\t\tdrive,\n\t\t\t\t\t\tcurrent.run,\n\t\t\t\t\t\tsources,\n\t\t\t\t\t\tcall,\n\t\t\t\t\t\texecution.tools,\n\t\t\t\t\t\texecution.toolContext,\n\t\t\t\t\t\trecovery,\n\t\t\t\t\t)\n\t\t\t\t: await recoverToolInvocation(\n\t\t\t\t\t\tlane,\n\t\t\t\t\t\tdrive,\n\t\t\t\t\t\tcurrent.run,\n\t\t\t\t\t\tsources,\n\t\t\t\t\t\tcall,\n\t\t\t\t\t\texecution.toolsByName,\n\t\t\t\t\t\texecution.toolContext,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\t\tawait started.completion;\n\t}\n\tthrow new SessionInvariantError(\"Sequential tool batch exceeded its bounded transition count\");\n}\n\nasync function runParallel<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n\tsources: ToolBatchSource,\n\ttools: AgentHarnessTool<TContext>[],\n\ttoolsByName: Map<string, AgentHarnessTool<TContext>>,\n\ttoolContext: TContext,\n\trecovery: boolean,\n): Promise<ProcedureResult> {\n\tconst { batch } = run;\n\tlet materialization = Promise.resolve();\n\tconst scheduleMaterialization = (): Promise<void> => {\n\t\tconst scheduled = materialization.then(() => materializeReady(lane, drive, run, sources, recovery));\n\t\tmaterialization = scheduled.catch(() => {});\n\t\treturn scheduled;\n\t};\n\tconst jobs: Promise<void>[] = [];\n\tfor (const call of batch.calls) {\n\t\tif (call.status === \"completed\" || call.status === \"outcome_ready\") continue;\n\t\tconst started =\n\t\t\tcall.status === \"planned\"\n\t\t\t\t? await startToolInvocation(lane, drive, run, sources, call, tools, toolContext, recovery)\n\t\t\t\t: await recoverToolInvocation(\n\t\t\t\t\t\tlane,\n\t\t\t\t\t\tdrive,\n\t\t\t\t\t\trun,\n\t\t\t\t\t\tsources,\n\t\t\t\t\t\tcall,\n\t\t\t\t\t\ttoolsByName,\n\t\t\t\t\t\ttoolContext,\n\t\t\t\t\t\tlane.state.operation!.state.control.status === \"cancel_requested\",\n\t\t\t\t\t);\n\t\tconst job = started.completion.then(async () => {\n\t\t\tawait scheduleMaterialization();\n\t\t});\n\t\tvoid job.catch(() => {});\n\t\tjobs.push(job);\n\t}\n\tawait Promise.all(jobs);\n\tawait scheduleMaterialization();\n\treturn { kind: \"continue\" };\n}\n\n/** Execute, recover, stage, and source-order one complete durable tool batch. */\nexport async function runTools<TContext extends object | undefined>(\n\tlane: Lane<TContext>,\n\tdrive: Drive,\n\trun: ToolsOperation,\n): Promise<ProcedureResult> {\n\tconst batch = run.batch;\n\tconst recovery = batch.calls.some((call) => call.status === \"effect_pending\" || call.status === \"outcome_ready\");\n\tif (recovery) {\n\t\tawait lane.emitBatch(\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\ttype: \"turn_start\",\n\t\t\t\t\tlane: lane.name,\n\t\t\t\t\trunId: drive.operationId,\n\t\t\t\t\tturnId: batch.turnId,\n\t\t\t\t\trecovery: true,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdrive.context,\n\t\t);\n\t}\n\tconst sources = await readToolBatchSource(lane, drive, batch);\n\tawait materializeReady(lane, drive, run, sources, recovery);\n\tconst current = currentBatch(lane);\n\tif (current === undefined) return { kind: \"continue\" };\n\tif (current.run.control.status === \"cancel_requested\") {\n\t\treturn runSequential(lane, drive, current.run, sources, undefined, recovery);\n\t}\n\tconst config = lane.readConfig();\n\tconst active = new Set(batch.configuration.activeToolNames);\n\tconst tools = config.tools.filter((tool) => active.has(tool.name));\n\tconst toolsByName = new Map(tools.map((tool) => [tool.name, tool]));\n\tconst toolContext = await resolveToolContext(lane, drive);\n\treturn run.settings.toolExecution === \"sequential\"\n\t\t? runSequential(lane, drive, current.run, sources, { tools, toolsByName, toolContext }, recovery)\n\t\t: runParallel(lane, drive, current.run, sources, tools, toolsByName, toolContext, recovery);\n}\n"]}
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { AbortRequested } from "../../execution/effect-gate.js";
|
|
2
|
+
import { applyBeforeToolDecision, createToolResultMessage, executeToolCall, finalizeToolCall, prepareToolCall, toolResultFromMessage, } from "../../execution/tools.js";
|
|
3
|
+
import { SessionInvariantError } from "../../session/session.js";
|
|
4
|
+
import { deleteValue, operationToolArgs, operationToolMemo, operationToolMemoPrefix, pendingEntry, pendingToolOutput, setValue, } from "../../session/values.js";
|
|
5
|
+
import { openToolProgress } from "../progress.js";
|
|
6
|
+
import { materializeReady, readToolBatchSource, toolCallFor, withToolBatch, } from "./tool-placement.js";
|
|
7
|
+
const INTERRUPTION_MARKER = "[Tool execution was interrupted. The preceding output is the latest durable progress snapshot; newer live output may be missing, and the external outcome is unknown.]";
|
|
8
|
+
class ToolInvocationEnded extends Error {
|
|
9
|
+
constructor() {
|
|
10
|
+
super("Tool invocation no longer owns its durable effect");
|
|
11
|
+
this.name = "ToolInvocationEnded";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function currentBatch(lane) {
|
|
15
|
+
const operation = lane.state.operation;
|
|
16
|
+
if (operation?.state.at !== "tools")
|
|
17
|
+
return undefined;
|
|
18
|
+
return { run: operation.state, batch: operation.state.batch };
|
|
19
|
+
}
|
|
20
|
+
function findCall(batch, sourceIndex, resultEntryId) {
|
|
21
|
+
return batch.calls.find((call) => call.sourceIndex === sourceIndex && call.resultEntryId === resultEntryId);
|
|
22
|
+
}
|
|
23
|
+
function replaceCall(batch, replacement) {
|
|
24
|
+
return {
|
|
25
|
+
...batch,
|
|
26
|
+
calls: batch.calls.map((call) => call.sourceIndex === replacement.sourceIndex && call.resultEntryId === replacement.resultEntryId
|
|
27
|
+
? replacement
|
|
28
|
+
: call),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function validateMemoName(name) {
|
|
32
|
+
if (name.length === 0)
|
|
33
|
+
throw new TypeError("Tool invocation memo name must not be empty");
|
|
34
|
+
if (name.includes(":"))
|
|
35
|
+
throw new TypeError("Tool invocation memo name must not contain ':'");
|
|
36
|
+
}
|
|
37
|
+
function invocationCapability(lane, drive, batch, call) {
|
|
38
|
+
let active = true;
|
|
39
|
+
const ownsEffect = (state) => {
|
|
40
|
+
const operation = state.operation;
|
|
41
|
+
if (operation?.state.at !== "tools")
|
|
42
|
+
return false;
|
|
43
|
+
return findCall(operation.state.batch, call.sourceIndex, call.resultEntryId)?.status === "effect_pending";
|
|
44
|
+
};
|
|
45
|
+
const ended = () => new ToolInvocationEnded();
|
|
46
|
+
return {
|
|
47
|
+
invocation: {
|
|
48
|
+
invocationId: call.resultEntryId,
|
|
49
|
+
operationId: drive.operationId,
|
|
50
|
+
turnId: batch.turnId,
|
|
51
|
+
getMemo(name) {
|
|
52
|
+
validateMemoName(name);
|
|
53
|
+
if (!active)
|
|
54
|
+
return Promise.reject(ended());
|
|
55
|
+
return lane.command(async (state, reader) => {
|
|
56
|
+
if (!ownsEffect(state))
|
|
57
|
+
return { kind: "reject", error: ended() };
|
|
58
|
+
const stored = await reader.getValue(operationToolMemo(drive.operationId, call.resultEntryId, name), drive.context);
|
|
59
|
+
return { kind: "return", result: stored?.value };
|
|
60
|
+
}, drive.context);
|
|
61
|
+
},
|
|
62
|
+
setMemo(name, value) {
|
|
63
|
+
validateMemoName(name);
|
|
64
|
+
if (!active)
|
|
65
|
+
return Promise.reject(ended());
|
|
66
|
+
return lane.command((state) => {
|
|
67
|
+
if (!ownsEffect(state))
|
|
68
|
+
return { kind: "reject", error: ended() };
|
|
69
|
+
const address = operationToolMemo(drive.operationId, call.resultEntryId, name);
|
|
70
|
+
return {
|
|
71
|
+
kind: "commit",
|
|
72
|
+
writes: [value === undefined ? deleteValue(address) : setValue(address, value)],
|
|
73
|
+
next: state,
|
|
74
|
+
materialize: () => undefined,
|
|
75
|
+
};
|
|
76
|
+
}, drive.context);
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
expire() {
|
|
80
|
+
active = false;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function syntheticMessage(toolCall, content, options = {}) {
|
|
85
|
+
return {
|
|
86
|
+
role: "toolResult",
|
|
87
|
+
toolCallId: toolCall.id,
|
|
88
|
+
toolName: toolCall.name,
|
|
89
|
+
content,
|
|
90
|
+
...(options.details === undefined ? {} : { details: options.details }),
|
|
91
|
+
...(options.usage === undefined ? {} : { usage: options.usage }),
|
|
92
|
+
isError: true,
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function abortedOutcome(toolCall) {
|
|
97
|
+
return {
|
|
98
|
+
toolCall,
|
|
99
|
+
message: syntheticMessage(toolCall, [{ type: "text", text: "Tool execution was cancelled before completion." }]),
|
|
100
|
+
terminate: false,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function interruptedOutcome(toolCall, checkpoint) {
|
|
104
|
+
return {
|
|
105
|
+
toolCall,
|
|
106
|
+
message: syntheticMessage(toolCall, [...(checkpoint?.content ?? []), { type: "text", text: INTERRUPTION_MARKER }], checkpoint === undefined ? {} : { details: checkpoint.details, usage: checkpoint.usage }),
|
|
107
|
+
terminate: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function truncatedOutcome(toolCall) {
|
|
111
|
+
return {
|
|
112
|
+
toolCall,
|
|
113
|
+
message: syntheticMessage(toolCall, [
|
|
114
|
+
{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `Tool call ${JSON.stringify(toolCall.name)} was not executed because the assistant response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`,
|
|
117
|
+
},
|
|
118
|
+
]),
|
|
119
|
+
terminate: false,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function outcomeFromFinalizedCall(finalized) {
|
|
123
|
+
return { toolCall: finalized.toolCall, message: createToolResultMessage(finalized), terminate: finalized.terminate };
|
|
124
|
+
}
|
|
125
|
+
async function publishToolIntent(lane, drive, run, planned, toolCall, args, replay, recovery) {
|
|
126
|
+
return lane.continueOperation(run, (_state, run) => {
|
|
127
|
+
const effectPending = {
|
|
128
|
+
status: "effect_pending",
|
|
129
|
+
sourceIndex: planned.sourceIndex,
|
|
130
|
+
resultEntryId: planned.resultEntryId,
|
|
131
|
+
replay,
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
kind: "commit",
|
|
135
|
+
writes: [setValue(operationToolArgs(drive.operationId, run.batch.turnId, planned.sourceIndex), args)],
|
|
136
|
+
operationState: withToolBatch(run, replaceCall(run.batch, effectPending)),
|
|
137
|
+
materialize: () => effectPending,
|
|
138
|
+
events: () => [
|
|
139
|
+
{
|
|
140
|
+
type: "tool_start",
|
|
141
|
+
lane: lane.name,
|
|
142
|
+
runId: drive.operationId,
|
|
143
|
+
turnId: run.batch.turnId,
|
|
144
|
+
toolCallId: toolCall.id,
|
|
145
|
+
toolName: toolCall.name,
|
|
146
|
+
args,
|
|
147
|
+
...(recovery ? { recovery: true } : {}),
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
}, drive.context);
|
|
152
|
+
}
|
|
153
|
+
async function publishToolOutcome(lane, drive, capability, call, finalized, recovery) {
|
|
154
|
+
await lane.settleOperation(capability, async (_state, run, _meta, reader) => {
|
|
155
|
+
const { toolCall } = finalized;
|
|
156
|
+
const memos = await reader.scanValues(operationToolMemoPrefix(drive.operationId, call.resultEntryId), drive.context);
|
|
157
|
+
const durableTerminate = run.control.status === "running" && finalized.terminate;
|
|
158
|
+
const outcome = {
|
|
159
|
+
status: "outcome_ready",
|
|
160
|
+
sourceIndex: call.sourceIndex,
|
|
161
|
+
resultEntryId: call.resultEntryId,
|
|
162
|
+
terminate: durableTerminate,
|
|
163
|
+
};
|
|
164
|
+
return {
|
|
165
|
+
kind: "commit",
|
|
166
|
+
writes: [
|
|
167
|
+
setValue(pendingEntry(call.resultEntryId), { type: "message", payload: finalized.message }),
|
|
168
|
+
deleteValue(pendingToolOutput(drive.operationId, call.resultEntryId)),
|
|
169
|
+
...memos.map(({ address }) => deleteValue(address)),
|
|
170
|
+
],
|
|
171
|
+
operationState: withToolBatch(run, replaceCall(run.batch, outcome)),
|
|
172
|
+
materialize: () => undefined,
|
|
173
|
+
events: () => [
|
|
174
|
+
...(call.status === "planned"
|
|
175
|
+
? [
|
|
176
|
+
{
|
|
177
|
+
type: "tool_start",
|
|
178
|
+
lane: lane.name,
|
|
179
|
+
runId: drive.operationId,
|
|
180
|
+
turnId: run.batch.turnId,
|
|
181
|
+
toolCallId: toolCall.id,
|
|
182
|
+
toolName: toolCall.name,
|
|
183
|
+
args: toolCall.arguments,
|
|
184
|
+
...(recovery ? { recovery: true } : {}),
|
|
185
|
+
},
|
|
186
|
+
]
|
|
187
|
+
: []),
|
|
188
|
+
{
|
|
189
|
+
type: "tool_end",
|
|
190
|
+
lane: lane.name,
|
|
191
|
+
runId: drive.operationId,
|
|
192
|
+
turnId: run.batch.turnId,
|
|
193
|
+
toolCallId: toolCall.id,
|
|
194
|
+
toolName: toolCall.name,
|
|
195
|
+
result: toolResultFromMessage(finalized.message, durableTerminate),
|
|
196
|
+
isError: finalized.message.isError,
|
|
197
|
+
terminate: durableTerminate,
|
|
198
|
+
...(recovery ? { recovery: true } : {}),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}, drive.context);
|
|
203
|
+
}
|
|
204
|
+
async function clearReplayCheckpoint(lane, drive, batch, call, toolCall) {
|
|
205
|
+
return lane.command(async (state, reader) => {
|
|
206
|
+
const stored = await reader.getValue(operationToolArgs(drive.operationId, batch.turnId, call.sourceIndex), drive.context);
|
|
207
|
+
if (stored === undefined) {
|
|
208
|
+
throw new SessionInvariantError(`Tool call ${call.resultEntryId} is missing persisted arguments`);
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
kind: "commit",
|
|
212
|
+
writes: [deleteValue(pendingToolOutput(drive.operationId, call.resultEntryId))],
|
|
213
|
+
next: state,
|
|
214
|
+
materialize: () => stored.value,
|
|
215
|
+
events: () => [
|
|
216
|
+
{
|
|
217
|
+
type: "tool_start",
|
|
218
|
+
lane: lane.name,
|
|
219
|
+
runId: drive.operationId,
|
|
220
|
+
turnId: batch.turnId,
|
|
221
|
+
toolCallId: toolCall.id,
|
|
222
|
+
toolName: toolCall.name,
|
|
223
|
+
args: stored.value,
|
|
224
|
+
recovery: true,
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
}, drive.context);
|
|
229
|
+
}
|
|
230
|
+
function readCheckpoint(lane, drive, call) {
|
|
231
|
+
return lane.command(async (_state, reader) => {
|
|
232
|
+
const stored = await reader.getValue(pendingToolOutput(drive.operationId, call.resultEntryId), drive.context);
|
|
233
|
+
return { kind: "return", result: stored?.value };
|
|
234
|
+
}, drive.context);
|
|
235
|
+
}
|
|
236
|
+
async function resolveToolContext(lane, drive) {
|
|
237
|
+
const source = lane.readConfig().toolContext;
|
|
238
|
+
return (typeof source === "function" ? await source(drive.context) : source);
|
|
239
|
+
}
|
|
240
|
+
async function performToolInvocation(lane, drive, batch, call, cleared, toolContext, recovery) {
|
|
241
|
+
const capability = invocationCapability(lane, drive, batch, call);
|
|
242
|
+
const progress = openToolProgress(lane, drive, batch.turnId, call.sourceIndex, call.resultEntryId);
|
|
243
|
+
let latestUpdateDelivery = Promise.resolve();
|
|
244
|
+
const publishUpdate = (partial) => {
|
|
245
|
+
latestUpdateDelivery = lane.emitBatch([
|
|
246
|
+
{
|
|
247
|
+
type: "tool_update",
|
|
248
|
+
lane: lane.name,
|
|
249
|
+
runId: drive.operationId,
|
|
250
|
+
turnId: batch.turnId,
|
|
251
|
+
toolCallId: cleared.toolCall.id,
|
|
252
|
+
toolName: cleared.toolCall.name,
|
|
253
|
+
partialResult: partial,
|
|
254
|
+
...(recovery ? { recovery: true } : {}),
|
|
255
|
+
},
|
|
256
|
+
], drive.context);
|
|
257
|
+
void latestUpdateDelivery.catch(() => { });
|
|
258
|
+
};
|
|
259
|
+
let execution;
|
|
260
|
+
try {
|
|
261
|
+
execution = executeToolCall(cleared, drive.gate, (partial, options) => {
|
|
262
|
+
publishUpdate(partial);
|
|
263
|
+
if (options?.checkpoint === true)
|
|
264
|
+
progress.write(partial);
|
|
265
|
+
}, toolContext, capability.invocation, drive.context);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
capability.expire();
|
|
269
|
+
progress.seal();
|
|
270
|
+
await progress.drain();
|
|
271
|
+
if (!(error instanceof AbortRequested))
|
|
272
|
+
throw error;
|
|
273
|
+
await error.cancellation;
|
|
274
|
+
return recovery ? interruptedOutcome(cleared.toolCall, undefined) : abortedOutcome(cleared.toolCall);
|
|
275
|
+
}
|
|
276
|
+
const executed = await execution.finally(() => {
|
|
277
|
+
capability.expire();
|
|
278
|
+
progress.seal();
|
|
279
|
+
});
|
|
280
|
+
await latestUpdateDelivery;
|
|
281
|
+
await progress.drain();
|
|
282
|
+
let patch;
|
|
283
|
+
try {
|
|
284
|
+
patch = await lane.hooks.runToolWithGate("after_tool", {
|
|
285
|
+
lane: lane.name,
|
|
286
|
+
runId: drive.operationId,
|
|
287
|
+
toolCallId: cleared.toolCall.id,
|
|
288
|
+
toolName: cleared.toolCall.name,
|
|
289
|
+
args: cleared.args,
|
|
290
|
+
content: executed.result.content,
|
|
291
|
+
...(executed.result.details === undefined ? {} : { details: executed.result.details }),
|
|
292
|
+
isError: executed.isError,
|
|
293
|
+
...(executed.result.usage === undefined ? {} : { usage: executed.result.usage }),
|
|
294
|
+
}, drive.gate, drive.context);
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (!(error instanceof AbortRequested))
|
|
298
|
+
throw error;
|
|
299
|
+
patch = undefined;
|
|
300
|
+
}
|
|
301
|
+
const finalized = finalizeToolCall(cleared, executed, patch);
|
|
302
|
+
return { toolCall: finalized.toolCall, message: createToolResultMessage(finalized), terminate: finalized.terminate };
|
|
303
|
+
}
|
|
304
|
+
async function prepareToolInvocation(lane, drive, sources, call, tools) {
|
|
305
|
+
const toolCall = toolCallFor(sources, call);
|
|
306
|
+
if (sources.assistant.stopReason === "length") {
|
|
307
|
+
return { kind: "outcome", outcome: truncatedOutcome(toolCall) };
|
|
308
|
+
}
|
|
309
|
+
const prepared = prepareToolCall(toolCall, tools);
|
|
310
|
+
if ("kind" in prepared)
|
|
311
|
+
return { kind: "outcome", outcome: outcomeFromFinalizedCall(prepared) };
|
|
312
|
+
let decision;
|
|
313
|
+
try {
|
|
314
|
+
decision = await lane.hooks.runToolWithGate("before_tool", {
|
|
315
|
+
lane: lane.name,
|
|
316
|
+
runId: drive.operationId,
|
|
317
|
+
toolCallId: toolCall.id,
|
|
318
|
+
toolName: toolCall.name,
|
|
319
|
+
args: prepared.args,
|
|
320
|
+
}, drive.gate, drive.context);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
if (!(error instanceof AbortRequested))
|
|
324
|
+
throw error;
|
|
325
|
+
await error.cancellation;
|
|
326
|
+
return { kind: "outcome", outcome: abortedOutcome(toolCall) };
|
|
327
|
+
}
|
|
328
|
+
const cleared = applyBeforeToolDecision(prepared, decision);
|
|
329
|
+
return "kind" in cleared
|
|
330
|
+
? { kind: "outcome", outcome: outcomeFromFinalizedCall(cleared) }
|
|
331
|
+
: { kind: "ready", cleared };
|
|
332
|
+
}
|
|
333
|
+
async function startToolInvocation(lane, drive, run, sources, call, tools, toolContext, recovery) {
|
|
334
|
+
const prepared = await prepareToolInvocation(lane, drive, sources, call, tools);
|
|
335
|
+
if (prepared.kind === "outcome") {
|
|
336
|
+
return { completion: publishToolOutcome(lane, drive, run, call, prepared.outcome, recovery) };
|
|
337
|
+
}
|
|
338
|
+
const effectPending = await publishToolIntent(lane, drive, run, call, prepared.cleared.toolCall, prepared.cleared.args, prepared.cleared.tool.replay ?? "never", recovery);
|
|
339
|
+
return {
|
|
340
|
+
completion: effectPending.kind === "cancel_requested"
|
|
341
|
+
? publishToolOutcome(lane, drive, run, call, abortedOutcome(prepared.cleared.toolCall), recovery)
|
|
342
|
+
: performToolInvocation(lane, drive, run.batch, effectPending.value, prepared.cleared, toolContext, recovery).then((outcome) => publishToolOutcome(lane, drive, run, effectPending.value, outcome, recovery)),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
async function recoverToolInvocation(lane, drive, run, sources, call, toolsByName, toolContext, cancelled) {
|
|
346
|
+
const toolCall = toolCallFor(sources, call);
|
|
347
|
+
const tool = toolsByName.get(toolCall.name);
|
|
348
|
+
if (!cancelled && call.replay === "safe" && tool?.replay === "safe") {
|
|
349
|
+
const args = await clearReplayCheckpoint(lane, drive, run.batch, call, toolCall);
|
|
350
|
+
const cleared = { toolCall, tool, args };
|
|
351
|
+
return {
|
|
352
|
+
completion: performToolInvocation(lane, drive, run.batch, call, cleared, toolContext, true).then((outcome) => publishToolOutcome(lane, drive, run, call, outcome, true)),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const checkpoint = await readCheckpoint(lane, drive, call);
|
|
356
|
+
return {
|
|
357
|
+
completion: publishToolOutcome(lane, drive, run, call, interruptedOutcome(toolCall, checkpoint), true),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
async function runSequential(lane, drive, run, sources, execution, recovery) {
|
|
361
|
+
const { batch } = run;
|
|
362
|
+
for (let transition = 0; transition <= batch.calls.length * 2 + 1; transition += 1) {
|
|
363
|
+
await materializeReady(lane, drive, run, sources, recovery);
|
|
364
|
+
const current = currentBatch(lane);
|
|
365
|
+
if (current === undefined)
|
|
366
|
+
return { kind: "continue" };
|
|
367
|
+
const call = current.batch.calls.find((candidate) => candidate.status !== "completed");
|
|
368
|
+
if (call === undefined)
|
|
369
|
+
throw new SessionInvariantError("Tool batch remained open after every call completed");
|
|
370
|
+
if (call.status === "outcome_ready")
|
|
371
|
+
throw new SessionInvariantError("Ready tool outcome was not materialized");
|
|
372
|
+
if (current.run.control.status === "cancel_requested") {
|
|
373
|
+
const toolCall = toolCallFor(sources, call);
|
|
374
|
+
if (call.status === "planned") {
|
|
375
|
+
await publishToolOutcome(lane, drive, current.run, call, abortedOutcome(toolCall), recovery);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
const checkpoint = await readCheckpoint(lane, drive, call);
|
|
379
|
+
await publishToolOutcome(lane, drive, current.run, call, interruptedOutcome(toolCall, checkpoint), recovery);
|
|
380
|
+
}
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (execution === undefined)
|
|
384
|
+
throw new SessionInvariantError("Running tool batch is missing execution context");
|
|
385
|
+
const started = call.status === "planned"
|
|
386
|
+
? await startToolInvocation(lane, drive, current.run, sources, call, execution.tools, execution.toolContext, recovery)
|
|
387
|
+
: await recoverToolInvocation(lane, drive, current.run, sources, call, execution.toolsByName, execution.toolContext, false);
|
|
388
|
+
await started.completion;
|
|
389
|
+
}
|
|
390
|
+
throw new SessionInvariantError("Sequential tool batch exceeded its bounded transition count");
|
|
391
|
+
}
|
|
392
|
+
async function runParallel(lane, drive, run, sources, tools, toolsByName, toolContext, recovery) {
|
|
393
|
+
const { batch } = run;
|
|
394
|
+
let materialization = Promise.resolve();
|
|
395
|
+
const scheduleMaterialization = () => {
|
|
396
|
+
const scheduled = materialization.then(() => materializeReady(lane, drive, run, sources, recovery));
|
|
397
|
+
materialization = scheduled.catch(() => { });
|
|
398
|
+
return scheduled;
|
|
399
|
+
};
|
|
400
|
+
const jobs = [];
|
|
401
|
+
for (const call of batch.calls) {
|
|
402
|
+
if (call.status === "completed" || call.status === "outcome_ready")
|
|
403
|
+
continue;
|
|
404
|
+
const started = call.status === "planned"
|
|
405
|
+
? await startToolInvocation(lane, drive, run, sources, call, tools, toolContext, recovery)
|
|
406
|
+
: await recoverToolInvocation(lane, drive, run, sources, call, toolsByName, toolContext, lane.state.operation.state.control.status === "cancel_requested");
|
|
407
|
+
const job = started.completion.then(async () => {
|
|
408
|
+
await scheduleMaterialization();
|
|
409
|
+
});
|
|
410
|
+
void job.catch(() => { });
|
|
411
|
+
jobs.push(job);
|
|
412
|
+
}
|
|
413
|
+
await Promise.all(jobs);
|
|
414
|
+
await scheduleMaterialization();
|
|
415
|
+
return { kind: "continue" };
|
|
416
|
+
}
|
|
417
|
+
/** Execute, recover, stage, and source-order one complete durable tool batch. */
|
|
418
|
+
export async function runTools(lane, drive, run) {
|
|
419
|
+
const batch = run.batch;
|
|
420
|
+
const recovery = batch.calls.some((call) => call.status === "effect_pending" || call.status === "outcome_ready");
|
|
421
|
+
if (recovery) {
|
|
422
|
+
await lane.emitBatch([
|
|
423
|
+
{
|
|
424
|
+
type: "turn_start",
|
|
425
|
+
lane: lane.name,
|
|
426
|
+
runId: drive.operationId,
|
|
427
|
+
turnId: batch.turnId,
|
|
428
|
+
recovery: true,
|
|
429
|
+
},
|
|
430
|
+
], drive.context);
|
|
431
|
+
}
|
|
432
|
+
const sources = await readToolBatchSource(lane, drive, batch);
|
|
433
|
+
await materializeReady(lane, drive, run, sources, recovery);
|
|
434
|
+
const current = currentBatch(lane);
|
|
435
|
+
if (current === undefined)
|
|
436
|
+
return { kind: "continue" };
|
|
437
|
+
if (current.run.control.status === "cancel_requested") {
|
|
438
|
+
return runSequential(lane, drive, current.run, sources, undefined, recovery);
|
|
439
|
+
}
|
|
440
|
+
const config = lane.readConfig();
|
|
441
|
+
const active = new Set(batch.configuration.activeToolNames);
|
|
442
|
+
const tools = config.tools.filter((tool) => active.has(tool.name));
|
|
443
|
+
const toolsByName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
444
|
+
const toolContext = await resolveToolContext(lane, drive);
|
|
445
|
+
return run.settings.toolExecution === "sequential"
|
|
446
|
+
? runSequential(lane, drive, current.run, sources, { tools, toolsByName, toolContext }, recovery)
|
|
447
|
+
: runParallel(lane, drive, current.run, sources, tools, toolsByName, toolContext, recovery);
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=tools.js.map
|