@assemblyline-agents/runtime 2.0.0 → 3.0.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/LICENSE +1 -1
- package/dist/a2a-client.d.ts +22 -0
- package/dist/a2a-client.d.ts.map +1 -0
- package/dist/a2a-client.js +211 -0
- package/dist/a2a-client.js.map +1 -0
- package/dist/agent-hook-context.d.ts +6 -1
- package/dist/agent-hook-context.d.ts.map +1 -1
- package/dist/agent-hook-context.js +24 -11
- package/dist/agent-hook-context.js.map +1 -1
- package/dist/agent-hook-evaluation.d.ts +6 -1
- package/dist/agent-hook-evaluation.d.ts.map +1 -1
- package/dist/agent-hook-evaluation.js +16 -5
- package/dist/agent-hook-evaluation.js.map +1 -1
- package/dist/agent-hook-run-lifecycle.d.ts +5 -1
- package/dist/agent-hook-run-lifecycle.d.ts.map +1 -1
- package/dist/agent-hook-run-lifecycle.js +11 -13
- package/dist/agent-hook-run-lifecycle.js.map +1 -1
- package/dist/agent-surface.d.ts +32 -0
- package/dist/agent-surface.d.ts.map +1 -0
- package/dist/agent-surface.js +85 -0
- package/dist/agent-surface.js.map +1 -0
- package/dist/attachments.d.ts +5 -1
- package/dist/attachments.d.ts.map +1 -1
- package/dist/attachments.js +58 -32
- package/dist/attachments.js.map +1 -1
- package/dist/audience.d.ts +30 -0
- package/dist/audience.d.ts.map +1 -0
- package/dist/audience.js +68 -0
- package/dist/audience.js.map +1 -0
- package/dist/automation-event-match.d.ts +8 -0
- package/dist/automation-event-match.d.ts.map +1 -0
- package/dist/automation-event-match.js +25 -0
- package/dist/automation-event-match.js.map +1 -0
- package/dist/background-review-trigger.d.ts.map +1 -1
- package/dist/background-review-trigger.js +14 -16
- package/dist/background-review-trigger.js.map +1 -1
- package/dist/background-review-types.d.ts +9 -2
- package/dist/background-review-types.d.ts.map +1 -1
- package/dist/background-review-worker.js +2 -2
- package/dist/background-review-worker.js.map +1 -1
- package/dist/background-review.d.ts.map +1 -1
- package/dist/background-review.js +27 -10
- package/dist/background-review.js.map +1 -1
- package/dist/builtin-tool-executors.d.ts +47 -21
- package/dist/builtin-tool-executors.d.ts.map +1 -1
- package/dist/builtin-tool-executors.js +293 -121
- package/dist/builtin-tool-executors.js.map +1 -1
- package/dist/builtin-tools.d.ts +16 -8
- package/dist/builtin-tools.d.ts.map +1 -1
- package/dist/builtin-tools.js +309 -70
- package/dist/builtin-tools.js.map +1 -1
- package/dist/capability-catalog.d.ts +3 -2
- package/dist/capability-catalog.d.ts.map +1 -1
- package/dist/capability-catalog.js +10 -6
- package/dist/capability-catalog.js.map +1 -1
- package/dist/capability-inspection.d.ts +31 -0
- package/dist/capability-inspection.d.ts.map +1 -0
- package/dist/capability-inspection.js +58 -0
- package/dist/capability-inspection.js.map +1 -0
- package/dist/channel-http-util.d.ts.map +1 -1
- package/dist/channel-http-util.js +6 -2
- package/dist/channel-http-util.js.map +1 -1
- package/dist/channel-ingress.d.ts +16 -1
- package/dist/channel-ingress.d.ts.map +1 -1
- package/dist/channel-ingress.js +117 -7
- package/dist/channel-ingress.js.map +1 -1
- package/dist/channel.d.ts +58 -2
- package/dist/channel.d.ts.map +1 -1
- package/dist/checkpoints.d.ts +1 -1
- package/dist/checkpoints.d.ts.map +1 -1
- package/dist/checkpoints.js +6 -6
- package/dist/checkpoints.js.map +1 -1
- package/dist/child-process-env.d.ts +7 -0
- package/dist/child-process-env.d.ts.map +1 -0
- package/dist/child-process-env.js +41 -0
- package/dist/child-process-env.js.map +1 -0
- package/dist/computer-relay-protocol.d.ts.map +1 -1
- package/dist/computer-relay-protocol.js +4 -4
- package/dist/computer-relay-protocol.js.map +1 -1
- package/dist/concurrency.d.ts +1 -1
- package/dist/concurrency.js +1 -1
- package/dist/connection-auth-util.d.ts +1 -0
- package/dist/connection-auth-util.d.ts.map +1 -1
- package/dist/connection-auth-util.js +1 -1
- package/dist/connection-auth-util.js.map +1 -1
- package/dist/connection-clients.d.ts +11 -3
- package/dist/connection-clients.d.ts.map +1 -1
- package/dist/connection-clients.js +71 -8
- package/dist/connection-clients.js.map +1 -1
- package/dist/connection-event-store.d.ts +98 -0
- package/dist/connection-event-store.d.ts.map +1 -0
- package/dist/connection-event-store.js +162 -0
- package/dist/connection-event-store.js.map +1 -0
- package/dist/connection-events.d.ts +51 -0
- package/dist/connection-events.d.ts.map +1 -0
- package/dist/connection-events.js +343 -0
- package/dist/connection-events.js.map +1 -0
- package/dist/connection-stores.d.ts +3 -0
- package/dist/connection-stores.d.ts.map +1 -1
- package/dist/connection-stores.js +4 -1
- package/dist/connection-stores.js.map +1 -1
- package/dist/connection-util.d.ts +3 -2
- package/dist/connection-util.d.ts.map +1 -1
- package/dist/connection-util.js +18 -1
- package/dist/connection-util.js.map +1 -1
- package/dist/connections.d.ts +54 -5
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +342 -53
- package/dist/connections.js.map +1 -1
- package/dist/context-policy-util.d.ts.map +1 -1
- package/dist/context-policy-util.js +1 -3
- package/dist/context-policy-util.js.map +1 -1
- package/dist/conversation-context.d.ts +6 -2
- package/dist/conversation-context.d.ts.map +1 -1
- package/dist/conversation-context.js +45 -12
- package/dist/conversation-context.js.map +1 -1
- package/dist/conversation-transcript.d.ts +8 -5
- package/dist/conversation-transcript.d.ts.map +1 -1
- package/dist/conversation-transcript.js +24 -5
- package/dist/conversation-transcript.js.map +1 -1
- package/dist/conversation-turn-coalescing.d.ts +22 -0
- package/dist/conversation-turn-coalescing.d.ts.map +1 -0
- package/dist/conversation-turn-coalescing.js +121 -0
- package/dist/conversation-turn-coalescing.js.map +1 -0
- package/dist/conversation-turn-dispatch.d.ts +5 -2
- package/dist/conversation-turn-dispatch.d.ts.map +1 -1
- package/dist/conversation-turn-dispatch.js +59 -22
- package/dist/conversation-turn-dispatch.js.map +1 -1
- package/dist/default-outbound-route.d.ts +29 -0
- package/dist/default-outbound-route.d.ts.map +1 -0
- package/dist/default-outbound-route.js +105 -0
- package/dist/default-outbound-route.js.map +1 -0
- package/dist/delivery-artifacts.d.ts +2 -0
- package/dist/delivery-artifacts.d.ts.map +1 -0
- package/dist/delivery-artifacts.js +34 -0
- package/dist/delivery-artifacts.js.map +1 -0
- package/dist/delivery-files.d.ts +5 -0
- package/dist/delivery-files.d.ts.map +1 -0
- package/dist/delivery-files.js +33 -0
- package/dist/delivery-files.js.map +1 -0
- package/dist/delivery-queue.d.ts +21 -1
- package/dist/delivery-queue.d.ts.map +1 -1
- package/dist/delivery-queue.js +144 -1
- package/dist/delivery-queue.js.map +1 -1
- package/dist/delivery-send.d.ts +2 -2
- package/dist/delivery-send.d.ts.map +1 -1
- package/dist/delivery-send.js +256 -100
- package/dist/delivery-send.js.map +1 -1
- package/dist/durable-files.d.ts +37 -0
- package/dist/durable-files.d.ts.map +1 -0
- package/dist/durable-files.js +63 -0
- package/dist/durable-files.js.map +1 -0
- package/dist/harness-loop.d.ts +6 -1
- package/dist/harness-loop.d.ts.map +1 -1
- package/dist/harness-loop.js +110 -25
- package/dist/harness-loop.js.map +1 -1
- package/dist/heic-transcode-worker.d.ts +2 -0
- package/dist/heic-transcode-worker.d.ts.map +1 -0
- package/dist/heic-transcode-worker.js +59 -0
- package/dist/heic-transcode-worker.js.map +1 -0
- package/dist/heic-transcode.d.ts +18 -0
- package/dist/heic-transcode.d.ts.map +1 -0
- package/dist/heic-transcode.js +99 -0
- package/dist/heic-transcode.js.map +1 -0
- package/dist/human-input-routing.d.ts +22 -0
- package/dist/human-input-routing.d.ts.map +1 -0
- package/dist/human-input-routing.js +26 -0
- package/dist/human-input-routing.js.map +1 -0
- package/dist/in-memory-conversation-turn-store.d.ts +3 -1
- package/dist/in-memory-conversation-turn-store.d.ts.map +1 -1
- package/dist/in-memory-conversation-turn-store.js +41 -2
- package/dist/in-memory-conversation-turn-store.js.map +1 -1
- package/dist/in-memory-run-store.d.ts +8 -0
- package/dist/in-memory-run-store.d.ts.map +1 -1
- package/dist/in-memory-run-store.js +28 -5
- package/dist/in-memory-run-store.js.map +1 -1
- package/dist/in-memory-sandbox-session-store.d.ts +2 -1
- package/dist/in-memory-sandbox-session-store.d.ts.map +1 -1
- package/dist/in-memory-sandbox-session-store.js +65 -1
- package/dist/in-memory-sandbox-session-store.js.map +1 -1
- package/dist/in-memory-small-stores.d.ts +18 -1
- package/dist/in-memory-small-stores.d.ts.map +1 -1
- package/dist/in-memory-small-stores.js +107 -1
- package/dist/in-memory-small-stores.js.map +1 -1
- package/dist/in-memory-workspace-store.d.ts +40 -0
- package/dist/in-memory-workspace-store.d.ts.map +1 -0
- package/dist/in-memory-workspace-store.js +370 -0
- package/dist/in-memory-workspace-store.js.map +1 -0
- package/dist/index.d.ts +73 -36
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +390 -258
- package/dist/index.js.map +1 -1
- package/dist/json-util.d.ts +8 -0
- package/dist/json-util.d.ts.map +1 -1
- package/dist/json-util.js +8 -0
- package/dist/json-util.js.map +1 -1
- package/dist/local-sandbox.d.ts +3 -2
- package/dist/local-sandbox.d.ts.map +1 -1
- package/dist/local-sandbox.js +69 -25
- package/dist/local-sandbox.js.map +1 -1
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +3 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/media-processor.d.ts +42 -0
- package/dist/media-processor.d.ts.map +1 -0
- package/dist/media-processor.js +2 -0
- package/dist/media-processor.js.map +1 -0
- package/dist/model-media.d.ts +13 -1
- package/dist/model-media.d.ts.map +1 -1
- package/dist/model-media.js +81 -18
- package/dist/model-media.js.map +1 -1
- package/dist/model-visible-interrupts.d.ts +10 -0
- package/dist/model-visible-interrupts.d.ts.map +1 -0
- package/dist/model-visible-interrupts.js +41 -0
- package/dist/model-visible-interrupts.js.map +1 -0
- package/dist/operator-controls.d.ts.map +1 -1
- package/dist/operator-controls.js +16 -3
- package/dist/operator-controls.js.map +1 -1
- package/dist/outbound-http-policy.d.ts +7 -0
- package/dist/outbound-http-policy.d.ts.map +1 -0
- package/dist/outbound-http-policy.js +155 -0
- package/dist/outbound-http-policy.js.map +1 -0
- package/dist/public-api.d.ts +21 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +19 -0
- package/dist/public-api.js.map +1 -0
- package/dist/replay-resume.d.ts +8 -0
- package/dist/replay-resume.d.ts.map +1 -1
- package/dist/replay-resume.js +141 -11
- package/dist/replay-resume.js.map +1 -1
- package/dist/resource-projection-util.d.ts +1 -1
- package/dist/resource-projection-util.d.ts.map +1 -1
- package/dist/resource-projection-util.js +21 -10
- package/dist/resource-projection-util.js.map +1 -1
- package/dist/resource-projection.d.ts +8 -1
- package/dist/resource-projection.d.ts.map +1 -1
- package/dist/resource-projection.js +229 -29
- package/dist/resource-projection.js.map +1 -1
- package/dist/run-heartbeat.d.ts +12 -2
- package/dist/run-heartbeat.d.ts.map +1 -1
- package/dist/run-heartbeat.js +31 -4
- package/dist/run-heartbeat.js.map +1 -1
- package/dist/run-outcome.d.ts +9 -5
- package/dist/run-outcome.d.ts.map +1 -1
- package/dist/run-outcome.js +14 -5
- package/dist/run-outcome.js.map +1 -1
- package/dist/run-recovery.d.ts +19 -3
- package/dist/run-recovery.d.ts.map +1 -1
- package/dist/run-recovery.js +205 -34
- package/dist/run-recovery.js.map +1 -1
- package/dist/run-replay.d.ts +35 -0
- package/dist/run-replay.d.ts.map +1 -0
- package/dist/run-replay.js +193 -0
- package/dist/run-replay.js.map +1 -0
- package/dist/run-result.d.ts +4 -0
- package/dist/run-result.d.ts.map +1 -0
- package/dist/run-result.js +18 -0
- package/dist/run-result.js.map +1 -0
- package/dist/run-timeline-query.d.ts +38 -0
- package/dist/run-timeline-query.d.ts.map +1 -0
- package/dist/run-timeline-query.js +99 -0
- package/dist/run-timeline-query.js.map +1 -0
- package/dist/runs-query.d.ts.map +1 -1
- package/dist/runs-query.js +11 -3
- package/dist/runs-query.js.map +1 -1
- package/dist/runtime-bundle.d.ts.map +1 -1
- package/dist/runtime-bundle.js +2 -0
- package/dist/runtime-bundle.js.map +1 -1
- package/dist/runtime-learning.d.ts +15 -13
- package/dist/runtime-learning.d.ts.map +1 -1
- package/dist/runtime-learning.js +79 -58
- package/dist/runtime-learning.js.map +1 -1
- package/dist/runtime-types.d.ts +68 -9
- package/dist/runtime-types.d.ts.map +1 -1
- package/dist/sandbox-fs.d.ts +8 -5
- package/dist/sandbox-fs.d.ts.map +1 -1
- package/dist/sandbox-fs.js +30 -31
- package/dist/sandbox-fs.js.map +1 -1
- package/dist/sandbox-handle.d.ts +25 -0
- package/dist/sandbox-handle.d.ts.map +1 -0
- package/dist/sandbox-handle.js +120 -0
- package/dist/sandbox-handle.js.map +1 -0
- package/dist/sandbox-session-identity.d.ts +14 -0
- package/dist/sandbox-session-identity.d.ts.map +1 -0
- package/dist/sandbox-session-identity.js +33 -0
- package/dist/sandbox-session-identity.js.map +1 -0
- package/dist/sandbox-session-key.d.ts.map +1 -1
- package/dist/sandbox-session-key.js +12 -9
- package/dist/sandbox-session-key.js.map +1 -1
- package/dist/sandbox-session-lifecycle.d.ts.map +1 -1
- package/dist/sandbox-session-lifecycle.js +187 -44
- package/dist/sandbox-session-lifecycle.js.map +1 -1
- package/dist/sandbox-snapshot-policy.js +3 -3
- package/dist/sandbox-snapshot-policy.js.map +1 -1
- package/dist/sandbox-state-sync.d.ts +4 -2
- package/dist/sandbox-state-sync.d.ts.map +1 -1
- package/dist/sandbox-state-sync.js +47 -15
- package/dist/sandbox-state-sync.js.map +1 -1
- package/dist/sandbox-sync-worker.d.ts +11 -2
- package/dist/sandbox-sync-worker.d.ts.map +1 -1
- package/dist/sandbox-sync-worker.js +143 -31
- package/dist/sandbox-sync-worker.js.map +1 -1
- package/dist/schedule-execution.d.ts.map +1 -1
- package/dist/schedule-execution.js +127 -23
- package/dist/schedule-execution.js.map +1 -1
- package/dist/sdk-api-client.d.ts +17 -0
- package/dist/sdk-api-client.d.ts.map +1 -0
- package/dist/sdk-api-client.js +55 -0
- package/dist/sdk-api-client.js.map +1 -0
- package/dist/security.js +2 -2
- package/dist/security.js.map +1 -1
- package/dist/self-improvement.d.ts +5 -1
- package/dist/self-improvement.d.ts.map +1 -1
- package/dist/self-improvement.js +28 -14
- package/dist/self-improvement.js.map +1 -1
- package/dist/skill-bundles.d.ts +55 -0
- package/dist/skill-bundles.d.ts.map +1 -0
- package/dist/skill-bundles.js +134 -0
- package/dist/skill-bundles.js.map +1 -0
- package/dist/source-loader.js +7 -7
- package/dist/source-loader.js.map +1 -1
- package/dist/state-store-helpers.d.ts +2 -0
- package/dist/state-store-helpers.d.ts.map +1 -1
- package/dist/state-store-helpers.js +11 -1
- package/dist/state-store-helpers.js.map +1 -1
- package/dist/state-stores.d.ts +1 -0
- package/dist/state-stores.d.ts.map +1 -1
- package/dist/state-stores.js +26 -7
- package/dist/state-stores.js.map +1 -1
- package/dist/state.d.ts +305 -5
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +41 -2
- package/dist/state.js.map +1 -1
- package/dist/storage.d.ts +47 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +158 -6
- package/dist/storage.js.map +1 -1
- package/dist/subagent-execution.d.ts +1 -1
- package/dist/subagent-execution.d.ts.map +1 -1
- package/dist/subagent-execution.js +10 -12
- package/dist/subagent-execution.js.map +1 -1
- package/dist/target-instructions.js +1 -1
- package/dist/target-instructions.js.map +1 -1
- package/dist/tool-apis.d.ts.map +1 -1
- package/dist/tool-apis.js +33 -9
- package/dist/tool-apis.js.map +1 -1
- package/dist/tool-execution.d.ts +22 -12
- package/dist/tool-execution.d.ts.map +1 -1
- package/dist/tool-execution.js +368 -238
- package/dist/tool-execution.js.map +1 -1
- package/dist/turn-media.d.ts +29 -0
- package/dist/turn-media.d.ts.map +1 -0
- package/dist/turn-media.js +233 -0
- package/dist/turn-media.js.map +1 -0
- package/dist/usage-reconciliation.d.ts +1 -1
- package/dist/usage-reconciliation.js +1 -1
- package/dist/workspace-id.d.ts +10 -0
- package/dist/workspace-id.d.ts.map +1 -0
- package/dist/workspace-id.js +55 -0
- package/dist/workspace-id.js.map +1 -0
- package/dist/workspace-manifest.d.ts +24 -0
- package/dist/workspace-manifest.d.ts.map +1 -0
- package/dist/workspace-manifest.js +111 -0
- package/dist/workspace-manifest.js.map +1 -0
- package/dist/workspace-operation-limiter.d.ts +16 -0
- package/dist/workspace-operation-limiter.d.ts.map +1 -0
- package/dist/workspace-operation-limiter.js +31 -0
- package/dist/workspace-operation-limiter.js.map +1 -0
- package/dist/workspace-operations.d.ts +145 -0
- package/dist/workspace-operations.d.ts.map +1 -0
- package/dist/workspace-operations.js +420 -0
- package/dist/workspace-operations.js.map +1 -0
- package/dist/workspace-runtime.d.ts +110 -0
- package/dist/workspace-runtime.d.ts.map +1 -0
- package/dist/workspace-runtime.js +240 -0
- package/dist/workspace-runtime.js.map +1 -0
- package/dist/workspace-search.d.ts +55 -0
- package/dist/workspace-search.d.ts.map +1 -0
- package/dist/workspace-search.js +262 -0
- package/dist/workspace-search.js.map +1 -0
- package/dist/workspace-service.d.ts +173 -0
- package/dist/workspace-service.d.ts.map +1 -0
- package/dist/workspace-service.js +619 -0
- package/dist/workspace-service.js.map +1 -0
- package/dist/workspace.d.ts +7 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +7 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +7 -4
package/dist/tool-execution.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { boundModelOutput, normalizeApprovalPolicy, sandboxFilesystemContractMetadata } from "@assemblyline-agents/core";
|
|
2
|
-
import {
|
|
3
|
-
import { createConnectionRegistryForRunImpl,
|
|
4
|
-
import { CONNECTION_SEARCH_TOOL_NAME, parseQualifiedName } from "./connections.js";
|
|
1
|
+
import { boundModelOutput, DELEGATE_TOOL_NAME, normalizeApprovalPolicy, sandboxFilesystemContractMetadata } from "@assemblyline-agents/core";
|
|
2
|
+
import { HISTORY_SEARCH_TOOL_NAME, FILES_MOUNT_TOOL_NAME, FILES_SEARCH_TOOL_NAME, LOAD_SKILL_TOOL_NAME, PAIR_TOOL_NAME, runtimeToolsForSurface, TOOL_SEARCH_TOOL_NAME, WORKSPACE_CHECKPOINT_CREATE_TOOL_NAME, WORKSPACE_CHECKPOINT_LIST_TOOL_NAME, WORKSPACE_CHECKPOINT_RESTORE_TOOL_NAME, WORKSPACE_FORK_TOOL_NAME, WORKSPACE_SEARCH_TOOL_NAME, WORKSPACE_STATUS_TOOL_NAME } from "./builtin-tools.js";
|
|
3
|
+
import { createConnectionRegistryForRunImpl, executeConnectionSearchTool, executeConnectionTool, executeHistorySearchTool, executeLoadSkillTool, executePairTool, executeToolSearchTool, failRuntimeHandledTool, recordRuntimeHandledToolStart } from "./builtin-tool-executors.js";
|
|
4
|
+
import { CONNECTION_SEARCH_TOOL_NAME, isConnectionConfigurationError, parseQualifiedName } from "./connections.js";
|
|
5
5
|
import { resolvePositiveIntegerEnv } from "./env-config.js";
|
|
6
6
|
import { harnessPauseOutcome } from "./harness-continuation.js";
|
|
7
7
|
import { evalRunOptionsForRun } from "./eval-run-options.js";
|
|
8
8
|
import { isJsonObject, previewString, redactedToolInput, safeJson } from "./json-util.js";
|
|
9
|
+
import { runUsesChannelReplyForHumanInput } from "./human-input-routing.js";
|
|
9
10
|
import { prepareToolModelOutput } from "./model-media.js";
|
|
10
|
-
import { failRun } from "./run-outcome.js";
|
|
11
11
|
import { sandboxWriteByteLength } from "./resource-projection-util.js";
|
|
12
12
|
import { stringValue, timestamp, toolRequiresSandbox } from "./runtime-util.js";
|
|
13
13
|
import { applyCoreToolPolicy, filterVisibleToolSet } from "./security.js";
|
|
@@ -16,10 +16,13 @@ export function visibleToolSetImpl(host, defaultToolNames, activeSkills) {
|
|
|
16
16
|
void activeSkills;
|
|
17
17
|
return filterVisibleToolSet(defaultToolNames, host.coreToolPolicy);
|
|
18
18
|
}
|
|
19
|
-
export async function modelToolsImpl(host, activeToolNames, connectionRegistry, discoveredConnectionTools = new Map()) {
|
|
19
|
+
export async function modelToolsImpl(host, run, activeToolNames, connectionRegistry, discoveredConnectionTools = new Map(), options = {}) {
|
|
20
20
|
const tools = [];
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const surface = host.surfaceForRun(run);
|
|
22
|
+
for (const tool of runtimeToolsForSurface(surface.tools)) {
|
|
23
|
+
const active = activeToolNames.has(tool.name);
|
|
24
|
+
const deferred = options.includeDeferred === true && tool.visibility === "deferred";
|
|
25
|
+
if (!active && !deferred)
|
|
23
26
|
continue;
|
|
24
27
|
const policyTool = applyCoreToolPolicy(tool, host.coreToolPolicy);
|
|
25
28
|
if (!policyTool)
|
|
@@ -30,17 +33,21 @@ export async function modelToolsImpl(host, activeToolNames, connectionRegistry,
|
|
|
30
33
|
description: definition.description ?? policyTool.description,
|
|
31
34
|
inputSchema: definition.inputSchema ?? policyTool.inputSchema
|
|
32
35
|
};
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
// the deferred-tool bridge can hit any of those through the tool it
|
|
36
|
-
// routes to.
|
|
37
|
-
if (policyTool.name === ASK_QUESTION_TOOL_NAME ||
|
|
38
|
-
policyTool.name === TOOL_CALL_TOOL_NAME ||
|
|
39
|
-
normalizeApprovalPolicy(policyTool.needsApproval).mode === "always") {
|
|
36
|
+
// Approval-gated tools park the run and therefore serialize their batch.
|
|
37
|
+
if (normalizeApprovalPolicy(policyTool.needsApproval).mode === "always") {
|
|
40
38
|
descriptor.execution = "sequential";
|
|
41
39
|
}
|
|
40
|
+
if (!active) {
|
|
41
|
+
descriptor.deferLoading = true;
|
|
42
|
+
options.exposedDeferredToolNames?.add(policyTool.name);
|
|
43
|
+
}
|
|
42
44
|
tools.push(descriptor);
|
|
43
45
|
}
|
|
46
|
+
// connection_search is not part of the built-in tool catalog, so it cannot
|
|
47
|
+
// be selected by authored setup() (capability validation rejects unknown
|
|
48
|
+
// names) and this branch stays dormant today. tool_search is the model's
|
|
49
|
+
// discovery surface for connection tools, and the core `pair` tool is the
|
|
50
|
+
// discovery-independent binding path.
|
|
44
51
|
if (connectionRegistry?.hasLiveConnections() && activeToolNames.has(CONNECTION_SEARCH_TOOL_NAME)) {
|
|
45
52
|
tools.push({
|
|
46
53
|
name: CONNECTION_SEARCH_TOOL_NAME,
|
|
@@ -66,30 +73,74 @@ export async function modelToolsImpl(host, activeToolNames, connectionRegistry,
|
|
|
66
73
|
}
|
|
67
74
|
});
|
|
68
75
|
}
|
|
76
|
+
if (options.includeDeferred && connectionRegistry?.hasLiveConnections()) {
|
|
77
|
+
const catalog = await connectionRegistry.search({ keywords: "", limit: Number.MAX_SAFE_INTEGER });
|
|
78
|
+
for (const result of catalog) {
|
|
79
|
+
if (!result.qualifiedName || !result.tool || !result.inputSchema)
|
|
80
|
+
continue;
|
|
81
|
+
const metadata = {
|
|
82
|
+
connection: result.connection,
|
|
83
|
+
name: result.tool,
|
|
84
|
+
qualifiedName: result.qualifiedName,
|
|
85
|
+
description: result.description,
|
|
86
|
+
inputSchema: result.inputSchema
|
|
87
|
+
};
|
|
88
|
+
if (result.outputSchema)
|
|
89
|
+
metadata.outputSchema = result.outputSchema;
|
|
90
|
+
discoveredConnectionTools.set(result.qualifiedName, metadata);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
69
93
|
for (const [qualifiedName, metadata] of discoveredConnectionTools) {
|
|
70
|
-
|
|
94
|
+
const active = activeToolNames.has(qualifiedName);
|
|
95
|
+
if (!active && !options.includeDeferred)
|
|
71
96
|
continue;
|
|
72
|
-
|
|
97
|
+
const descriptor = {
|
|
73
98
|
name: qualifiedName,
|
|
74
99
|
description: metadata.description,
|
|
75
100
|
inputSchema: metadata.inputSchema,
|
|
101
|
+
external: {
|
|
102
|
+
namespace: metadata.connection,
|
|
103
|
+
name: metadata.name
|
|
104
|
+
},
|
|
76
105
|
// Connection tools can pause for authorization at any call.
|
|
77
106
|
execution: "sequential"
|
|
78
|
-
}
|
|
107
|
+
};
|
|
108
|
+
if (!active) {
|
|
109
|
+
descriptor.deferLoading = true;
|
|
110
|
+
options.exposedDeferredToolNames?.add(qualifiedName);
|
|
111
|
+
}
|
|
112
|
+
tools.push(descriptor);
|
|
79
113
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
114
|
+
const selectedSubagentNames = new Set(Array.isArray(run.input.agentSubagents)
|
|
115
|
+
? run.input.agentSubagents.filter((name) => typeof name === "string")
|
|
116
|
+
: []);
|
|
117
|
+
const selectedSubagents = surface.subagents
|
|
118
|
+
.filter((subagent) => selectedSubagentNames.has(subagent.name))
|
|
119
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
120
|
+
if (activeToolNames.has(DELEGATE_TOOL_NAME) && selectedSubagents.length > 0) {
|
|
121
|
+
const directory = selectedSubagents
|
|
122
|
+
.map((subagent) => `${subagent.name}: ${subagent.description}`)
|
|
123
|
+
.join("\n");
|
|
83
124
|
tools.push({
|
|
84
|
-
name:
|
|
85
|
-
description:
|
|
125
|
+
name: DELEGATE_TOOL_NAME,
|
|
126
|
+
description: `Delegate one self-contained task to an enabled immediate child. The child has no parent transcript, so include needed context and usable file paths; review its result before replying. Available agents:\n${directory}`,
|
|
86
127
|
inputSchema: {
|
|
87
128
|
type: "object",
|
|
88
129
|
properties: {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
130
|
+
agent: {
|
|
131
|
+
type: "string",
|
|
132
|
+
enum: selectedSubagents.map((subagent) => subagent.name),
|
|
133
|
+
description: "Exact child-agent name from the available-agent directory."
|
|
134
|
+
},
|
|
135
|
+
task: { type: "string", description: "Self-contained objective and required context." },
|
|
136
|
+
expectedOutput: { type: "string", description: "Required result or artifact." },
|
|
137
|
+
constraints: {
|
|
138
|
+
type: "array",
|
|
139
|
+
items: { type: "string" },
|
|
140
|
+
description: "Limits, authority, and confidentiality requirements."
|
|
141
|
+
}
|
|
92
142
|
},
|
|
143
|
+
required: ["agent", "task"],
|
|
93
144
|
additionalProperties: true
|
|
94
145
|
}
|
|
95
146
|
});
|
|
@@ -97,126 +148,142 @@ export async function modelToolsImpl(host, activeToolNames, connectionRegistry,
|
|
|
97
148
|
return tools;
|
|
98
149
|
}
|
|
99
150
|
export async function harnessExecuteToolImpl(host, call, state) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return harnessResult(
|
|
108
|
-
}
|
|
109
|
-
if (name === TOOL_SEARCH_TOOL_NAME) {
|
|
110
|
-
const outcome = await executeToolSearchTool(host, state.run(), {
|
|
111
|
-
connectionRegistry: state.connectionRegistry,
|
|
112
|
-
discoveredConnectionTools: state.discoveredConnectionTools
|
|
113
|
-
}, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
114
|
-
state.setRun(outcome.run);
|
|
115
|
-
return harnessResult(outcome.modelOutput, host.env);
|
|
116
|
-
}
|
|
117
|
-
if (name === TOOL_DESCRIBE_TOOL_NAME) {
|
|
118
|
-
const outcome = await executeToolDescribeTool(host, state.run(), {
|
|
119
|
-
connectionRegistry: state.connectionRegistry,
|
|
120
|
-
discoveredConnectionTools: state.discoveredConnectionTools
|
|
121
|
-
}, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
122
|
-
state.setRun(outcome.run);
|
|
123
|
-
return harnessResult(outcome.modelOutput, host.env);
|
|
151
|
+
// Tool calls may already be queued in a provider response when the operator
|
|
152
|
+
// cancels. Re-read the durable run before every tool boundary so no new side
|
|
153
|
+
// effect starts after cancellation became visible to the operator.
|
|
154
|
+
const durableRun = await host.state.getRun(state.run().id);
|
|
155
|
+
if (durableRun?.status === "cancelled" || durableRun?.controlIntent === "cancel") {
|
|
156
|
+
if (durableRun)
|
|
157
|
+
state.setRun(durableRun);
|
|
158
|
+
return harnessResult({ cancelled: true }, host.env);
|
|
124
159
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
160
|
+
const { toolCallId, name, input: params } = call;
|
|
161
|
+
const boundaryIdempotencyKey = `tool:${state.run().id}:${name}:${toolCallId}`;
|
|
162
|
+
try {
|
|
163
|
+
if (!state.defaultToolNames.has(name) && !state.exposedDeferredToolNames.has(name)) {
|
|
164
|
+
await host.state.appendEvent(state.run().id, "tool.unavailable", {
|
|
165
|
+
toolName: name,
|
|
166
|
+
reason: "not_enabled_for_run"
|
|
167
|
+
});
|
|
168
|
+
throw new Error(`Tool ${name} is not enabled for this run.`);
|
|
169
|
+
}
|
|
170
|
+
if (state.exposedDeferredToolNames.has(name))
|
|
171
|
+
state.defaultToolNames.add(name);
|
|
172
|
+
if (name === LOAD_SKILL_TOOL_NAME) {
|
|
173
|
+
const outcome = await executeLoadSkillTool(host, state.run(), {
|
|
174
|
+
sandboxHandle: state.sandboxHandle,
|
|
175
|
+
allowedSkills: state.activeSkills
|
|
176
|
+
}, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
177
|
+
state.setRun(outcome.run);
|
|
178
|
+
return harnessResult(outcome.modelOutput, host.env);
|
|
179
|
+
}
|
|
180
|
+
if (name === TOOL_SEARCH_TOOL_NAME) {
|
|
181
|
+
const outcome = await executeToolSearchTool(host, state.run(), {
|
|
182
|
+
connectionRegistry: state.connectionRegistry,
|
|
183
|
+
discoveredConnectionTools: state.discoveredConnectionTools,
|
|
184
|
+
activeToolNames: state.defaultToolNames
|
|
185
|
+
}, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
186
|
+
state.setRun(outcome.run);
|
|
187
|
+
return harnessResult(outcome.modelOutput, host.env);
|
|
188
|
+
}
|
|
189
|
+
if (name === DELEGATE_TOOL_NAME) {
|
|
190
|
+
if (!isJsonObject(params))
|
|
191
|
+
throw new Error(`${DELEGATE_TOOL_NAME} requires an object input.`);
|
|
192
|
+
const subagentName = stringValue(params.agent);
|
|
193
|
+
if (!subagentName)
|
|
194
|
+
throw new Error(`${DELEGATE_TOOL_NAME} requires agent.`);
|
|
195
|
+
if (!stringValue(params.task))
|
|
196
|
+
throw new Error(`${DELEGATE_TOOL_NAME} requires a non-empty task.`);
|
|
197
|
+
const task = { ...params };
|
|
198
|
+
delete task.agent;
|
|
199
|
+
const timeline = await host.runSubagent(state.run().id, subagentName, task);
|
|
200
|
+
return harnessResult({
|
|
201
|
+
runId: timeline.run.id,
|
|
202
|
+
status: timeline.run.status,
|
|
203
|
+
events: timeline.events.map((event) => ({ type: event.type, data: event.data })).slice(-8)
|
|
204
|
+
}, host.env);
|
|
205
|
+
}
|
|
206
|
+
if (name === PAIR_TOOL_NAME) {
|
|
207
|
+
const outcome = await executePairTool(host, state.run(), state.connectionRegistry, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
208
|
+
state.setRun(outcome.run);
|
|
209
|
+
return harnessResult(outcome.modelOutput, host.env);
|
|
210
|
+
}
|
|
211
|
+
if (name === CONNECTION_SEARCH_TOOL_NAME) {
|
|
212
|
+
const outcome = await executeConnectionSearchTool(host, state.run(), state.connectionRegistry, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
213
|
+
state.setRun(outcome.run);
|
|
214
|
+
for (const result of outcome.results) {
|
|
215
|
+
if (result.qualifiedName && result.tool && result.inputSchema) {
|
|
216
|
+
const metadata = {
|
|
217
|
+
connection: result.connection,
|
|
218
|
+
name: result.tool,
|
|
219
|
+
qualifiedName: result.qualifiedName,
|
|
220
|
+
description: result.description,
|
|
221
|
+
inputSchema: result.inputSchema
|
|
222
|
+
};
|
|
223
|
+
if (result.outputSchema)
|
|
224
|
+
metadata.outputSchema = result.outputSchema;
|
|
225
|
+
state.discoveredConnectionTools.set(result.qualifiedName, metadata);
|
|
226
|
+
state.defaultToolNames.add(result.qualifiedName);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return harnessResult(outcome.results, host.env);
|
|
230
|
+
}
|
|
231
|
+
if (parseQualifiedName(name)) {
|
|
232
|
+
const outcome = await executeConnectionTool(host, state.run(), state.connectionRegistry, name, params, false, `tool:${state.run().id}:${name}:${toolCallId}`, "return");
|
|
233
|
+
state.setRun(outcome.run);
|
|
234
|
+
if (outcome.waitingForApproval || outcome.waitingForConnection) {
|
|
235
|
+
const waiting = { run: outcome.run };
|
|
236
|
+
if (outcome.waitingForApproval !== undefined)
|
|
237
|
+
waiting.waitingForApproval = outcome.waitingForApproval;
|
|
238
|
+
if (outcome.waitingForConnection !== undefined)
|
|
239
|
+
waiting.waitingForConnection = outcome.waitingForConnection;
|
|
240
|
+
waiting.toolCallId = toolCallId;
|
|
241
|
+
waiting.toolName = name;
|
|
242
|
+
if (outcome.authorizationSessionId)
|
|
243
|
+
waiting.authorizationSessionId = outcome.authorizationSessionId;
|
|
244
|
+
state.setPause(waiting);
|
|
245
|
+
return harnessPauseOutcome(waiting);
|
|
246
|
+
}
|
|
247
|
+
return harnessResult(outcome.modelOutput ?? {}, host.env);
|
|
248
|
+
}
|
|
249
|
+
const compiledTool = runtimeToolsForSurface(host.surfaceForRun(state.run()).tools).find((candidate) => candidate.name === name);
|
|
250
|
+
if (!compiledTool) {
|
|
251
|
+
await host.state.appendEvent(state.run().id, "tool.unavailable", { toolName: name });
|
|
252
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
253
|
+
}
|
|
254
|
+
const outcome = await executeToolImpl(host, state.run(), compiledTool, params, state.sandboxHandle, false, `tool:${state.run().id}:${compiledTool.name}:${toolCallId}`, call.signal);
|
|
131
255
|
state.setRun(outcome.run);
|
|
132
|
-
if (outcome.waitingForApproval || outcome.waitingForInput
|
|
256
|
+
if (outcome.waitingForApproval || outcome.waitingForInput) {
|
|
133
257
|
const waiting = { run: outcome.run };
|
|
134
258
|
if (outcome.waitingForApproval !== undefined)
|
|
135
259
|
waiting.waitingForApproval = outcome.waitingForApproval;
|
|
136
260
|
if (outcome.waitingForInput !== undefined)
|
|
137
261
|
waiting.waitingForInput = outcome.waitingForInput;
|
|
138
|
-
if (outcome.waitingForConnection !== undefined)
|
|
139
|
-
waiting.waitingForConnection = outcome.waitingForConnection;
|
|
140
262
|
if (outcome.toolCallId)
|
|
141
263
|
waiting.toolCallId = outcome.toolCallId;
|
|
142
264
|
if (outcome.toolName)
|
|
143
265
|
waiting.toolName = outcome.toolName;
|
|
144
|
-
if (outcome.authorizationSessionId)
|
|
145
|
-
waiting.authorizationSessionId = outcome.authorizationSessionId;
|
|
146
|
-
state.setPause(waiting);
|
|
147
|
-
return harnessPauseOutcome(waiting);
|
|
148
|
-
}
|
|
149
|
-
return harnessResult(outcome.modelOutput ?? {}, host.env);
|
|
150
|
-
}
|
|
151
|
-
if (name.startsWith("delegate_")) {
|
|
152
|
-
const subagentName = name.slice("delegate_".length);
|
|
153
|
-
const task = isJsonObject(params) ? params : { task: String(params ?? "") };
|
|
154
|
-
const timeline = await host.runSubagent(state.run().id, subagentName, task);
|
|
155
|
-
return harnessResult({
|
|
156
|
-
runId: timeline.run.id,
|
|
157
|
-
status: timeline.run.status,
|
|
158
|
-
events: timeline.events.map((event) => ({ type: event.type, data: event.data })).slice(-8)
|
|
159
|
-
}, host.env);
|
|
160
|
-
}
|
|
161
|
-
if (name === CONNECTION_SEARCH_TOOL_NAME) {
|
|
162
|
-
const outcome = await executeConnectionSearchTool(host, state.run(), state.connectionRegistry, params, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
163
|
-
state.setRun(outcome.run);
|
|
164
|
-
for (const result of outcome.results) {
|
|
165
|
-
if (result.qualifiedName && result.tool && result.inputSchema) {
|
|
166
|
-
const metadata = {
|
|
167
|
-
connection: result.connection,
|
|
168
|
-
name: result.tool,
|
|
169
|
-
qualifiedName: result.qualifiedName,
|
|
170
|
-
description: result.description,
|
|
171
|
-
inputSchema: result.inputSchema
|
|
172
|
-
};
|
|
173
|
-
if (result.outputSchema)
|
|
174
|
-
metadata.outputSchema = result.outputSchema;
|
|
175
|
-
state.discoveredConnectionTools.set(result.qualifiedName, metadata);
|
|
176
|
-
state.defaultToolNames.add(result.qualifiedName);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return harnessResult(outcome.results, host.env);
|
|
180
|
-
}
|
|
181
|
-
if (parseQualifiedName(name)) {
|
|
182
|
-
const outcome = await executeConnectionTool(host, state.run(), state.connectionRegistry, name, params, false, `tool:${state.run().id}:${name}:${toolCallId}`);
|
|
183
|
-
state.setRun(outcome.run);
|
|
184
|
-
if (outcome.waitingForApproval || outcome.waitingForConnection) {
|
|
185
|
-
const waiting = { run: outcome.run };
|
|
186
|
-
if (outcome.waitingForApproval !== undefined)
|
|
187
|
-
waiting.waitingForApproval = outcome.waitingForApproval;
|
|
188
|
-
if (outcome.waitingForConnection !== undefined)
|
|
189
|
-
waiting.waitingForConnection = outcome.waitingForConnection;
|
|
190
|
-
waiting.toolCallId = toolCallId;
|
|
191
|
-
waiting.toolName = name;
|
|
192
|
-
if (outcome.authorizationSessionId)
|
|
193
|
-
waiting.authorizationSessionId = outcome.authorizationSessionId;
|
|
194
266
|
state.setPause(waiting);
|
|
195
267
|
return harnessPauseOutcome(waiting);
|
|
196
268
|
}
|
|
197
269
|
return harnessResult(outcome.modelOutput ?? {}, host.env);
|
|
198
270
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (outcome.toolName)
|
|
215
|
-
waiting.toolName = outcome.toolName;
|
|
216
|
-
state.setPause(waiting);
|
|
217
|
-
return harnessPauseOutcome(waiting);
|
|
271
|
+
catch (error) {
|
|
272
|
+
// One shared model-tool boundary catches failures that occur before a
|
|
273
|
+
// specialized executor can normalize them (sandbox acquisition, deferred
|
|
274
|
+
// activation preflight, connection approval resolution, delegation, or
|
|
275
|
+
// future dispatch branches). State persistence failures still escape naturally:
|
|
276
|
+
// if we cannot durably record this failure, the run cannot safely continue.
|
|
277
|
+
const run = state.run();
|
|
278
|
+
const existing = (await host.state.listToolCalls(run.id))
|
|
279
|
+
.filter((candidate) => candidate.idempotencyKey === boundaryIdempotencyKey
|
|
280
|
+
|| candidate.idempotencyKey.startsWith(`${boundaryIdempotencyKey}:`))
|
|
281
|
+
.at(-1);
|
|
282
|
+
const toolCall = existing ?? await recordRuntimeHandledToolStart(host, run, name, params, boundaryIdempotencyKey);
|
|
283
|
+
const failure = await failRuntimeHandledTool(host, run, toolCall, toolCall.toolName, error, isConnectionConfigurationError(error) ? { failureKind: "configuration_error" } : undefined);
|
|
284
|
+
state.setRun(failure.run);
|
|
285
|
+
return harnessResult(failure.modelOutput, host.env);
|
|
218
286
|
}
|
|
219
|
-
return harnessResult(outcome.modelOutput ?? {}, host.env);
|
|
220
287
|
}
|
|
221
288
|
function harnessResult(output, env) {
|
|
222
289
|
const prepared = prepareToolModelOutput(output, env);
|
|
@@ -224,31 +291,14 @@ function harnessResult(output, env) {
|
|
|
224
291
|
return { kind: "result", output: prepared.output };
|
|
225
292
|
return { kind: "result", output: prepared.output, media: prepared.media };
|
|
226
293
|
}
|
|
227
|
-
async function executeToolCallBridge(host, run, state, input, idempotencyKey, approved = false) {
|
|
228
|
-
const raw = isJsonObject(input) ? input : {};
|
|
229
|
-
const name = stringValue(raw.name);
|
|
230
|
-
const args = isJsonObject(raw.arguments) ? raw.arguments : isJsonObject(raw.input) ? raw.input : {};
|
|
231
|
-
if (!name)
|
|
232
|
-
throw new Error("tool_call requires name.");
|
|
233
|
-
if (CORE_HARNESS_TOOL_NAMES.includes(name)) {
|
|
234
|
-
throw new Error(`Core harness tool ${name} is already directly visible; call it directly.`);
|
|
235
|
-
}
|
|
236
|
-
if (parseQualifiedName(name)) {
|
|
237
|
-
return executeConnectionTool(host, run, state.connectionRegistry, name, args, approved, `${idempotencyKey}:${name}`);
|
|
238
|
-
}
|
|
239
|
-
const compiledTool = deferredLocalTools(host).find((tool) => tool.name === name);
|
|
240
|
-
if (!compiledTool)
|
|
241
|
-
throw new Error(`Deferred tool not found: ${name}`);
|
|
242
|
-
const outcome = await executeToolImpl(host, run, compiledTool, args, state.sandboxHandle, approved, `${idempotencyKey}:${name}`);
|
|
243
|
-
return { ...outcome, toolName: compiledTool.name };
|
|
244
|
-
}
|
|
245
294
|
export function selectToolImpl(host, options) {
|
|
246
295
|
if (options.toolName) {
|
|
247
|
-
|
|
296
|
+
const surface = options.existingRun ? host.surfaceForRun(options.existingRun) : undefined;
|
|
297
|
+
return runtimeToolsForSurface((surface?.tools ?? host.manifest.tools)).find((tool) => tool.name === options.toolName);
|
|
248
298
|
}
|
|
249
299
|
return undefined;
|
|
250
300
|
}
|
|
251
|
-
export async function executeToolImpl(host, run, tool, input, sandboxHandle, approved, idempotencyKey = `tool:${run.id}:${tool.name}
|
|
301
|
+
export async function executeToolImpl(host, run, tool, input, sandboxHandle, approved, idempotencyKey = `tool:${run.id}:${tool.name}`, signal) {
|
|
252
302
|
const policyTool = applyCoreToolPolicy(tool, host.coreToolPolicy);
|
|
253
303
|
if (!policyTool) {
|
|
254
304
|
await host.state.appendEvent(run.id, "tool.call_requested", { toolName: tool.name, input: redactedToolInput(input) });
|
|
@@ -256,37 +306,30 @@ export async function executeToolImpl(host, run, tool, input, sandboxHandle, app
|
|
|
256
306
|
runId: run.id,
|
|
257
307
|
toolName: tool.name,
|
|
258
308
|
status: "requested",
|
|
259
|
-
input:
|
|
309
|
+
input: safeJson(input),
|
|
260
310
|
idempotencyKey
|
|
261
311
|
});
|
|
262
|
-
return failRuntimeHandledTool(host, run, toolCall, tool.name, `Core tool ${tool.name} is disabled by the
|
|
312
|
+
return failRuntimeHandledTool(host, run, toolCall, tool.name, `Core tool ${tool.name} is disabled by the Assembly Line core tool policy.`);
|
|
263
313
|
}
|
|
264
314
|
tool = policyTool;
|
|
265
315
|
if (tool.name === TOOL_SEARCH_TOOL_NAME) {
|
|
266
316
|
return executeToolSearchTool(host, run, {
|
|
267
317
|
connectionRegistry: createConnectionRegistryForRunImpl(host, run, "local"),
|
|
268
|
-
discoveredConnectionTools: new Map()
|
|
318
|
+
discoveredConnectionTools: new Map(),
|
|
319
|
+
activeToolNames: new Set()
|
|
269
320
|
}, input, idempotencyKey);
|
|
270
321
|
}
|
|
271
|
-
if (tool.name ===
|
|
272
|
-
return
|
|
273
|
-
connectionRegistry: createConnectionRegistryForRunImpl(host, run, "local"),
|
|
274
|
-
discoveredConnectionTools: new Map()
|
|
275
|
-
}, input, idempotencyKey);
|
|
276
|
-
}
|
|
277
|
-
if (tool.name === TOOL_CALL_TOOL_NAME) {
|
|
278
|
-
return executeToolCallBridge(host, run, {
|
|
279
|
-
sandboxHandle,
|
|
280
|
-
connectionRegistry: createConnectionRegistryForRunImpl(host, run, "local", sandboxHandle),
|
|
281
|
-
discoveredConnectionTools: new Map()
|
|
282
|
-
}, input, idempotencyKey, approved);
|
|
322
|
+
if (tool.name === HISTORY_SEARCH_TOOL_NAME) {
|
|
323
|
+
return executeHistorySearchTool(host, run, input, idempotencyKey);
|
|
283
324
|
}
|
|
284
325
|
await host.state.appendEvent(run.id, "tool.call_requested", { toolName: tool.name, input: redactedToolInput(input) });
|
|
285
326
|
let toolCall = await host.state.createToolCall({
|
|
286
327
|
runId: run.id,
|
|
287
328
|
toolName: tool.name,
|
|
288
329
|
status: "requested",
|
|
289
|
-
|
|
330
|
+
// Raw, not redacted: approval resume re-executes this persisted input.
|
|
331
|
+
// Redaction happens at outward read boundaries (redactedToolCallRecord).
|
|
332
|
+
input: safeJson(input),
|
|
290
333
|
idempotencyKey
|
|
291
334
|
});
|
|
292
335
|
const approval = normalizeApprovalPolicy(tool.needsApproval);
|
|
@@ -303,7 +346,7 @@ export async function executeToolImpl(host, run, tool, input, sandboxHandle, app
|
|
|
303
346
|
toolName: tool.name,
|
|
304
347
|
source: "eval"
|
|
305
348
|
});
|
|
306
|
-
return executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, true);
|
|
349
|
+
return executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, true, signal);
|
|
307
350
|
}
|
|
308
351
|
if (approval.mode === "always" && !approved) {
|
|
309
352
|
toolCall = await host.state.updateToolCall(toolCall.id, { status: "waiting_for_approval" });
|
|
@@ -320,22 +363,34 @@ export async function executeToolImpl(host, run, tool, input, sandboxHandle, app
|
|
|
320
363
|
});
|
|
321
364
|
return { run: waitingRun, waitingForApproval: true, toolCallId: toolCall.id, toolName: tool.name };
|
|
322
365
|
}
|
|
323
|
-
return executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, approved);
|
|
366
|
+
return executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, approved, signal);
|
|
324
367
|
}
|
|
325
|
-
export async function executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, approvedToolCall = false) {
|
|
368
|
+
export async function executeToolWithRecordImpl(host, run, tool, toolCall, input, sandboxHandle, approvedToolCall = false, signal) {
|
|
326
369
|
await host.state.updateToolCall(toolCall.id, { status: "running" });
|
|
327
370
|
await host.state.appendEvent(run.id, "tool.execution_started", { toolCallId: toolCall.id, toolName: tool.name });
|
|
328
371
|
const toolSpanStartedAt = timestamp();
|
|
329
|
-
if (toolRequiresSandbox(tool)) {
|
|
330
|
-
await sandboxHandle.get();
|
|
331
|
-
}
|
|
332
|
-
const ctx = createToolContext(host, run, sandboxHandle, approvedToolCall);
|
|
333
372
|
try {
|
|
334
|
-
const
|
|
335
|
-
|
|
373
|
+
const workspaceTool = WORKSPACE_TOOL_NAMES.has(tool.name);
|
|
374
|
+
const definition = workspaceTool ? undefined : await host.loadTool(tool, run);
|
|
375
|
+
if (!workspaceTool && !definition?.execute)
|
|
336
376
|
throw new Error(`Tool ${tool.name} does not export execute().`);
|
|
337
|
-
const
|
|
338
|
-
|
|
377
|
+
const executed = await withToolTimeout(async () => {
|
|
378
|
+
// Acquisition, provider reconnect, filesystem hydration, credential
|
|
379
|
+
// projection, authored execution, and output conversion share one
|
|
380
|
+
// deadline. A sandbox provider can no longer wedge the tool boundary
|
|
381
|
+
// before its timer starts.
|
|
382
|
+
if (toolRequiresSandbox(tool))
|
|
383
|
+
await sandboxHandle.get();
|
|
384
|
+
const ctx = createToolContext(host, run, sandboxHandle, approvedToolCall);
|
|
385
|
+
const result = workspaceTool
|
|
386
|
+
? await host.executeWorkspaceTool(run, tool.name, input, sandboxHandle)
|
|
387
|
+
: await Promise.resolve(definition.execute(input, ctx));
|
|
388
|
+
const modelOutput = definition?.toModelOutput
|
|
389
|
+
? await definition.toModelOutput(result)
|
|
390
|
+
: boundModelOutput(result, host.toolOutputMaxChars);
|
|
391
|
+
return { result, modelOutput };
|
|
392
|
+
}, definition?.timeoutMs ?? host.toolTimeoutMs, tool.name, signal);
|
|
393
|
+
const { result, modelOutput } = executed;
|
|
339
394
|
await host.state.updateToolCall(toolCall.id, {
|
|
340
395
|
status: "completed",
|
|
341
396
|
result: safeJson(result),
|
|
@@ -368,7 +423,57 @@ export async function executeToolWithRecordImpl(host, run, tool, toolCall, input
|
|
|
368
423
|
return { run: await host.state.getRun(run.id) ?? run, modelOutput };
|
|
369
424
|
}
|
|
370
425
|
catch (error) {
|
|
426
|
+
if (error instanceof ToolOperationInterruptedError && !sandboxHandle.current()) {
|
|
427
|
+
sandboxHandle.abandonAcquisition();
|
|
428
|
+
}
|
|
371
429
|
if (error instanceof HumanInputRequired) {
|
|
430
|
+
if (runUsesChannelReplyForHumanInput(run)) {
|
|
431
|
+
const message = "This run accepts human input through its active channel, not by pausing the run.";
|
|
432
|
+
const modelOutput = {
|
|
433
|
+
error: message,
|
|
434
|
+
question: error.question,
|
|
435
|
+
options: safeJson(error.options ?? {}),
|
|
436
|
+
action: "Ask the question as your final response. The user's next channel message will continue the conversation.",
|
|
437
|
+
failure: {
|
|
438
|
+
kind: "channel_reply_required",
|
|
439
|
+
runCanContinue: true
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
await host.state.updateToolCall(toolCall.id, {
|
|
443
|
+
status: "failed",
|
|
444
|
+
error: message,
|
|
445
|
+
modelOutput
|
|
446
|
+
});
|
|
447
|
+
await host.state.appendEvent(run.id, "tool.execution_failed", {
|
|
448
|
+
toolCallId: toolCall.id,
|
|
449
|
+
toolName: tool.name,
|
|
450
|
+
error: message,
|
|
451
|
+
failureKind: "channel_reply_required",
|
|
452
|
+
recoverable: true
|
|
453
|
+
});
|
|
454
|
+
await host.state.appendEvent(run.id, "human_input.redirected_to_channel", {
|
|
455
|
+
toolCallId: toolCall.id,
|
|
456
|
+
toolName: tool.name,
|
|
457
|
+
question: error.question,
|
|
458
|
+
options: error.options ?? {}
|
|
459
|
+
});
|
|
460
|
+
await host.emitSpan("ai.toolCall", toolSpanStartedAt, host.runSpanAttributes(run, {
|
|
461
|
+
toolCallId: toolCall.id,
|
|
462
|
+
toolName: tool.name,
|
|
463
|
+
status: "failed",
|
|
464
|
+
error: message,
|
|
465
|
+
...host.toolContentAttributes(input, modelOutput)
|
|
466
|
+
}), {
|
|
467
|
+
parentSpanId: host.turnSpanId(run.id),
|
|
468
|
+
status: "error"
|
|
469
|
+
});
|
|
470
|
+
await host.emitSpan("assembly-line.tool", toolSpanStartedAt, {
|
|
471
|
+
runId: run.id,
|
|
472
|
+
toolName: tool.name,
|
|
473
|
+
status: "failed"
|
|
474
|
+
});
|
|
475
|
+
return { run: await host.state.getRun(run.id) ?? run, modelOutput };
|
|
476
|
+
}
|
|
372
477
|
await host.state.updateToolCall(toolCall.id, { status: "waiting_for_approval", error: error.message });
|
|
373
478
|
const waitingRun = await host.state.updateRun(run.id, { status: "waiting_for_input" });
|
|
374
479
|
await host.state.appendEvent(run.id, "human_input.requested", {
|
|
@@ -392,27 +497,14 @@ export async function executeToolWithRecordImpl(host, run, tool, toolCall, input
|
|
|
392
497
|
});
|
|
393
498
|
return { run: waitingRun, waitingForInput: true, toolCallId: toolCall.id, toolName: tool.name };
|
|
394
499
|
}
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
// empty /workspace or a first-run state file that doesn't exist yet.
|
|
401
|
-
// Authored tools throwing is a stronger signal (the agent's own code
|
|
402
|
-
// broke) and remains a run failure, so routine/trigger failure detection
|
|
403
|
-
// is unchanged. Terminal conditions (human input, approval, connection
|
|
404
|
-
// auth) are explicit cases above and never reach here.
|
|
500
|
+
// Every durably recordable model-invoked tool failure is returned to the
|
|
501
|
+
// model. RecoverableToolError classifies correctable input, but ordinary
|
|
502
|
+
// tool and infrastructure errors are also visible so the model can choose
|
|
503
|
+
// another action or explain the failure. State persistence failures still
|
|
504
|
+
// escape because continuing without a durable record is unsafe.
|
|
405
505
|
const message = error instanceof Error ? error.message : String(error);
|
|
406
|
-
await host
|
|
407
|
-
|
|
408
|
-
const recoverable = isBuiltInToolName(tool.name);
|
|
409
|
-
const nextRun = recoverable
|
|
410
|
-
? await host.state.getRun(run.id) ?? run
|
|
411
|
-
: await failRun({ state: host.state }, run.id, {
|
|
412
|
-
reason: "tool.execution_failed",
|
|
413
|
-
error: message,
|
|
414
|
-
data: { toolCallId: toolCall.id, toolName: tool.name }
|
|
415
|
-
});
|
|
506
|
+
const failure = await failRuntimeHandledTool(host, run, toolCall, tool.name, error);
|
|
507
|
+
const nextRun = failure.run;
|
|
416
508
|
await host.emitSpan("ai.toolCall", toolSpanStartedAt, host.runSpanAttributes(nextRun, {
|
|
417
509
|
toolCallId: toolCall.id,
|
|
418
510
|
toolName: tool.name,
|
|
@@ -428,44 +520,66 @@ export async function executeToolWithRecordImpl(host, run, tool, toolCall, input
|
|
|
428
520
|
toolName: tool.name,
|
|
429
521
|
status: "failed"
|
|
430
522
|
});
|
|
431
|
-
return { run: nextRun, modelOutput:
|
|
523
|
+
return { run: nextRun, modelOutput: failure.modelOutput };
|
|
432
524
|
}
|
|
433
525
|
}
|
|
526
|
+
const WORKSPACE_TOOL_NAMES = new Set([
|
|
527
|
+
FILES_SEARCH_TOOL_NAME,
|
|
528
|
+
FILES_MOUNT_TOOL_NAME,
|
|
529
|
+
WORKSPACE_SEARCH_TOOL_NAME,
|
|
530
|
+
WORKSPACE_STATUS_TOOL_NAME,
|
|
531
|
+
WORKSPACE_CHECKPOINT_CREATE_TOOL_NAME,
|
|
532
|
+
WORKSPACE_CHECKPOINT_LIST_TOOL_NAME,
|
|
533
|
+
WORKSPACE_CHECKPOINT_RESTORE_TOOL_NAME,
|
|
534
|
+
WORKSPACE_FORK_TOOL_NAME
|
|
535
|
+
]);
|
|
434
536
|
const DEFAULT_SHELL_TIMEOUT_MS = 30_000;
|
|
435
537
|
const DEFAULT_SHELL_TIMEOUT_MAX_MS = 600_000;
|
|
436
|
-
/** Clamp a (possibly model-supplied) shell timeout to [1s,
|
|
538
|
+
/** Clamp a (possibly model-supplied) shell timeout to [1s, ASSEMBLY_LINE_BASH_TIMEOUT_MAX_MS]; 0/negative/NaN fall to the default. */
|
|
437
539
|
export function clampShellTimeoutMs(requested, env) {
|
|
438
|
-
const max = resolvePositiveIntegerEnv(env.
|
|
540
|
+
const max = resolvePositiveIntegerEnv(env.ASSEMBLY_LINE_BASH_TIMEOUT_MAX_MS, DEFAULT_SHELL_TIMEOUT_MAX_MS);
|
|
439
541
|
if (typeof requested !== "number" || !Number.isFinite(requested) || requested <= 0) {
|
|
440
542
|
return Math.min(DEFAULT_SHELL_TIMEOUT_MS, max);
|
|
441
543
|
}
|
|
442
544
|
return Math.min(Math.max(Math.floor(requested), 1_000), max);
|
|
443
545
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
546
|
+
class ToolOperationInterruptedError extends Error {
|
|
547
|
+
}
|
|
548
|
+
/** Bound the complete runtime tool boundary and release its caller on cancel. */
|
|
549
|
+
function withToolTimeout(operation, timeoutMs, toolName, signal) {
|
|
550
|
+
if (signal?.aborted) {
|
|
551
|
+
return Promise.reject(new ToolOperationInterruptedError(`Tool ${toolName} was cancelled.`));
|
|
552
|
+
}
|
|
553
|
+
const pending = Promise.resolve().then(operation);
|
|
554
|
+
if (timeoutMs <= 0 && !signal)
|
|
555
|
+
return pending;
|
|
452
556
|
return new Promise((resolve, reject) => {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
557
|
+
let settled = false;
|
|
558
|
+
const finish = (callback) => {
|
|
559
|
+
if (settled)
|
|
560
|
+
return;
|
|
561
|
+
settled = true;
|
|
562
|
+
if (timer)
|
|
563
|
+
clearTimeout(timer);
|
|
564
|
+
signal?.removeEventListener("abort", onAbort);
|
|
565
|
+
callback();
|
|
566
|
+
};
|
|
567
|
+
const onAbort = () => finish(() => {
|
|
568
|
+
reject(new ToolOperationInterruptedError(`Tool ${toolName} was cancelled.`));
|
|
569
|
+
});
|
|
570
|
+
const timer = timeoutMs > 0 ? setTimeout(() => finish(() => {
|
|
571
|
+
reject(new ToolOperationInterruptedError(`Tool ${toolName} timed out after ${timeoutMs}ms.`));
|
|
572
|
+
}), timeoutMs) : undefined;
|
|
573
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
574
|
+
pending.then((value) => {
|
|
575
|
+
finish(() => resolve(value));
|
|
461
576
|
}, (error) => {
|
|
462
|
-
|
|
463
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
577
|
+
finish(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
464
578
|
});
|
|
465
579
|
});
|
|
466
580
|
}
|
|
467
581
|
export function wrapSandboxImpl(host, runId, session) {
|
|
468
|
-
|
|
582
|
+
const wrapped = {
|
|
469
583
|
...session,
|
|
470
584
|
readFile: async (path) => {
|
|
471
585
|
const contents = await session.readFile(path);
|
|
@@ -505,6 +619,14 @@ export function wrapSandboxImpl(host, runId, session) {
|
|
|
505
619
|
return result;
|
|
506
620
|
}
|
|
507
621
|
};
|
|
622
|
+
if (session.readFileBytes) {
|
|
623
|
+
wrapped.readFileBytes = async (path) => {
|
|
624
|
+
const contents = await session.readFileBytes(path);
|
|
625
|
+
await host.state.appendEvent(runId, "sandbox.file_read", { path, bytes: contents.byteLength });
|
|
626
|
+
return contents;
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
return wrapped;
|
|
508
630
|
}
|
|
509
631
|
async function ensureSandboxSyncObligation(host, runId, session, reason, metadata = {}) {
|
|
510
632
|
const run = await host.state.getRun(runId);
|
|
@@ -512,6 +634,31 @@ async function ensureSandboxSyncObligation(host, runId, session, reason, metadat
|
|
|
512
634
|
throw new Error(`Run not found for sandbox sync obligation: ${runId}`);
|
|
513
635
|
const sessionKey = host.sandboxSessionKey(run);
|
|
514
636
|
const existing = await host.state.getSandboxSession(sessionKey);
|
|
637
|
+
const workspaceId = stringValue(existing?.manifest.workspaceId)?.trim();
|
|
638
|
+
const baseVersionId = existing?.manifest.baseVersionId;
|
|
639
|
+
const hasBaseVersionId = baseVersionId === null || typeof baseVersionId === "string";
|
|
640
|
+
if (!workspaceId || !hasBaseVersionId) {
|
|
641
|
+
const missing = [
|
|
642
|
+
...(!workspaceId ? ["workspaceId"] : []),
|
|
643
|
+
...(!hasBaseVersionId ? ["baseVersionId"] : [])
|
|
644
|
+
];
|
|
645
|
+
const error = `Sandbox is not fully hydrated; refusing ${reason} before creating an invalid sync obligation (missing ${missing.join(", ")}).`;
|
|
646
|
+
await host.state.appendEvent(runId, "sandbox.sync_obligation_rejected", {
|
|
647
|
+
sandboxId: session.id,
|
|
648
|
+
sessionKey,
|
|
649
|
+
reason,
|
|
650
|
+
missing,
|
|
651
|
+
metadata
|
|
652
|
+
});
|
|
653
|
+
throw new Error(error);
|
|
654
|
+
}
|
|
655
|
+
const sessionManifest = {
|
|
656
|
+
...existing?.manifest,
|
|
657
|
+
roots: ["/memory", "/skills", "/workspace"],
|
|
658
|
+
sandboxRoot: session.root,
|
|
659
|
+
...sandboxFilesystemContractMetadata(session.provider === "local" ? "emulated" : "physical")
|
|
660
|
+
};
|
|
661
|
+
const syncManifest = { ...sessionManifest, sessionRecordKey: sessionKey };
|
|
515
662
|
const syncJob = await host.state.enqueueSandboxSyncJob({
|
|
516
663
|
runId,
|
|
517
664
|
sandboxId: session.id,
|
|
@@ -519,13 +666,7 @@ async function ensureSandboxSyncObligation(host, runId, session, reason, metadat
|
|
|
519
666
|
idempotencyKey: `sandbox-sync:${runId}:${session.id}`,
|
|
520
667
|
reason,
|
|
521
668
|
maxAttempts: host.sandboxSyncMaxAttempts,
|
|
522
|
-
manifest:
|
|
523
|
-
...(existing?.manifest ?? {}),
|
|
524
|
-
roots: ["/memory", "/skills", "/workspace"],
|
|
525
|
-
sandboxRoot: session.root,
|
|
526
|
-
sessionKey,
|
|
527
|
-
...sandboxFilesystemContractMetadata(session.provider === "local" ? "emulated" : "physical")
|
|
528
|
-
},
|
|
669
|
+
manifest: syncManifest,
|
|
529
670
|
metadata
|
|
530
671
|
});
|
|
531
672
|
await host.state.updateSandboxSession(sessionKey, {
|
|
@@ -535,13 +676,7 @@ async function ensureSandboxSyncObligation(host, runId, session, reason, metadat
|
|
|
535
676
|
dirty: true,
|
|
536
677
|
lastSeenAt: timestamp(),
|
|
537
678
|
syncJobId: syncJob.id,
|
|
538
|
-
manifest:
|
|
539
|
-
...(existing?.manifest ?? {}),
|
|
540
|
-
roots: ["/memory", "/skills", "/workspace"],
|
|
541
|
-
sandboxRoot: session.root,
|
|
542
|
-
sessionKey,
|
|
543
|
-
...sandboxFilesystemContractMetadata(session.provider === "local" ? "emulated" : "physical")
|
|
544
|
-
}
|
|
679
|
+
manifest: sessionManifest
|
|
545
680
|
}).catch(async () => {
|
|
546
681
|
await host.state.upsertSandboxSession({
|
|
547
682
|
sessionKey,
|
|
@@ -552,12 +687,7 @@ async function ensureSandboxSyncObligation(host, runId, session, reason, metadat
|
|
|
552
687
|
dirty: true,
|
|
553
688
|
lastSeenAt: timestamp(),
|
|
554
689
|
syncJobId: syncJob.id,
|
|
555
|
-
manifest:
|
|
556
|
-
roots: ["/memory", "/skills", "/workspace"],
|
|
557
|
-
sandboxRoot: session.root,
|
|
558
|
-
sessionKey,
|
|
559
|
-
...sandboxFilesystemContractMetadata(session.provider === "local" ? "emulated" : "physical")
|
|
560
|
-
}
|
|
690
|
+
manifest: sessionManifest
|
|
561
691
|
});
|
|
562
692
|
});
|
|
563
693
|
await host.state.appendEvent(runId, "sandbox.sync_obligation", {
|