@tangle-network/agent-runtime 0.317.0 → 0.319.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{activation-CvdE2HIU.js → activation-ClcJ6wO1.js} +3 -3
- package/dist/{activation-CvdE2HIU.js.map → activation-ClcJ6wO1.js.map} +1 -1
- package/dist/{activation-BFDmjaKP.d.ts → activation-OColGsfd.d.ts} +2 -2
- package/dist/agent.d.ts +3 -3
- package/dist/agent.js +3 -3
- package/dist/{bundle-RgHpAFDY.js → bundle-Cw-QdGmH.js} +2 -2
- package/dist/{bundle-RgHpAFDY.js.map → bundle-Cw-QdGmH.js.map} +1 -1
- package/dist/candidate-execution/index.d.ts +40 -3
- package/dist/candidate-execution/index.js +86 -7
- package/dist/candidate-execution/index.js.map +1 -1
- package/dist/{coordination-driver-DGhN8GO9.js → coordination-driver-Culvomn2.js} +3 -3
- package/dist/{coordination-driver-DGhN8GO9.js.map → coordination-driver-Culvomn2.js.map} +1 -1
- package/dist/{delegate-B5pmSbQa.js → delegate-CpMbpiIR.js} +2 -2
- package/dist/{delegate-B5pmSbQa.js.map → delegate-CpMbpiIR.js.map} +1 -1
- package/dist/durable.d.ts +1 -1
- package/dist/durable.js +4 -4
- package/dist/{graph-G0j1ysqe.js → graph-DnfSGUM8.js} +5 -5
- package/dist/{graph-G0j1ysqe.js.map → graph-DnfSGUM8.js.map} +1 -1
- package/dist/graph-registry-BuJbzTzF.js +211 -0
- package/dist/graph-registry-BuJbzTzF.js.map +1 -0
- package/dist/{improvement-cycle-D7yR6GC2.js → improvement-cycle-xnQwUaC3.js} +7 -7
- package/dist/{improvement-cycle-D7yR6GC2.js.map → improvement-cycle-xnQwUaC3.js.map} +1 -1
- package/dist/{index-CUh40yUJ.d.ts → index-Da7w2H86.d.ts} +351 -132
- package/dist/index.d.ts +5 -5
- package/dist/index.js +10 -10
- package/dist/intelligence.d.ts +4 -4
- package/dist/intelligence.js +7 -7
- package/dist/kernel.d.ts +3 -2
- package/dist/kernel.js +12 -11
- package/dist/{loop-runner-bin-DQKLUt0l.d.ts → loop-runner-bin-CbBoLC9D.d.ts} +2 -2
- package/dist/{loop-runner-bin-CFVX4oi0.js → loop-runner-bin-uoeGHNZA.js} +3 -3
- package/dist/{loop-runner-bin-CFVX4oi0.js.map → loop-runner-bin-uoeGHNZA.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +6 -6
- package/dist/{model-policy-DhvyZ8-O.js → model-policy-CNe257pB.js} +37 -2
- package/dist/model-policy-CNe257pB.js.map +1 -0
- package/dist/{openai-tools-u3gWBi3x.d.ts → openai-tools-Cu9E1Bda.d.ts} +2 -2
- package/dist/placement.d.ts +1 -1
- package/dist/{prepare-CD9kR0gS.js → prepare-DjCLEN-q.js} +3 -3
- package/dist/prepare-DjCLEN-q.js.map +1 -0
- package/dist/{profile-CHXYmpGd.js → profile-DmVM4Gxb.js} +9 -2
- package/dist/profile-DmVM4Gxb.js.map +1 -0
- package/dist/{profile-materialization-Cca615eu.d.ts → profile-materialization-C5-t3HJ7.d.ts} +14 -3
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/{protected-model-port-C9QtEf3y.d.ts → protected-model-port-CQg2gstJ.d.ts} +3 -3
- package/dist/{protected-model-port-B0pHd65J.js → protected-model-port-D1fcnYdj.js} +4 -4
- package/dist/{protected-model-port-B0pHd65J.js.map → protected-model-port-D1fcnYdj.js.map} +1 -1
- package/dist/{provision-supervisor-BQLLrUtn.js → provision-supervisor-DiZTjzdp.js} +5 -5
- package/dist/{provision-supervisor-BQLLrUtn.js.map → provision-supervisor-DiZTjzdp.js.map} +1 -1
- package/dist/{runtime-B9BOFyEp.js → runtime-6qzuLTJ7.js} +514 -277
- package/dist/runtime-6qzuLTJ7.js.map +1 -0
- package/dist/{search-executor-B5ZVFsDV.js → search-executor-DlaLafvy.js} +4 -4
- package/dist/{search-executor-B5ZVFsDV.js.map → search-executor-DlaLafvy.js.map} +1 -1
- package/dist/{server-TwpH9aik.js → server-sLrmWqKw.js} +4 -4
- package/dist/{server-TwpH9aik.js.map → server-sLrmWqKw.js.map} +1 -1
- package/dist/{supervise-CU6AuxWY.js → supervise-D4CnC-cl.js} +5 -5
- package/dist/{supervise-CU6AuxWY.js.map → supervise-D4CnC-cl.js.map} +1 -1
- package/dist/{supervisor-CbFyf48U.js → supervisor-Cqhu3xH-.js} +709 -80
- package/dist/supervisor-Cqhu3xH-.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +14 -14
- package/dist/tool-loop.d.ts +5 -1
- package/dist/tool-loop.js +4 -3
- package/dist/tool-loop.js.map +1 -1
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/workspace-store/index.d.ts +171 -3
- package/dist/workspace-store/index.js +529 -8
- package/dist/workspace-store/index.js.map +1 -1
- package/dist/{workspace-streams-DkijayqX.js → workspace-streams-DFAhW7hF.js} +300 -42
- package/dist/workspace-streams-DFAhW7hF.js.map +1 -0
- package/dist/{workspace-streams-CpSmt3zx.d.ts → workspace-streams-U6_UfOXu.d.ts} +10 -2
- package/package.json +15 -11
- package/skills/agent-graphs/references/authoring.md +7 -0
- package/skills/codemode/SKILL.md +6 -4
- package/skills/codemode/references/runtime-execution.md +63 -11
- package/skills/graph-designer/SKILL.md +57 -0
- package/skills/profile-authoring/SKILL.md +17 -15
- package/dist/model-policy-DhvyZ8-O.js.map +0 -1
- package/dist/prepare-CD9kR0gS.js.map +0 -1
- package/dist/profile-CHXYmpGd.js.map +0 -1
- package/dist/runtime-B9BOFyEp.js.map +0 -1
- package/dist/supervisor-CbFyf48U.js.map +0 -1
- package/dist/workspace-streams-DkijayqX.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { c as RetainedInteractiveAdmissionError, d as RetainedRunDispatchBindingError, f as RuntimeRunStateError, i as ConfigError, l as RetainedInteractiveBindingError, m as ValidationError$1, r as BackendTransportError, t as AgentEvalError$1, u as RetainedRunAdmissionError } from "./errors-DodWX-cb.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as promptCacheTokenClasses, Ct as checkInIdleMs, Dt as teardownSurfaces, Et as teardownExecutor, F as deepFreezeCandidate, G as cloneTokenUsage, H as addTokenUsage, J as fnv1a32Hex, K as deleteBoxSafe, Q as mapWithConcurrency, St as boundedChildDeadlineAt, Tt as singleFlightTeardown, U as chargedTokens, V as addSpend, W as cloneSpend, Y as hasCompleteCacheBreakdown, Z as isAsyncIterable$1, a as verifyAgentCandidateWorkspaceArtifacts, at as throwAbort, bt as ROOT_DEADLINE_REASON, ct as withTimeout, dt as addResourceSpend, et as randomSuffix, ft as assertResources, gt as CHILD_DEADLINE_REASON, ht as ACCEPTED_RESULT_GRACE_MS, i as readAgentCandidateWorkspaceArtifactFiles, it as stringifySafe, j as verifiedArtifactChunks, k as verifyWorkspaceSnapshotArtifacts, lt as zeroSpend, mt as withBudgetResources, nt as roundBoxMinutes, o as verifyAgentCandidateWorkspaceTree, ot as throwIfAborted, pt as resourceTelemetry, q as errorMessage, rt as sleep, st as unmeteredSpend, tt as randomUuid, u as verifyAgentCandidateWorkspaceArchive, ut as zeroTokenUsage, wt as isDeadlineAbortReason, xt as armDeadlineTimer } from "./workspace-streams-DFAhW7hF.js";
|
|
3
3
|
import { runTaskQueue } from "./task-queue.js";
|
|
4
|
-
import { _ as agentHarness, a as concreteProfileModel, c as profileModelExecutionSettings, d as assertRouterAutoDeclaration, f as assertRouterAutoResponse, g as observedModelMatchesDeclared, h as observedModelHasSnapshot, l as profileProviderModel, m as mergeObservedModelIdentity, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-
|
|
4
|
+
import { _ as agentHarness, a as concreteProfileModel, c as profileModelExecutionSettings, d as assertRouterAutoDeclaration, f as assertRouterAutoResponse, g as observedModelMatchesDeclared, h as observedModelHasSnapshot, l as profileProviderModel, m as mergeObservedModelIdentity, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-CNe257pB.js";
|
|
5
5
|
import { n as assertNoSymlinkDescendant, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
|
|
6
6
|
import { i as notifyRuntimeHookEvent } from "./runtime-hooks-tXpAarhW.js";
|
|
7
|
-
import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestSchema, AgentTurnInputSchema, AgentTurnResultSchema, CanonicalStreamEventSchema, ContextTransferRequestSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, REASONING_EFFORTS, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentCandidateArtifactRefSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, agentRunCancellationAcknowledgementMatchesRequest, agentRunCancellationRequestDigest, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalWorkspaceCwd, exactAgentInteractiveSessionStart, harnessTypeSchema, nativeContextContinuationTurnDigest, nativeReasoningControl, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema, workspaceCheckpointRequestDigest, workspaceCheckpointResultMatchesRequest, workspaceCleanupAcknowledgementMatches, workspaceCleanupRequestDigest, workspaceForkRequestDigest, workspaceForkResultMatchesRequest } from "@tangle-network/agent-interface";
|
|
7
|
+
import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestSchema, AgentTurnInputSchema, AgentTurnResultSchema, CanonicalStreamEventSchema, ContextTransferReceiptSchema, ContextTransferRequestSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, REASONING_EFFORTS, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentCandidateArtifactRefSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, agentRunCancellationAcknowledgementMatchesRequest, agentRunCancellationRequestDigest, agentWorkspaceSnapshotRefDigest, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalWorkspaceCwd, contextTransferReceiptMatches, exactAgentInteractiveSessionStart, harnessTypeSchema, nativeContextContinuationTurnDigest, nativeReasoningControl, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema, workspaceCheckpointRequestDigest, workspaceCheckpointResultMatchesRequest, workspaceCleanupAcknowledgementMatches, workspaceCleanupRequestDigest, workspaceForkRequestDigest, workspaceForkResultMatchesRequest } from "@tangle-network/agent-interface";
|
|
8
8
|
import { isToolSpan, toolSpansToTraceAnalysisStore } from "@tangle-network/agent-eval";
|
|
9
9
|
import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
|
|
10
10
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
@@ -4650,10 +4650,10 @@ function createOtelExporter(config) {
|
|
|
4650
4650
|
if (!resolvedEndpoint) return void 0;
|
|
4651
4651
|
const url = `${resolvedEndpoint.replace(/\/+$/, "")}/v1/traces`;
|
|
4652
4652
|
const headers = config?.headers ?? parseHeadersFromEnv();
|
|
4653
|
-
const batchSize = positiveInteger(config?.batchSize, 64);
|
|
4653
|
+
const batchSize = positiveInteger$1(config?.batchSize, 64);
|
|
4654
4654
|
const flushIntervalMs = config?.flushIntervalMs ?? 5e3;
|
|
4655
|
-
const maxQueueSize = Math.max(positiveInteger(config?.maxQueueSize, 2048), batchSize);
|
|
4656
|
-
const timeoutMs = positiveInteger(config?.timeoutMs, 1e4);
|
|
4655
|
+
const maxQueueSize = Math.max(positiveInteger$1(config?.maxQueueSize, 2048), batchSize);
|
|
4656
|
+
const timeoutMs = positiveInteger$1(config?.timeoutMs, 1e4);
|
|
4657
4657
|
const resource = { attributes: toOtelAttributes({
|
|
4658
4658
|
"service.name": config?.serviceName ?? "agent-runtime",
|
|
4659
4659
|
...config?.resourceAttributes ?? {}
|
|
@@ -4802,7 +4802,7 @@ function describeFetchError(error) {
|
|
|
4802
4802
|
const code = cause && typeof cause === "object" && "code" in cause && typeof cause.code === "string" ? cause.code : void 0;
|
|
4803
4803
|
return code ? `${error.message} (${code})` : error.message;
|
|
4804
4804
|
}
|
|
4805
|
-
function positiveInteger(value, fallback) {
|
|
4805
|
+
function positiveInteger$1(value, fallback) {
|
|
4806
4806
|
return value !== void 0 && Number.isSafeInteger(value) && value > 0 ? value : fallback;
|
|
4807
4807
|
}
|
|
4808
4808
|
/**
|
|
@@ -5866,6 +5866,270 @@ function priceTokens(work) {
|
|
|
5866
5866
|
return Math.max(0, work.inputTokens - cacheRead - cacheWrite) * price.input + cacheRead * (price.cachedInput ?? price.input) + cacheWrite * (price.cacheWrite ?? price.input) + work.outputTokens * price.output;
|
|
5867
5867
|
}
|
|
5868
5868
|
//#endregion
|
|
5869
|
+
//#region src/runtime/code-mode.ts
|
|
5870
|
+
function positiveInteger(value, fallback, name) {
|
|
5871
|
+
const result = value ?? fallback;
|
|
5872
|
+
if (!Number.isSafeInteger(result) || result < 1) throw new RangeError(`code mode: ${name} must be a positive safe integer`);
|
|
5873
|
+
return result;
|
|
5874
|
+
}
|
|
5875
|
+
/** Render the same tool descriptors that are executed, including their result schemas. */
|
|
5876
|
+
async function describeCodeModeTools(tools, query) {
|
|
5877
|
+
const needle = query?.trim().toLowerCase();
|
|
5878
|
+
const selected = tools.filter((tool) => !needle || tool.name.toLowerCase().includes(needle) || tool.description?.toLowerCase().includes(needle));
|
|
5879
|
+
const { renderDeclarations } = await import("@earendil-works/pi-codemode");
|
|
5880
|
+
return renderDeclarations({ tools: selected.map((tool) => ({
|
|
5881
|
+
name: tool.name,
|
|
5882
|
+
description: tool.description,
|
|
5883
|
+
inputSchema: tool.inputSchema,
|
|
5884
|
+
outputSchema: tool.outputSchema,
|
|
5885
|
+
execute: () => {
|
|
5886
|
+
throw new Error("Declaration-only tool");
|
|
5887
|
+
}
|
|
5888
|
+
})) });
|
|
5889
|
+
}
|
|
5890
|
+
/**
|
|
5891
|
+
* Execute a JS async-function body against Runtime capabilities. The upstream
|
|
5892
|
+
* QuickJS/WASM worker is the boundary; there is no node:vm or unsafe fallback.
|
|
5893
|
+
* Every invocation has a fresh VM. Only successful storeWrites may be committed
|
|
5894
|
+
* by the caller. External tool effects are neither transactional nor retried.
|
|
5895
|
+
*/
|
|
5896
|
+
async function runCodeMode(code, options) {
|
|
5897
|
+
if (typeof code !== "string" || !code.trim()) throw new TypeError("code mode: source is required");
|
|
5898
|
+
options.signal?.throwIfAborted();
|
|
5899
|
+
if (!options.callId.trim()) throw new TypeError("code mode: callId is required");
|
|
5900
|
+
const concurrency = positiveInteger(options.concurrency, 4, "concurrency");
|
|
5901
|
+
const maxCalls = positiveInteger(options.maxCalls, 1024, "maxCalls");
|
|
5902
|
+
const memoryLimitBytes = positiveInteger(options.memoryLimitBytes, 64 * 1024 * 1024, "memoryLimitBytes");
|
|
5903
|
+
const timeoutMs = options.timeoutMs === Infinity ? Infinity : positiveInteger(options.timeoutMs, 3e5, "timeoutMs");
|
|
5904
|
+
if (timeoutMs !== Infinity && timeoutMs > 2147483647) throw new RangeError("code mode: timeoutMs must be at most 2147483647 or Infinity");
|
|
5905
|
+
const { CodemodeSandbox, toCodemodeIdentifier } = await import("@earendil-works/pi-codemode");
|
|
5906
|
+
const names = /* @__PURE__ */ new Set();
|
|
5907
|
+
const identifiers = /* @__PURE__ */ new Set();
|
|
5908
|
+
for (const tool of options.tools) {
|
|
5909
|
+
if (!tool.name || names.has(tool.name)) throw new TypeError(`code mode: duplicate or empty tool ${tool.name}`);
|
|
5910
|
+
names.add(tool.name);
|
|
5911
|
+
const identifier = toCodemodeIdentifier(tool.name);
|
|
5912
|
+
if (identifiers.has(identifier)) throw new TypeError(`code mode: ambiguous tool name ${tool.name} normalizes to ${identifier}`);
|
|
5913
|
+
identifiers.add(identifier);
|
|
5914
|
+
}
|
|
5915
|
+
const callLimit = new AbortController();
|
|
5916
|
+
const executionSignal = options.signal ? AbortSignal.any([options.signal, callLimit.signal]) : callLimit.signal;
|
|
5917
|
+
const queue = new CallQueue(concurrency);
|
|
5918
|
+
let ordinal = 0;
|
|
5919
|
+
const sandbox = new CodemodeSandbox({
|
|
5920
|
+
tools: options.tools.map((tool) => ({
|
|
5921
|
+
name: tool.name,
|
|
5922
|
+
description: tool.description,
|
|
5923
|
+
inputSchema: tool.inputSchema,
|
|
5924
|
+
outputSchema: tool.outputSchema,
|
|
5925
|
+
execute: async (args, { signal }) => {
|
|
5926
|
+
signal.throwIfAborted();
|
|
5927
|
+
const index = ++ordinal;
|
|
5928
|
+
if (index > maxCalls) {
|
|
5929
|
+
const error = /* @__PURE__ */ new Error(`code mode: call limit ${maxCalls} exceeded`);
|
|
5930
|
+
callLimit.abort(error);
|
|
5931
|
+
throw error;
|
|
5932
|
+
}
|
|
5933
|
+
const release = await queue.acquire(signal);
|
|
5934
|
+
try {
|
|
5935
|
+
signal.throwIfAborted();
|
|
5936
|
+
const value = await tool.execute(args, Object.freeze({
|
|
5937
|
+
signal,
|
|
5938
|
+
parentCallId: options.callId,
|
|
5939
|
+
callId: `${options.callId}/tool/${index}`
|
|
5940
|
+
}));
|
|
5941
|
+
signal.throwIfAborted();
|
|
5942
|
+
return value;
|
|
5943
|
+
} finally {
|
|
5944
|
+
release();
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
})),
|
|
5948
|
+
timeoutMs,
|
|
5949
|
+
memoryLimitBytes,
|
|
5950
|
+
...options.wasm === void 0 ? {} : { wasm: options.wasm },
|
|
5951
|
+
...options.workerUrl === void 0 ? {} : { workerUrl: options.workerUrl }
|
|
5952
|
+
});
|
|
5953
|
+
try {
|
|
5954
|
+
return await sandbox.execute(code, {
|
|
5955
|
+
signal: executionSignal,
|
|
5956
|
+
store: options.store
|
|
5957
|
+
});
|
|
5958
|
+
} finally {
|
|
5959
|
+
await sandbox.close();
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
/** A per-invocation FIFO, not another scheduler. Aborted waiters never dispatch. */
|
|
5963
|
+
var CallQueue = class {
|
|
5964
|
+
active = 0;
|
|
5965
|
+
waiting = [];
|
|
5966
|
+
concurrency;
|
|
5967
|
+
constructor(concurrency) {
|
|
5968
|
+
this.concurrency = concurrency;
|
|
5969
|
+
}
|
|
5970
|
+
acquire(signal) {
|
|
5971
|
+
signal.throwIfAborted();
|
|
5972
|
+
if (this.active < this.concurrency) {
|
|
5973
|
+
this.active++;
|
|
5974
|
+
return Promise.resolve(this.release());
|
|
5975
|
+
}
|
|
5976
|
+
return new Promise((resolve, reject) => {
|
|
5977
|
+
const waiter = {
|
|
5978
|
+
signal,
|
|
5979
|
+
resolve,
|
|
5980
|
+
reject,
|
|
5981
|
+
abort: () => {}
|
|
5982
|
+
};
|
|
5983
|
+
waiter.abort = () => {
|
|
5984
|
+
const index = this.waiting.indexOf(waiter);
|
|
5985
|
+
if (index !== -1) this.waiting.splice(index, 1);
|
|
5986
|
+
reject(signal.reason);
|
|
5987
|
+
};
|
|
5988
|
+
signal.addEventListener("abort", waiter.abort, { once: true });
|
|
5989
|
+
this.waiting.push(waiter);
|
|
5990
|
+
if (signal.aborted) waiter.abort();
|
|
5991
|
+
});
|
|
5992
|
+
}
|
|
5993
|
+
release() {
|
|
5994
|
+
let released = false;
|
|
5995
|
+
return () => {
|
|
5996
|
+
if (released) return;
|
|
5997
|
+
released = true;
|
|
5998
|
+
this.active--;
|
|
5999
|
+
for (;;) {
|
|
6000
|
+
const next = this.waiting.shift();
|
|
6001
|
+
if (!next) return;
|
|
6002
|
+
next.signal.removeEventListener("abort", next.abort);
|
|
6003
|
+
if (next.signal.aborted) {
|
|
6004
|
+
next.reject(next.signal.reason);
|
|
6005
|
+
continue;
|
|
6006
|
+
}
|
|
6007
|
+
this.active++;
|
|
6008
|
+
next.resolve(this.release());
|
|
6009
|
+
return;
|
|
6010
|
+
}
|
|
6011
|
+
};
|
|
6012
|
+
}
|
|
6013
|
+
};
|
|
6014
|
+
/**
|
|
6015
|
+
* Present an existing authorized tool set as code mode. This is used by Runtime's
|
|
6016
|
+
* existing loops; it does not execute a model, create an agent, or grant authority.
|
|
6017
|
+
* One toolset belongs to one conversation. Concurrent programs are refused to
|
|
6018
|
+
* avoid silently losing store writes; concurrency within a program is queued.
|
|
6019
|
+
*/
|
|
6020
|
+
function createCodeModeTools(granted, options = {}) {
|
|
6021
|
+
const reserved = /* @__PURE__ */ new Set(["codemode", "tool_search"]);
|
|
6022
|
+
const names = /* @__PURE__ */ new Set();
|
|
6023
|
+
for (const tool of granted) {
|
|
6024
|
+
if (reserved.has(tool.name)) throw new TypeError(`code mode: ${tool.name} is already present; use the existing code mode, do not nest it`);
|
|
6025
|
+
if (!tool.name || names.has(tool.name)) throw new TypeError(`code mode: duplicate or empty tool ${tool.name}`);
|
|
6026
|
+
names.add(tool.name);
|
|
6027
|
+
}
|
|
6028
|
+
const direct = new Set(options.directTools ?? []);
|
|
6029
|
+
for (const name of direct) if (!names.has(name)) throw new TypeError(`code mode: direct tool ${name} is not granted`);
|
|
6030
|
+
const copied = granted.map((tool) => Object.freeze({
|
|
6031
|
+
...tool,
|
|
6032
|
+
...tool.inputSchema === void 0 ? {} : { inputSchema: structuredClone(tool.inputSchema) },
|
|
6033
|
+
...tool.outputSchema === void 0 ? {} : { outputSchema: structuredClone(tool.outputSchema) }
|
|
6034
|
+
}));
|
|
6035
|
+
const callable = Object.freeze(copied.filter((tool) => !direct.has(tool.name)));
|
|
6036
|
+
let store = structuredClone(options.store ?? {});
|
|
6037
|
+
let running = false;
|
|
6038
|
+
const tools = [
|
|
6039
|
+
{
|
|
6040
|
+
name: "tool_search",
|
|
6041
|
+
description: "Discover the tools available inside codemode. Returns generated TypeScript input and output declarations. Use an optional name/description substring query, or omit it for all tools.",
|
|
6042
|
+
inputSchema: {
|
|
6043
|
+
type: "object",
|
|
6044
|
+
properties: { query: { type: "string" } },
|
|
6045
|
+
additionalProperties: false
|
|
6046
|
+
},
|
|
6047
|
+
execute: async (raw) => {
|
|
6048
|
+
const args = codeModeArguments(raw);
|
|
6049
|
+
if (args.query !== void 0 && typeof args.query !== "string") throw new TypeError("query must be a string");
|
|
6050
|
+
return describeCodeModeTools(callable, args.query);
|
|
6051
|
+
}
|
|
6052
|
+
},
|
|
6053
|
+
{
|
|
6054
|
+
name: "codemode",
|
|
6055
|
+
description: "Run a JavaScript async-function body to compose the granted tools. Call tools.name(args) or tools[\"original-name\"](args); inspect ALL_TOOLS or tool_search to discover them. Await tool calls, use loops and Promise.all, keep intermediate data in variables, and return only the result needed for the next decision. text(value) prints, image({type:\"image\",data,mimeType}) emits an image. store(key,value) and load(key) retain JSON across successful calls in this conversation. No imports, process, filesystem, network, or timers. Side effects are not rolled back or automatically retried.",
|
|
6056
|
+
inputSchema: {
|
|
6057
|
+
type: "object",
|
|
6058
|
+
properties: { code: { type: "string" } },
|
|
6059
|
+
required: ["code"],
|
|
6060
|
+
additionalProperties: false
|
|
6061
|
+
},
|
|
6062
|
+
execute: async (raw, context) => {
|
|
6063
|
+
const args = codeModeArguments(raw);
|
|
6064
|
+
if (typeof args.code !== "string") throw new TypeError("codemode requires {code: string}");
|
|
6065
|
+
if (running) throw new Error("code mode: another program is still running in this conversation");
|
|
6066
|
+
running = true;
|
|
6067
|
+
try {
|
|
6068
|
+
const result = await runCodeMode(args.code, {
|
|
6069
|
+
...options,
|
|
6070
|
+
tools: callable,
|
|
6071
|
+
signal: context.signal,
|
|
6072
|
+
callId: context.callId,
|
|
6073
|
+
store
|
|
6074
|
+
});
|
|
6075
|
+
if (result.ok) {
|
|
6076
|
+
const next = Object.assign(Object.create(null), store, result.storeWrites.set);
|
|
6077
|
+
for (const key of result.storeWrites.delete) delete next[key];
|
|
6078
|
+
store = structuredClone(next);
|
|
6079
|
+
}
|
|
6080
|
+
return result.ok ? {
|
|
6081
|
+
ok: true,
|
|
6082
|
+
value: result.value ?? null,
|
|
6083
|
+
output: result.output
|
|
6084
|
+
} : {
|
|
6085
|
+
ok: false,
|
|
6086
|
+
error: result.error,
|
|
6087
|
+
output: result.output
|
|
6088
|
+
};
|
|
6089
|
+
} finally {
|
|
6090
|
+
running = false;
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
6093
|
+
},
|
|
6094
|
+
...copied.filter((tool) => direct.has(tool.name))
|
|
6095
|
+
];
|
|
6096
|
+
return {
|
|
6097
|
+
tools: Object.freeze(tools),
|
|
6098
|
+
snapshotStore: () => structuredClone(store)
|
|
6099
|
+
};
|
|
6100
|
+
}
|
|
6101
|
+
/** Model tools have object arguments. Validation against a tool's schema remains host-owned. */
|
|
6102
|
+
function codeModeArguments(value) {
|
|
6103
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("tool arguments must be a JSON object");
|
|
6104
|
+
return value;
|
|
6105
|
+
}
|
|
6106
|
+
/** Preserve legacy text tool results; structured tool handlers keep their actual JSON values. */
|
|
6107
|
+
function toolResultText(value) {
|
|
6108
|
+
return typeof value === "string" ? value : JSON.stringify(value) ?? "null";
|
|
6109
|
+
}
|
|
6110
|
+
/**
|
|
6111
|
+
* OpenAI-compatible output projection. All tool replies must precede the optional
|
|
6112
|
+
* user image message, so the loop appends returned images after the tool batch.
|
|
6113
|
+
* Image bytes never become a stringified pseudo-image in the tool's text.
|
|
6114
|
+
*/
|
|
6115
|
+
function codeModeModelOutput(value) {
|
|
6116
|
+
const reply = value;
|
|
6117
|
+
return {
|
|
6118
|
+
text: JSON.stringify({
|
|
6119
|
+
ok: reply.ok,
|
|
6120
|
+
...reply.ok ? { value: reply.value } : { error: reply.error },
|
|
6121
|
+
output: reply.output.map((item) => item.type === "text" ? item : {
|
|
6122
|
+
type: "image",
|
|
6123
|
+
mimeType: item.mimeType
|
|
6124
|
+
})
|
|
6125
|
+
}),
|
|
6126
|
+
images: reply.output.flatMap((item) => item.type === "image" ? [{
|
|
6127
|
+
type: "image_url",
|
|
6128
|
+
image_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
6129
|
+
}] : [])
|
|
6130
|
+
};
|
|
6131
|
+
}
|
|
6132
|
+
//#endregion
|
|
5869
6133
|
//#region src/durable/content-address.ts
|
|
5870
6134
|
/** Stable content address shared by result and trace artifacts. */
|
|
5871
6135
|
function contentAddress(artifact) {
|
|
@@ -7136,26 +7400,28 @@ async function captureProviderCheckpointWorkspace(port, prepare, marker, parent)
|
|
|
7136
7400
|
clearDeadline();
|
|
7137
7401
|
}
|
|
7138
7402
|
}
|
|
7139
|
-
/** Verify a running workspace copy before treating it as retained evidence.
|
|
7140
|
-
|
|
7403
|
+
/** Verify a running workspace copy before treating it as retained evidence. `parent` stops the
|
|
7404
|
+
* copy, in the queue or under way, when its turn ends. */
|
|
7405
|
+
async function captureProviderLiveWorkspace(port, context, parent) {
|
|
7141
7406
|
assertProviderWorkspaceRetentionPort(port, "provider workspace retention");
|
|
7142
7407
|
if (port.captureLive === void 0) throw new ValidationError$1("provider workspace retention: the port has no captureLive");
|
|
7143
7408
|
const timeoutMs = port.liveTimeoutMs ?? port.timeoutMs;
|
|
7144
7409
|
const controller = new AbortController();
|
|
7145
7410
|
const clearDeadline = armDeadlineTimer(timeoutMs, () => controller.abort(/* @__PURE__ */ new Error(`live workspace capture timed out after ${timeoutMs}ms`)), true);
|
|
7411
|
+
const signal = parent === void 0 ? controller.signal : AbortSignal.any([controller.signal, parent]);
|
|
7146
7412
|
try {
|
|
7147
|
-
return await runAbortable(() => withCaptureSlot(checkpointSlots(port),
|
|
7413
|
+
return await runAbortable(() => withCaptureSlot(checkpointSlots(port), signal, async () => {
|
|
7148
7414
|
const tree = detachedSnapshot(await port.captureLive({
|
|
7149
7415
|
...context,
|
|
7150
|
-
signal
|
|
7416
|
+
signal
|
|
7151
7417
|
}), "live workspace capture tree");
|
|
7152
7418
|
if (tree?.kind !== "agent-candidate-workspace-tree") throw new Error("live workspace capture returned no workspace tree");
|
|
7153
7419
|
if ((await verifyAgentCandidateWorkspaceTree(tree, port.artifacts, {
|
|
7154
7420
|
...port.limits === void 0 ? {} : { limits: port.limits },
|
|
7155
|
-
signal
|
|
7421
|
+
signal
|
|
7156
7422
|
})).files.length !== tree.files) throw new Error("live workspace capture tree misstates its file count");
|
|
7157
7423
|
return tree;
|
|
7158
|
-
}),
|
|
7424
|
+
}), signal, `live workspace capture timed out after ${timeoutMs}ms`);
|
|
7159
7425
|
} finally {
|
|
7160
7426
|
clearDeadline();
|
|
7161
7427
|
}
|
|
@@ -7543,6 +7809,43 @@ function assertRequestedInteractionCapabilities(providerName, requested, capabil
|
|
|
7543
7809
|
if (interactions.replay !== true || interactions.responseIdempotency !== true) throw new Error(`provider "${providerName}" cannot safely dispatch requested interactions without replay and response idempotency`);
|
|
7544
7810
|
}
|
|
7545
7811
|
//#endregion
|
|
7812
|
+
//#region src/runtime/retained-context-transfer.ts
|
|
7813
|
+
/** Validate attachment authority before admission or any provider operation. */
|
|
7814
|
+
function retainedContextTransferReceipt(options, provider, request) {
|
|
7815
|
+
if (request === void 0) {
|
|
7816
|
+
if (options.contextTransferReceipt !== void 0) throw new Error("context transfer receipt requires its exact request");
|
|
7817
|
+
return;
|
|
7818
|
+
}
|
|
7819
|
+
if (options.contextTransferReceipt === void 0) throw new Error("retained context transfer requires an accepted receipt; it cannot create another environment");
|
|
7820
|
+
const receipt = detachedSnapshot(ContextTransferReceiptSchema.parse(options.contextTransferReceipt), "retained context transfer receipt");
|
|
7821
|
+
if (!contextTransferReceiptMatches(request, receipt) || receipt.provider !== provider) throw new Error("retained context transfer receipt does not match its exact request or provider");
|
|
7822
|
+
const { environment, turn } = options;
|
|
7823
|
+
const destination = request.plan.destination;
|
|
7824
|
+
if (request.profile === void 0 || typeof environment.profile === "string" || canonicalAgentProfileDigest(environment.profile) !== destination.profileDigest || turn.profile !== void 0 && canonicalAgentProfileDigest(turn.profile) !== destination.profileDigest) throw new Error("retained context transfer requires the accepted exact profile");
|
|
7825
|
+
if (environment.backend !== void 0 && environment.backend !== destination.runner) throw new Error("retained context transfer runner conflicts with the accepted destination");
|
|
7826
|
+
if (canonicalCandidateDigest(environment.workspace ?? null) !== canonicalCandidateDigest(request.workspace ?? null) || canonicalCandidateDigest(environment.resources ?? null) !== canonicalCandidateDigest(request.resources ?? null)) throw new Error("retained context transfer workspace or resources conflict with acceptance");
|
|
7827
|
+
if (environment.requestedId !== void 0 && environment.requestedId !== receipt.environmentId || options.existingEnvironmentId !== void 0 && options.existingEnvironmentId !== receipt.environmentId) throw new Error("retained context transfer targets another environment");
|
|
7828
|
+
if (environment.runtimeAttachments !== void 0 || environment.egress !== void 0 || environment.billingOwner !== void 0 || Object.keys(environment.env ?? {}).length > 0 || Object.keys(environment.secrets ?? {}).length > 0 || Object.keys(environment.providerOptions ?? {}).length > 0) throw new Error("retained context transfer attachment cannot apply unaccepted create-time options");
|
|
7829
|
+
return receipt;
|
|
7830
|
+
}
|
|
7831
|
+
function assertRetainedContextTransferIdentity(receipt, identity) {
|
|
7832
|
+
if (receipt !== void 0 && (identity.sessionId !== receipt.sessionId || identity.executionId !== receipt.executionId)) throw new Error("retained context transfer identity conflicts with the accepted receipt");
|
|
7833
|
+
}
|
|
7834
|
+
function assertRetainedContextTransferCapability(capabilities) {
|
|
7835
|
+
if (capabilities.contextTransfer?.attach !== true) throw new Error("provider cannot attach the accepted context transfer destination");
|
|
7836
|
+
}
|
|
7837
|
+
/** The provider get contract performs the authoritative operation lookup once. */
|
|
7838
|
+
function assertRetainedContextTransferEnvironment(environment, request, receipt) {
|
|
7839
|
+
const actual = ContextTransferReceiptSchema.safeParse(environment.contextTransferReceipt);
|
|
7840
|
+
if (!actual.success || !contextTransferReceiptMatches(request, actual.data) || environment.id !== receipt.environmentId || environment.provider !== receipt.provider || canonicalCandidateDigest({
|
|
7841
|
+
...actual.data,
|
|
7842
|
+
status: "accepted"
|
|
7843
|
+
}) !== canonicalCandidateDigest({
|
|
7844
|
+
...receipt,
|
|
7845
|
+
status: "accepted"
|
|
7846
|
+
})) throw new Error("provider did not reconstruct the authoritative accepted context transfer receipt");
|
|
7847
|
+
}
|
|
7848
|
+
//#endregion
|
|
7546
7849
|
//#region src/runtime/retained-run-events.ts
|
|
7547
7850
|
/** The runtime's own contract checks inside the stream loop, so the catch can tell a broken
|
|
7548
7851
|
* answer (a verdict) from a read the provider's iterator failed (a wrapper). */
|
|
@@ -7943,10 +8246,31 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
|
|
|
7943
8246
|
* Secret names remain public binding data, so changing requested credentials
|
|
7944
8247
|
* still conflicts before provider effects begin.
|
|
7945
8248
|
*/
|
|
8249
|
+
/**
|
|
8250
|
+
* The pre-interface5 create-material projection: `requestedId`, `egress`,
|
|
8251
|
+
* `billingOwner`, and the workspace `snapshot` digest omitted — the shape
|
|
8252
|
+
* records persisted by the previous version digested. Accepted only when
|
|
8253
|
+
* validating replayed records (an upgrade must not strand an in-flight run
|
|
8254
|
+
* whose provider creation already completed); every new admission digests the
|
|
8255
|
+
* current projection.
|
|
8256
|
+
*/
|
|
8257
|
+
function legacyRetainedCreateMaterial(environment) {
|
|
8258
|
+
const { requestedId: _requestedId, egress: _egress, billingOwner: _billingOwner, workspace, ...preInterface5 } = environment;
|
|
8259
|
+
return retainedCreateMaterial(workspace === void 0 ? preInterface5 : {
|
|
8260
|
+
...preInterface5,
|
|
8261
|
+
workspace: (() => {
|
|
8262
|
+
const { snapshot: _snapshot, ...legacyWorkspace } = workspace;
|
|
8263
|
+
return legacyWorkspace;
|
|
8264
|
+
})()
|
|
8265
|
+
});
|
|
8266
|
+
}
|
|
7946
8267
|
function retainedCreateMaterial(environment) {
|
|
7947
8268
|
return {
|
|
7948
8269
|
...environment.metadata?.runtimeProviderPlacement === void 0 ? {} : { placement: environment.metadata.runtimeProviderPlacement },
|
|
7949
8270
|
...environment.backend === void 0 ? {} : { backend: environment.backend },
|
|
8271
|
+
...environment.requestedId === void 0 ? {} : { requestedId: environment.requestedId },
|
|
8272
|
+
...environment.egress === void 0 ? {} : { egress: environment.egress },
|
|
8273
|
+
...environment.billingOwner === void 0 ? {} : { billingOwner: environment.billingOwner },
|
|
7950
8274
|
...environment.workspace === void 0 ? {} : { workspaceDigest: canonicalCandidateDigest(publicWorkspaceMaterial(environment.workspace)) },
|
|
7951
8275
|
...environment.resources === void 0 ? {} : { resourcesDigest: canonicalCandidateDigest(publicResourceMaterial(environment.resources)) },
|
|
7952
8276
|
...environment.runtimeAttachments === void 0 ? {} : { runtimeAttachmentsDigest: canonicalCandidateDigest(environment.runtimeAttachments) },
|
|
@@ -7971,6 +8295,8 @@ function publicWorkspaceMaterial(workspace) {
|
|
|
7971
8295
|
...workspace.repoUrl === void 0 ? {} : { repoUrl: workspace.repoUrl },
|
|
7972
8296
|
...workspace.gitRef === void 0 ? {} : { gitRef: workspace.gitRef },
|
|
7973
8297
|
...workspace.cwd === void 0 ? {} : { cwd: workspace.cwd },
|
|
8298
|
+
...workspace.checkpoint === void 0 ? {} : { checkpoint: workspace.checkpoint },
|
|
8299
|
+
...workspace.snapshot === void 0 ? {} : { snapshotDigest: agentWorkspaceSnapshotRefDigest(workspace.snapshot) },
|
|
7974
8300
|
...workspace.providerOptions === void 0 ? {} : { providerOptionNames: retainedObjectNames(workspace.providerOptions) }
|
|
7975
8301
|
};
|
|
7976
8302
|
}
|
|
@@ -8027,7 +8353,7 @@ function mintRetainedIdentity(idempotencyKey, turnId) {
|
|
|
8027
8353
|
* coordinates are confirmed by the provider and persisted by the caller.
|
|
8028
8354
|
*
|
|
8029
8355
|
* The required `onAdmission` hook first records a digest-only intent before
|
|
8030
|
-
* creation, then records recovery coordinates and the verified exact control
|
|
8356
|
+
* creation or receipt-authorized attachment, then records recovery coordinates and the verified exact control
|
|
8031
8357
|
* reference. The returned promise resolves only after the dispatched admission
|
|
8032
8358
|
* is durable, so a crash cannot lose a successful start's exact reference.
|
|
8033
8359
|
*
|
|
@@ -8037,14 +8363,19 @@ async function startRetainedRun(options) {
|
|
|
8037
8363
|
assertStableText(options.environment.idempotencyKey, "environment idempotency key");
|
|
8038
8364
|
assertStableText(options.turn.turnId, "turn idempotency key");
|
|
8039
8365
|
if (typeof options.onAdmission !== "function") throw new Error("startRetainedRun requires an awaited onAdmission durability hook");
|
|
8040
|
-
const
|
|
8366
|
+
const contextTransfer = retainedContextTransfer(options.turn.contextTransfer);
|
|
8367
|
+
const transferReceipt = retainedContextTransferReceipt(options, options.provider.name, contextTransfer);
|
|
8368
|
+
const { sessionId, executionId } = options.identity ?? options.intent ?? (transferReceipt === void 0 ? void 0 : {
|
|
8369
|
+
sessionId: transferReceipt.sessionId,
|
|
8370
|
+
executionId: transferReceipt.executionId
|
|
8371
|
+
}) ?? mintRetainedIdentity(options.environment.idempotencyKey, options.turn.turnId);
|
|
8041
8372
|
const identity = {
|
|
8042
8373
|
sessionId,
|
|
8043
8374
|
executionId
|
|
8044
8375
|
};
|
|
8045
8376
|
assertStableText(identity.sessionId, "retained session id");
|
|
8046
8377
|
assertStableText(identity.executionId, "retained execution id");
|
|
8047
|
-
|
|
8378
|
+
assertRetainedContextTransferIdentity(transferReceipt, identity);
|
|
8048
8379
|
AgentTurnInputSchema.parse(freshTurnInput(options.turn, {
|
|
8049
8380
|
turnId: options.turn.turnId,
|
|
8050
8381
|
detach: true,
|
|
@@ -8056,11 +8387,22 @@ async function startRetainedRun(options) {
|
|
|
8056
8387
|
if (options.intent === void 0) await admitDurably(options.onAdmission, intent);
|
|
8057
8388
|
else assertExactRetainedRunIntent(options.intent, intent);
|
|
8058
8389
|
const providerCapabilities = await assertRetainedCapabilities(options.provider);
|
|
8390
|
+
if (transferReceipt !== void 0) assertRetainedContextTransferCapability(providerCapabilities);
|
|
8059
8391
|
assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, providerCapabilities);
|
|
8060
8392
|
options.environment.signal?.throwIfAborted();
|
|
8061
8393
|
options.turn.signal?.throwIfAborted();
|
|
8394
|
+
const attachmentSignal = options.environment.signal === void 0 ? options.turn.signal : options.turn.signal === void 0 ? options.environment.signal : AbortSignal.any([options.environment.signal, options.turn.signal]);
|
|
8062
8395
|
let environment;
|
|
8063
|
-
if (
|
|
8396
|
+
if (transferReceipt !== void 0 && contextTransfer !== void 0) {
|
|
8397
|
+
const existing = await options.provider.get(transferReceipt.environmentId, {
|
|
8398
|
+
contextTransfer,
|
|
8399
|
+
...attachmentSignal === void 0 ? {} : { signal: attachmentSignal }
|
|
8400
|
+
});
|
|
8401
|
+
attachmentSignal?.throwIfAborted();
|
|
8402
|
+
if (!existing) throw new Error("accepted context transfer environment is unavailable; it cannot be replaced");
|
|
8403
|
+
assertRetainedContextTransferEnvironment(existing, contextTransfer, transferReceipt);
|
|
8404
|
+
environment = existing;
|
|
8405
|
+
} else if (options.existingEnvironmentId !== void 0) {
|
|
8064
8406
|
assertStableText(options.existingEnvironmentId, "retained environment id");
|
|
8065
8407
|
const existing = await options.provider.get(options.existingEnvironmentId);
|
|
8066
8408
|
if (!existing || existing.id !== options.existingEnvironmentId || existing.provider !== options.provider.name) throw new Error("retained provider environment is unavailable or has another identity");
|
|
@@ -8073,9 +8415,10 @@ async function startRetainedRun(options) {
|
|
|
8073
8415
|
let capabilities;
|
|
8074
8416
|
try {
|
|
8075
8417
|
capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
|
|
8418
|
+
if (transferReceipt !== void 0) assertRetainedContextTransferCapability(capabilities);
|
|
8076
8419
|
assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, capabilities);
|
|
8077
8420
|
} catch (error) {
|
|
8078
|
-
if (options.existingEnvironmentId !== void 0) throw error;
|
|
8421
|
+
if (transferReceipt !== void 0 || options.existingEnvironmentId !== void 0) throw error;
|
|
8079
8422
|
try {
|
|
8080
8423
|
await environment.destroy?.();
|
|
8081
8424
|
} catch (cleanupError) {
|
|
@@ -8084,7 +8427,7 @@ async function startRetainedRun(options) {
|
|
|
8084
8427
|
throw error;
|
|
8085
8428
|
}
|
|
8086
8429
|
if (!environment.dispatch || !environment.session) {
|
|
8087
|
-
if (options.existingEnvironmentId !== void 0) throw new Error(`provider "${options.provider.name}" does not expose detached session control`);
|
|
8430
|
+
if (transferReceipt !== void 0 || options.existingEnvironmentId !== void 0) throw new Error(`provider "${options.provider.name}" does not expose detached session control`);
|
|
8088
8431
|
try {
|
|
8089
8432
|
await environment.destroy?.();
|
|
8090
8433
|
} catch (cleanupError) {
|
|
@@ -8095,15 +8438,16 @@ async function startRetainedRun(options) {
|
|
|
8095
8438
|
return dispatchRetainedRun({
|
|
8096
8439
|
provider: options.provider,
|
|
8097
8440
|
environment,
|
|
8098
|
-
signal:
|
|
8441
|
+
signal: attachmentSignal,
|
|
8099
8442
|
environmentIdempotencyKey: options.environment.idempotencyKey,
|
|
8100
8443
|
turn: options.turn,
|
|
8101
8444
|
contextTransfer,
|
|
8445
|
+
expectedRunId: transferReceipt?.runId,
|
|
8102
8446
|
identity,
|
|
8103
8447
|
onAdmission: options.onAdmission,
|
|
8104
8448
|
capabilities,
|
|
8105
8449
|
now: options.now,
|
|
8106
|
-
preserveEnvironment: options.existingEnvironmentId !== void 0
|
|
8450
|
+
preserveEnvironment: transferReceipt !== void 0 || options.existingEnvironmentId !== void 0
|
|
8107
8451
|
});
|
|
8108
8452
|
}
|
|
8109
8453
|
/**
|
|
@@ -8116,6 +8460,7 @@ async function startRetainedRun(options) {
|
|
|
8116
8460
|
* @stable
|
|
8117
8461
|
*/
|
|
8118
8462
|
async function startRetainedRunInEnvironment(options) {
|
|
8463
|
+
if (options.turn.contextTransfer !== void 0) throw new Error("accepted context transfer requires startRetainedRun with its exact profile and receipt");
|
|
8119
8464
|
assertStableText(options.environment.id, "retained environment id");
|
|
8120
8465
|
assertStableText(options.environment.idempotencyKey, "environment idempotency key");
|
|
8121
8466
|
assertStableText(options.turn.turnId, "turn idempotency key");
|
|
@@ -8220,6 +8565,7 @@ async function dispatchRetainedRun(options) {
|
|
|
8220
8565
|
sessionId: identity.sessionId
|
|
8221
8566
|
});
|
|
8222
8567
|
if (controlRef.executionId !== identity.executionId) throw new Error("provider bound another execution than the requested identity");
|
|
8568
|
+
if (options.expectedRunId !== void 0 && controlRef.runId !== options.expectedRunId) throw new Error("provider bound another run than the accepted context transfer receipt");
|
|
8223
8569
|
exact = exactSession(environment, controlRef);
|
|
8224
8570
|
} catch (error) {
|
|
8225
8571
|
const bindingError = new RetainedRunDispatchBindingError({
|
|
@@ -8279,10 +8625,12 @@ async function recoverRetainedRun(options) {
|
|
|
8279
8625
|
assertStableText(options.environmentId, "retained environment id");
|
|
8280
8626
|
assertStableText(options.sessionId, "retained session id");
|
|
8281
8627
|
assertStableText(options.executionId, "retained execution id");
|
|
8628
|
+
const contextTransfer = retainedContextTransfer(options.contextTransfer);
|
|
8282
8629
|
const providerCapabilities = await assertRetainedCapabilities(options.provider);
|
|
8283
8630
|
if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
|
|
8284
|
-
const environment = await options.provider.get(options.environmentId);
|
|
8631
|
+
const environment = contextTransfer === void 0 || options.transferReceipt === void 0 ? await options.provider.get(options.environmentId) : await options.provider.get(options.environmentId, { contextTransfer });
|
|
8285
8632
|
if (!environment) return { outcome: "not_found" };
|
|
8633
|
+
if (contextTransfer !== void 0 && options.transferReceipt !== void 0) assertRetainedContextTransferEnvironment(environment, contextTransfer, options.transferReceipt);
|
|
8286
8634
|
const capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
|
|
8287
8635
|
if (!environment.session) return {
|
|
8288
8636
|
outcome: "unverifiable",
|
|
@@ -8322,6 +8670,8 @@ function assertRetainedRunReplayMaterial(provider, replay, admission) {
|
|
|
8322
8670
|
}, identity, retainedContextTransfer(replay.turn.contextTransfer)));
|
|
8323
8671
|
}
|
|
8324
8672
|
function retainedRunIntent(options, identity, contextTransfer) {
|
|
8673
|
+
const receipt = retainedContextTransferReceipt(options, options.provider.name, contextTransfer);
|
|
8674
|
+
assertRetainedContextTransferIdentity(receipt, identity);
|
|
8325
8675
|
const { profile } = options.environment;
|
|
8326
8676
|
const requestedProfileDigest = typeof profile === "string" ? canonicalCandidateDigest(profile) : canonicalAgentProfileDigest(profile);
|
|
8327
8677
|
const requestDigest = canonicalCandidateDigest({
|
|
@@ -8333,6 +8683,10 @@ function retainedRunIntent(options, identity, contextTransfer) {
|
|
|
8333
8683
|
sessionId: identity.sessionId,
|
|
8334
8684
|
executionId: identity.executionId,
|
|
8335
8685
|
requestedProfileDigest,
|
|
8686
|
+
...receipt === void 0 ? {} : { contextTransferReceiptDigest: canonicalCandidateDigest({
|
|
8687
|
+
...receipt,
|
|
8688
|
+
status: "accepted"
|
|
8689
|
+
}) },
|
|
8336
8690
|
create: retainedCreateMaterial(options.environment),
|
|
8337
8691
|
turn: retainedTurnMaterial(options.turn, contextTransfer)
|
|
8338
8692
|
});
|
|
@@ -8350,7 +8704,9 @@ function retainedRunIntent(options, identity, contextTransfer) {
|
|
|
8350
8704
|
}
|
|
8351
8705
|
function retainedContextTransfer(value) {
|
|
8352
8706
|
if (value === void 0) return void 0;
|
|
8353
|
-
|
|
8707
|
+
const parsed = ContextTransferRequestSchema.safeParse(value);
|
|
8708
|
+
if (!parsed.success) throw new Error("retained context transfer request is invalid or uses an incompatible wire contract; preserve the original record and explicitly reconstruct and review an Interface 5 transfer request before retrying", { cause: parsed.error });
|
|
8709
|
+
return detachedSnapshot(parsed.data, "retained context transfer request");
|
|
8354
8710
|
}
|
|
8355
8711
|
function assertExactRetainedRunIntent(received, expected) {
|
|
8356
8712
|
if (canonicalCandidateDigest(parseRetainedRunIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("retained run intent conflicts with replay material");
|
|
@@ -10825,6 +11181,7 @@ function retainedExecutorContext(ctx) {
|
|
|
10825
11181
|
}
|
|
10826
11182
|
const causeMessages = {
|
|
10827
11183
|
unobservable: "retained provider execution requires reconciliation before replacement",
|
|
11184
|
+
"terminal-event-lost": "retained provider stream ended or stalled without a terminal event; exact result requires reconciliation",
|
|
10828
11185
|
"provider-contract": "retained provider response violated its contract; original execution remains unresolved",
|
|
10829
11186
|
"request-rejected": "retained provider execution was refused before it ran; nothing to reconcile",
|
|
10830
11187
|
transport: "retained provider execution lost its transport; status in doubt",
|
|
@@ -11578,13 +11935,18 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
11578
11935
|
const livePort = options.workspaceRetention?.captureLive === void 0 ? void 0 : options.workspaceRetention;
|
|
11579
11936
|
let liveInFlight;
|
|
11580
11937
|
let liveTimer;
|
|
11938
|
+
let liveStop;
|
|
11581
11939
|
const stopLiveMirror = () => {
|
|
11582
11940
|
if (liveTimer !== void 0) clearTimeout(liveTimer);
|
|
11583
11941
|
liveTimer = void 0;
|
|
11942
|
+
liveStop?.abort(/* @__PURE__ */ new Error("live workspace capture stopped: its turn ended"));
|
|
11943
|
+
liveStop = void 0;
|
|
11584
11944
|
};
|
|
11585
11945
|
const startLiveMirror = (next) => {
|
|
11586
11946
|
if (livePort?.liveIntervalMs === void 0) return;
|
|
11587
11947
|
stopLiveMirror();
|
|
11948
|
+
const stop = new AbortController();
|
|
11949
|
+
liveStop = stop;
|
|
11588
11950
|
const schedule = () => {
|
|
11589
11951
|
liveTimer = setTimeout(() => {
|
|
11590
11952
|
if (liveInFlight === void 0 && workspaceCapturePromise === void 0) {
|
|
@@ -11596,7 +11958,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
11596
11958
|
providerSessionId,
|
|
11597
11959
|
nativeSessionId: null,
|
|
11598
11960
|
profile: createProfile
|
|
11599
|
-
}).then(() => void 0, () => void 0).finally(() => {
|
|
11961
|
+
}, stop.signal).then(() => void 0, () => void 0).finally(() => {
|
|
11600
11962
|
if (liveInFlight === tracked) liveInFlight = void 0;
|
|
11601
11963
|
});
|
|
11602
11964
|
liveInFlight = tracked;
|
|
@@ -11675,6 +12037,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
|
|
|
11675
12037
|
schedule();
|
|
11676
12038
|
};
|
|
11677
12039
|
const finishNativeMirror = async (next, phase) => {
|
|
12040
|
+
stopLiveMirror();
|
|
11678
12041
|
await stopNativeMirror();
|
|
11679
12042
|
if (workspaceSnapshot !== void 0 && !nativeHoldsTranscript) return;
|
|
11680
12043
|
await captureNative(next, phase, void 0, harnessStopped);
|
|
@@ -12096,6 +12459,33 @@ const NATIVE_STOP_TIMEOUT_MS = 3e4;
|
|
|
12096
12459
|
/** How long the final copy of a stopped harness waits for the provider to record how it ended. */
|
|
12097
12460
|
const NATIVE_SETTLE_WINDOW_MS = 15e3;
|
|
12098
12461
|
const NATIVE_SETTLE_POLL_MS = 1e3;
|
|
12462
|
+
/** The two waits together leave a minute for Runtime to record a pending result before ten minutes. */
|
|
12463
|
+
const RETAINED_OBSERVATION_IDLE_MS = 8 * 6e4;
|
|
12464
|
+
const RETAINED_RESULT_WAIT_MS = 6e4;
|
|
12465
|
+
var RetainedReadTimeoutError = class extends Error {
|
|
12466
|
+
constructor(label, ms) {
|
|
12467
|
+
super(`retained provider ${label} did not settle within ${ms} ms`);
|
|
12468
|
+
this.name = "RetainedReadTimeoutError";
|
|
12469
|
+
}
|
|
12470
|
+
};
|
|
12471
|
+
function retainedWaitBound(value, maximum, name) {
|
|
12472
|
+
if (value === void 0) return maximum;
|
|
12473
|
+
if (!Number.isSafeInteger(value) || value <= 0 || value > maximum) throw new ValidationError(`${name} must be a positive integer at most ${maximum} ms`);
|
|
12474
|
+
return value;
|
|
12475
|
+
}
|
|
12476
|
+
/** Bound a provider read without confusing a lost observer with a cancelled execution. */
|
|
12477
|
+
function awaitRetainedRead(read, ms, label) {
|
|
12478
|
+
return new Promise((resolve, reject) => {
|
|
12479
|
+
const clear = armDeadlineTimer(ms, () => reject(new RetainedReadTimeoutError(label, ms)), true);
|
|
12480
|
+
read.then((value) => {
|
|
12481
|
+
clear();
|
|
12482
|
+
resolve(value);
|
|
12483
|
+
}, (error) => {
|
|
12484
|
+
clear();
|
|
12485
|
+
reject(error);
|
|
12486
|
+
});
|
|
12487
|
+
});
|
|
12488
|
+
}
|
|
12099
12489
|
/** The environment id the latest durable admission names, when creation got that far. */
|
|
12100
12490
|
function admittedEnvironmentId(retention) {
|
|
12101
12491
|
for (const admission of [...retention?.admissions ?? []].reverse()) {
|
|
@@ -12485,6 +12875,8 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12485
12875
|
};
|
|
12486
12876
|
}
|
|
12487
12877
|
const retention = args.retention;
|
|
12878
|
+
const observationIdleMs = retainedWaitBound(args.options.retainedObservationIdleMs, RETAINED_OBSERVATION_IDLE_MS, "retainedObservationIdleMs");
|
|
12879
|
+
const resultWaitMs = retainedWaitBound(args.options.retainedResultWaitMs, RETAINED_RESULT_WAIT_MS, "retainedResultWaitMs");
|
|
12488
12880
|
let admitted = args.recovering;
|
|
12489
12881
|
let executionAdmitted = args.recovering && retention.admissions.some((admission) => admission.phase === "dispatched");
|
|
12490
12882
|
const onAdmission = async (admission) => {
|
|
@@ -12611,6 +13003,8 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12611
13003
|
let observationFailure;
|
|
12612
13004
|
let lastReplayPosition;
|
|
12613
13005
|
let sawTerminal = false;
|
|
13006
|
+
let lastObservedAt = Date.now();
|
|
13007
|
+
const seenEvents = /* @__PURE__ */ new Map();
|
|
12614
13008
|
const drain = async function* (open) {
|
|
12615
13009
|
let iterator;
|
|
12616
13010
|
let failed = false;
|
|
@@ -12625,7 +13019,9 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12625
13019
|
while (true) {
|
|
12626
13020
|
let next;
|
|
12627
13021
|
try {
|
|
12628
|
-
|
|
13022
|
+
const remaining = observationIdleMs - (Date.now() - lastObservedAt);
|
|
13023
|
+
if (remaining <= 0) throw new RetainedReadTimeoutError("event stream", observationIdleMs);
|
|
13024
|
+
next = await awaitRetainedRead(awaitAbortable$1(Promise.resolve().then(() => iterator.next()), signal), remaining, "event stream");
|
|
12629
13025
|
} catch (error) {
|
|
12630
13026
|
if (signal.aborted) throw error;
|
|
12631
13027
|
observationFailure = { error };
|
|
@@ -12641,7 +13037,25 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12641
13037
|
cause: error
|
|
12642
13038
|
});
|
|
12643
13039
|
}
|
|
12644
|
-
|
|
13040
|
+
const identity = extractTransportEventIdentity(next.value);
|
|
13041
|
+
const eventId = identity.eventId ?? identity.cursor;
|
|
13042
|
+
if (eventId !== void 0) {
|
|
13043
|
+
const digest = canonicalCandidateDigest({
|
|
13044
|
+
type: next.value.type,
|
|
13045
|
+
data: next.value.data,
|
|
13046
|
+
...next.value.usage === void 0 ? {} : { usage: next.value.usage },
|
|
13047
|
+
...next.value.normalized === void 0 ? {} : { normalized: next.value.normalized }
|
|
13048
|
+
});
|
|
13049
|
+
const prior = seenEvents.get(eventId);
|
|
13050
|
+
if (prior !== void 0) {
|
|
13051
|
+
if (prior !== digest) throw new RetainedRunProviderContractError(`provider replay changed retained event ${eventId}`, { code: "RETAINED_EVENT_DUPLICATE_CHANGED" });
|
|
13052
|
+
continue;
|
|
13053
|
+
}
|
|
13054
|
+
seenEvents.set(eventId, digest);
|
|
13055
|
+
}
|
|
13056
|
+
lastObservedAt = Date.now();
|
|
13057
|
+
if (identity.cursor !== void 0) lastReplayPosition = identity.cursor;
|
|
13058
|
+
else if (eventId !== void 0) lastReplayPosition = eventId;
|
|
12645
13059
|
if (isTerminalEnvironmentEvent(next.value)) sawTerminal = true;
|
|
12646
13060
|
yield next.value;
|
|
12647
13061
|
}
|
|
@@ -12654,7 +13068,7 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12654
13068
|
if (!(yield* drain(() => session.events({
|
|
12655
13069
|
executionId: handle.controlRef.executionId,
|
|
12656
13070
|
signal
|
|
12657
|
-
}))) && !sawTerminal && lastReplayPosition !== void 0) {
|
|
13071
|
+
}))) && !sawTerminal && lastReplayPosition !== void 0 && !(observationFailure?.error instanceof RetainedReadTimeoutError)) {
|
|
12658
13072
|
const firstFailure = observationFailure;
|
|
12659
13073
|
observationFailure = void 0;
|
|
12660
13074
|
if (!(yield* drain(() => session.events({
|
|
@@ -12663,11 +13077,14 @@ async function providerExecutionSource(args, turn, signal) {
|
|
|
12663
13077
|
signal
|
|
12664
13078
|
})))) observationFailure = firstFailure;
|
|
12665
13079
|
}
|
|
13080
|
+
if (!sawTerminal && observationFailure === void 0) observationFailure = { error: /* @__PURE__ */ new Error("retained provider stream ended without a terminal event") };
|
|
12666
13081
|
let result;
|
|
12667
13082
|
try {
|
|
12668
|
-
result = await awaitAbortable$1(handle.result(), signal);
|
|
13083
|
+
result = await awaitRetainedRead(awaitAbortable$1(handle.result(), signal), resultWaitMs, "exact result");
|
|
12669
13084
|
} catch (error) {
|
|
12670
|
-
if (
|
|
13085
|
+
if (signal.aborted) throw error;
|
|
13086
|
+
if (!sawTerminal && error instanceof RetainedReadTimeoutError) throw new RetainedExecutionPendingError(new AggregateError([observationFailure?.error, error], "retained event stream had no terminal event and its exact result is unavailable", { cause: error }), "terminal-event-lost");
|
|
13087
|
+
if (observationFailure === void 0) throw error;
|
|
12671
13088
|
throw new AggregateError([observationFailure.error, error], "retained event observation failed and its exact result could not be reconciled", { cause: error });
|
|
12672
13089
|
}
|
|
12673
13090
|
yield {
|
|
@@ -13475,15 +13892,57 @@ async function runBrainLoop(opts) {
|
|
|
13475
13892
|
let tokensKnown = true;
|
|
13476
13893
|
let completedTurns = 0;
|
|
13477
13894
|
const toolTrace = [];
|
|
13895
|
+
const signal = opts.signal ?? new AbortController().signal;
|
|
13896
|
+
const codeMode = opts.codeMode ? createCodeModeTools(opts.tools.map(({ function: tool }) => ({
|
|
13897
|
+
name: tool.name,
|
|
13898
|
+
description: tool.description,
|
|
13899
|
+
inputSchema: tool.parameters,
|
|
13900
|
+
outputSchema: tool.outputSchema,
|
|
13901
|
+
execute: async (raw, context) => {
|
|
13902
|
+
signal.throwIfAborted();
|
|
13903
|
+
if (opts.hooks?.stopBefore?.(completedTurns + 1)) throw new Error("code mode: Runtime execution has stopped");
|
|
13904
|
+
const args = codeModeArguments(raw);
|
|
13905
|
+
let result;
|
|
13906
|
+
try {
|
|
13907
|
+
result = await opts.execute(tool.name, args, context);
|
|
13908
|
+
} catch (error) {
|
|
13909
|
+
if (context.callId !== context.parentCallId) toolTrace.push({
|
|
13910
|
+
name: tool.name,
|
|
13911
|
+
args: JSON.stringify(args),
|
|
13912
|
+
result: `error: ${error instanceof Error ? error.message : String(error)}`
|
|
13913
|
+
});
|
|
13914
|
+
throw error;
|
|
13915
|
+
}
|
|
13916
|
+
if (context.callId !== context.parentCallId) toolTrace.push({
|
|
13917
|
+
name: tool.name,
|
|
13918
|
+
args: JSON.stringify(args),
|
|
13919
|
+
result: toolResultText(result)
|
|
13920
|
+
});
|
|
13921
|
+
return result;
|
|
13922
|
+
}
|
|
13923
|
+
})), opts.codeMode === true ? {} : opts.codeMode) : void 0;
|
|
13924
|
+
const modelTools = codeMode ? codeMode.tools.map((tool) => ({
|
|
13925
|
+
type: "function",
|
|
13926
|
+
function: {
|
|
13927
|
+
name: tool.name,
|
|
13928
|
+
description: tool.description,
|
|
13929
|
+
parameters: tool.inputSchema
|
|
13930
|
+
}
|
|
13931
|
+
})) : opts.tools;
|
|
13932
|
+
const codeByName = new Map(codeMode?.tools.map((tool) => [tool.name, tool]) ?? []);
|
|
13933
|
+
const retainedCodeMode = () => codeMode ? {
|
|
13934
|
+
codeModeStore: codeMode.snapshotStore(),
|
|
13935
|
+
modelToolNames: modelTools.map((tool) => tool.function.name)
|
|
13936
|
+
} : {};
|
|
13478
13937
|
for (let turn = 1; maxTurns === 0 || turn <= maxTurns; turn += 1) {
|
|
13479
|
-
if (opts.hooks?.stopBefore?.(turn)) break;
|
|
13938
|
+
if (signal.aborted || opts.hooks?.stopBefore?.(turn)) break;
|
|
13480
13939
|
await opts.hooks?.beforeTurn?.(turn, messages);
|
|
13481
|
-
if (opts.hooks?.stopBefore?.(turn)) break;
|
|
13940
|
+
if (signal.aborted || opts.hooks?.stopBefore?.(turn)) break;
|
|
13482
13941
|
if (opts.compaction) {
|
|
13483
13942
|
await maybeCompact(messages, opts.compaction, turn);
|
|
13484
|
-
if (opts.hooks?.stopBefore?.(turn)) break;
|
|
13943
|
+
if (signal.aborted || opts.hooks?.stopBefore?.(turn)) break;
|
|
13485
13944
|
}
|
|
13486
|
-
const r = await opts.chat(messages,
|
|
13945
|
+
const r = await opts.chat(messages, modelTools);
|
|
13487
13946
|
completedTurns = turn;
|
|
13488
13947
|
if (r.usage) {
|
|
13489
13948
|
usage.input += r.usage.input;
|
|
@@ -13511,13 +13970,15 @@ async function runBrainLoop(opts) {
|
|
|
13511
13970
|
toolTrace,
|
|
13512
13971
|
usage,
|
|
13513
13972
|
...tokensKnown ? {} : { tokensKnown: false },
|
|
13514
|
-
messages
|
|
13973
|
+
messages,
|
|
13974
|
+
...retainedCodeMode()
|
|
13515
13975
|
};
|
|
13516
13976
|
}
|
|
13517
13977
|
messages.push({
|
|
13518
13978
|
role: "assistant",
|
|
13519
13979
|
content: r.content ?? "",
|
|
13520
13980
|
tool_calls: r.toolCalls.map((tc) => ({
|
|
13981
|
+
...tc.providerFields,
|
|
13521
13982
|
id: tc.id,
|
|
13522
13983
|
type: "function",
|
|
13523
13984
|
function: {
|
|
@@ -13526,6 +13987,7 @@ async function runBrainLoop(opts) {
|
|
|
13526
13987
|
}
|
|
13527
13988
|
}))
|
|
13528
13989
|
});
|
|
13990
|
+
const images = [];
|
|
13529
13991
|
for (const tc of r.toolCalls) {
|
|
13530
13992
|
toolCalls += 1;
|
|
13531
13993
|
let args = {};
|
|
@@ -13539,7 +14001,32 @@ async function runBrainLoop(opts) {
|
|
|
13539
14001
|
});
|
|
13540
14002
|
continue;
|
|
13541
14003
|
}
|
|
13542
|
-
|
|
14004
|
+
signal.throwIfAborted();
|
|
14005
|
+
let result;
|
|
14006
|
+
let dispatchSucceeded = true;
|
|
14007
|
+
if (codeMode) {
|
|
14008
|
+
const tool = codeByName.get(tc.name);
|
|
14009
|
+
if (!tool) {
|
|
14010
|
+
dispatchSucceeded = false;
|
|
14011
|
+
result = `error: code mode: ${tc.name} is not in the model-visible tool set`;
|
|
14012
|
+
} else try {
|
|
14013
|
+
result = await tool.execute(args, {
|
|
14014
|
+
signal,
|
|
14015
|
+
callId: tc.id,
|
|
14016
|
+
parentCallId: tc.id
|
|
14017
|
+
});
|
|
14018
|
+
} catch (error) {
|
|
14019
|
+
dispatchSucceeded = false;
|
|
14020
|
+
result = `error: ${error instanceof Error ? error.message : String(error)}`;
|
|
14021
|
+
}
|
|
14022
|
+
} else result = await opts.execute(tc.name, args, {
|
|
14023
|
+
signal,
|
|
14024
|
+
callId: tc.id,
|
|
14025
|
+
parentCallId: tc.id
|
|
14026
|
+
});
|
|
14027
|
+
const projected = dispatchSucceeded && codeMode && tc.name === "codemode" ? codeModeModelOutput(result) : void 0;
|
|
14028
|
+
if (projected) images.push(...projected.images);
|
|
14029
|
+
const out = projected?.text ?? toolResultText(result);
|
|
13543
14030
|
messages.push({
|
|
13544
14031
|
role: "tool",
|
|
13545
14032
|
tool_call_id: tc.id,
|
|
@@ -13551,6 +14038,13 @@ async function runBrainLoop(opts) {
|
|
|
13551
14038
|
result: out
|
|
13552
14039
|
});
|
|
13553
14040
|
}
|
|
14041
|
+
if (images.length) messages.push({
|
|
14042
|
+
role: "user",
|
|
14043
|
+
content: [{
|
|
14044
|
+
type: "text",
|
|
14045
|
+
text: "Images emitted by codemode:"
|
|
14046
|
+
}, ...images]
|
|
14047
|
+
});
|
|
13554
14048
|
}
|
|
13555
14049
|
return {
|
|
13556
14050
|
final: lastText,
|
|
@@ -13559,7 +14053,8 @@ async function runBrainLoop(opts) {
|
|
|
13559
14053
|
toolTrace,
|
|
13560
14054
|
usage,
|
|
13561
14055
|
...tokensKnown ? {} : { tokensKnown: false },
|
|
13562
|
-
messages
|
|
14056
|
+
messages,
|
|
14057
|
+
...retainedCodeMode()
|
|
13563
14058
|
};
|
|
13564
14059
|
}
|
|
13565
14060
|
//#endregion
|
|
@@ -13667,6 +14162,17 @@ function splitReasoning(rawContent, fieldReasoning) {
|
|
|
13667
14162
|
...fieldReasoning ? { reasoning: fieldReasoning } : {}
|
|
13668
14163
|
};
|
|
13669
14164
|
}
|
|
14165
|
+
/** Keep provider extensions beside, never in place of, the canonical call identity and function.
|
|
14166
|
+
* Stream indices identify assembly slots and are not replay fields. */
|
|
14167
|
+
function toolCallProviderFields(call) {
|
|
14168
|
+
const fields = Object.fromEntries(Object.entries(call).filter(([key]) => ![
|
|
14169
|
+
"id",
|
|
14170
|
+
"type",
|
|
14171
|
+
"function",
|
|
14172
|
+
"index"
|
|
14173
|
+
].includes(key)));
|
|
14174
|
+
return Object.keys(fields).length === 0 ? void 0 : fields;
|
|
14175
|
+
}
|
|
13670
14176
|
/**
|
|
13671
14177
|
* A router completion WITH tool-calling — the operator driver's LLM seam. Passes OpenAI-shape
|
|
13672
14178
|
* `messages` (system/user/assistant-with-tool_calls/tool roles) + function `tools`, and returns the
|
|
@@ -13698,11 +14204,15 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
|
|
|
13698
14204
|
const data = raw;
|
|
13699
14205
|
const msg = data.choices?.[0]?.message;
|
|
13700
14206
|
if (!msg) throw new ValidationError$1("router completion: no choices[0].message");
|
|
13701
|
-
const toolCalls = (msg?.tool_calls ?? []).map((tc, i) =>
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
14207
|
+
const toolCalls = (msg?.tool_calls ?? []).map((tc, i) => {
|
|
14208
|
+
const providerFields = toolCallProviderFields(tc);
|
|
14209
|
+
return {
|
|
14210
|
+
id: tc.id ?? `call_${i}`,
|
|
14211
|
+
name: tc.function?.name ?? "",
|
|
14212
|
+
arguments: tc.function?.arguments ?? "{}",
|
|
14213
|
+
...providerFields ? { providerFields } : {}
|
|
14214
|
+
};
|
|
14215
|
+
});
|
|
13706
14216
|
const { usage, resources, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(data.usage, cfg.model, transportAttempts);
|
|
13707
14217
|
return {
|
|
13708
14218
|
response: raw,
|
|
@@ -13740,7 +14250,10 @@ function toolCompletionBody(cfg, messages, tools, opts) {
|
|
|
13740
14250
|
model: cfg.model,
|
|
13741
14251
|
messages,
|
|
13742
14252
|
...tools.length > 0 ? {
|
|
13743
|
-
tools,
|
|
14253
|
+
tools: tools.map(({ function: { outputSchema: _outputSchema, ...fn }, ...tool }) => ({
|
|
14254
|
+
...tool,
|
|
14255
|
+
function: fn
|
|
14256
|
+
})),
|
|
13744
14257
|
tool_choice: opts?.toolChoice ?? "auto"
|
|
13745
14258
|
} : {},
|
|
13746
14259
|
...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
|
|
@@ -13849,7 +14362,8 @@ async function streamRouterChatWithTools(cfg, messages, tools, opts) {
|
|
|
13849
14362
|
const toolCalls = [...streamed.calls.entries()].sort((a, b) => a[0] - b[0]).map(([index, call]) => ({
|
|
13850
14363
|
id: call.id ?? `call_${index}`,
|
|
13851
14364
|
name: call.name ?? "",
|
|
13852
|
-
arguments: call.arguments || "{}"
|
|
14365
|
+
arguments: call.arguments || "{}",
|
|
14366
|
+
...call.providerFields ? { providerFields: call.providerFields } : {}
|
|
13853
14367
|
}));
|
|
13854
14368
|
const { usage, resources, costUsd, costProvenance, billedCostUsd, cache } = meterTurn(streamed.rawUsage, cfg.model, streamed.transportAttempts);
|
|
13855
14369
|
return {
|
|
@@ -13963,6 +14477,11 @@ async function streamChatCompletion(context, cfg, requestBody, opts) {
|
|
|
13963
14477
|
if (tc.id) acc.id = tc.id;
|
|
13964
14478
|
if (tc.function?.name) acc.name = tc.function.name;
|
|
13965
14479
|
if (tc.function?.arguments) acc.arguments += tc.function.arguments;
|
|
14480
|
+
const providerFields = toolCallProviderFields(tc);
|
|
14481
|
+
if (providerFields) acc.providerFields = {
|
|
14482
|
+
...acc.providerFields,
|
|
14483
|
+
...providerFields
|
|
14484
|
+
};
|
|
13966
14485
|
calls.set(index, acc);
|
|
13967
14486
|
}
|
|
13968
14487
|
}
|
|
@@ -19981,6 +20500,33 @@ const routerInlineExecutor = (spec, ctx) => {
|
|
|
19981
20500
|
});
|
|
19982
20501
|
return executor;
|
|
19983
20502
|
};
|
|
20503
|
+
/** Compose node behavior with host state and ceilings; neither grants new tools. */
|
|
20504
|
+
function routerCodeModeSettings(profile, host) {
|
|
20505
|
+
if (profile === false || profile === void 0 && host === void 0) return void 0;
|
|
20506
|
+
const environment = typeof host === "object" ? host : {};
|
|
20507
|
+
const node = typeof profile === "object" ? profile : {};
|
|
20508
|
+
const limits = {};
|
|
20509
|
+
for (const key of [
|
|
20510
|
+
"timeoutMs",
|
|
20511
|
+
"memoryLimitBytes",
|
|
20512
|
+
"concurrency",
|
|
20513
|
+
"maxCalls"
|
|
20514
|
+
]) {
|
|
20515
|
+
const ceiling = environment[key];
|
|
20516
|
+
const requested = node[key];
|
|
20517
|
+
for (const value of [ceiling, requested]) {
|
|
20518
|
+
if (value === void 0 || key === "timeoutMs" && value === Infinity) continue;
|
|
20519
|
+
if (!Number.isSafeInteger(value) || value < 1 || key === "timeoutMs" && value > 2147483647) throw new ValidationError$1(`router-tools: invalid codeMode.${key}`);
|
|
20520
|
+
}
|
|
20521
|
+
const value = ceiling === void 0 ? requested : requested === void 0 ? ceiling : Math.min(ceiling, requested);
|
|
20522
|
+
if (value !== void 0) limits[key] = value;
|
|
20523
|
+
}
|
|
20524
|
+
return {
|
|
20525
|
+
...environment,
|
|
20526
|
+
...limits,
|
|
20527
|
+
...environment.directTools || node.directTools ? { directTools: [.../* @__PURE__ */ new Set([...environment.directTools ?? [], ...node.directTools ?? []])] } : {}
|
|
20528
|
+
};
|
|
20529
|
+
}
|
|
19984
20530
|
const routerToolsSeamKey = "router-tools";
|
|
19985
20531
|
function mergePromptCache(target, cache) {
|
|
19986
20532
|
if (!cache) return;
|
|
@@ -20021,6 +20567,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20021
20567
|
tools: seam.tools
|
|
20022
20568
|
}, { multiTurn: true });
|
|
20023
20569
|
if (model === "tangle/auto") assertRouterAutoDeclaration(profileExecution.extraBody?.auto, profileExecution.stream);
|
|
20570
|
+
const codeModeConfig = routerCodeModeSettings(profileExecution.codeMode, seam.codeMode);
|
|
20024
20571
|
const enabledToolNames = new Set(seam.tools.map((tool) => tool.function.name));
|
|
20025
20572
|
const maxTurns = profileExecution.maxTurns ?? 0;
|
|
20026
20573
|
const requestIdentity = routerRequestIdentity(ctx);
|
|
@@ -20063,6 +20610,54 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20063
20610
|
});
|
|
20064
20611
|
};
|
|
20065
20612
|
const external = linkAbort(signal, controller.signal).signal;
|
|
20613
|
+
const executeGranted = async (name, raw, context) => {
|
|
20614
|
+
external.throwIfAborted();
|
|
20615
|
+
context.signal.throwIfAborted();
|
|
20616
|
+
if (!enabledToolNames.has(name)) throw new ValidationError$1(`tool ${name} is not granted`);
|
|
20617
|
+
const args = codeModeArguments(raw);
|
|
20618
|
+
if (context.callId !== context.parentCallId) executedToolCalls.push({
|
|
20619
|
+
id: context.callId,
|
|
20620
|
+
name,
|
|
20621
|
+
arguments: JSON.stringify(args)
|
|
20622
|
+
});
|
|
20623
|
+
const startedAt = Date.now();
|
|
20624
|
+
let status = "ok";
|
|
20625
|
+
try {
|
|
20626
|
+
return await seam.executeToolCall(name, args, task, context);
|
|
20627
|
+
} catch (error) {
|
|
20628
|
+
status = "error";
|
|
20629
|
+
throw error;
|
|
20630
|
+
} finally {
|
|
20631
|
+
const endedAt = Date.now();
|
|
20632
|
+
try {
|
|
20633
|
+
seam.onToolStep?.({
|
|
20634
|
+
toolName: name,
|
|
20635
|
+
args,
|
|
20636
|
+
status,
|
|
20637
|
+
startedAt,
|
|
20638
|
+
endedAt,
|
|
20639
|
+
durationMs: endedAt - startedAt
|
|
20640
|
+
});
|
|
20641
|
+
} catch {}
|
|
20642
|
+
}
|
|
20643
|
+
};
|
|
20644
|
+
const codeMode = codeModeConfig ? createCodeModeTools(seam.tools.map(({ function: tool }) => ({
|
|
20645
|
+
name: tool.name,
|
|
20646
|
+
description: tool.description,
|
|
20647
|
+
inputSchema: tool.parameters,
|
|
20648
|
+
outputSchema: tool.outputSchema,
|
|
20649
|
+
execute: (args, context) => executeGranted(tool.name, args, context)
|
|
20650
|
+
})), codeModeConfig) : void 0;
|
|
20651
|
+
const presentedTools = codeMode ? codeMode.tools.map((tool) => ({
|
|
20652
|
+
type: "function",
|
|
20653
|
+
function: {
|
|
20654
|
+
name: tool.name,
|
|
20655
|
+
description: tool.description,
|
|
20656
|
+
parameters: tool.inputSchema
|
|
20657
|
+
}
|
|
20658
|
+
})) : seam.tools;
|
|
20659
|
+
const modelToolNames = new Set(presentedTools.map((tool) => tool.function.name));
|
|
20660
|
+
const codeByName = new Map(codeMode?.tools.map((tool) => [tool.name, tool]) ?? []);
|
|
20066
20661
|
try {
|
|
20067
20662
|
for (let t = 0; maxTurns === 0 || t < maxTurns; t += 1) {
|
|
20068
20663
|
flush();
|
|
@@ -20083,7 +20678,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20083
20678
|
model,
|
|
20084
20679
|
...profileExecution.retry !== void 0 ? { retry: profileExecution.retry } : {},
|
|
20085
20680
|
...seam.complete ? { complete: seam.complete } : {}
|
|
20086
|
-
}, messages,
|
|
20681
|
+
}, messages, presentedTools, {
|
|
20087
20682
|
...profileExecution.temperature !== void 0 ? { temperature: profileExecution.temperature } : {},
|
|
20088
20683
|
signal: turnController.signal,
|
|
20089
20684
|
onResponse: async (receipt) => {
|
|
@@ -20165,6 +20760,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20165
20760
|
role: "assistant",
|
|
20166
20761
|
content: res.content ?? "",
|
|
20167
20762
|
tool_calls: toolCalls.map((tc) => ({
|
|
20763
|
+
...tc.providerFields,
|
|
20168
20764
|
id: tc.id,
|
|
20169
20765
|
type: "function",
|
|
20170
20766
|
function: {
|
|
@@ -20173,6 +20769,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20173
20769
|
}
|
|
20174
20770
|
}))
|
|
20175
20771
|
});
|
|
20772
|
+
const images = [];
|
|
20176
20773
|
for (let i = 0; i < toolCalls.length; i += 1) {
|
|
20177
20774
|
const tc = toolCalls[i];
|
|
20178
20775
|
const id = tc?.id ?? `call_${i}`;
|
|
@@ -20182,7 +20779,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20182
20779
|
name: toolName,
|
|
20183
20780
|
arguments: tc?.arguments ?? ""
|
|
20184
20781
|
});
|
|
20185
|
-
if (!
|
|
20782
|
+
if (!modelToolNames.has(toolName)) {
|
|
20186
20783
|
messages.push({
|
|
20187
20784
|
role: "tool",
|
|
20188
20785
|
tool_call_id: id,
|
|
@@ -20209,34 +20806,38 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20209
20806
|
continue;
|
|
20210
20807
|
}
|
|
20211
20808
|
let result;
|
|
20212
|
-
let
|
|
20213
|
-
const toolStartedAt = Date.now();
|
|
20809
|
+
let succeeded = true;
|
|
20214
20810
|
try {
|
|
20215
|
-
|
|
20811
|
+
const context = {
|
|
20812
|
+
signal: AbortSignal.any([external, turnController.signal]),
|
|
20813
|
+
callId: id,
|
|
20814
|
+
parentCallId: id
|
|
20815
|
+
};
|
|
20816
|
+
result = codeMode ? await codeByName.get(toolName).execute(args, context) : await executeGranted(toolName, args, context);
|
|
20216
20817
|
} catch (e) {
|
|
20217
|
-
|
|
20818
|
+
succeeded = false;
|
|
20218
20819
|
result = `error: ${e instanceof Error ? e.message : String(e)}`;
|
|
20219
20820
|
}
|
|
20220
|
-
const
|
|
20821
|
+
const projected = succeeded && codeMode && toolName === "codemode" ? codeModeModelOutput(result) : void 0;
|
|
20822
|
+
if (projected) images.push(...projected.images);
|
|
20221
20823
|
messages.push({
|
|
20222
20824
|
role: "tool",
|
|
20223
20825
|
tool_call_id: id,
|
|
20224
|
-
content: result
|
|
20826
|
+
content: projected?.text ?? toolResultText(result)
|
|
20225
20827
|
});
|
|
20226
|
-
try {
|
|
20227
|
-
seam.onToolStep?.({
|
|
20228
|
-
toolName,
|
|
20229
|
-
args,
|
|
20230
|
-
status,
|
|
20231
|
-
startedAt: toolStartedAt,
|
|
20232
|
-
endedAt: toolEndedAt,
|
|
20233
|
-
durationMs: toolEndedAt - toolStartedAt
|
|
20234
|
-
});
|
|
20235
|
-
} catch {}
|
|
20236
20828
|
}
|
|
20829
|
+
if (images.length) messages.push({
|
|
20830
|
+
role: "user",
|
|
20831
|
+
content: [{
|
|
20832
|
+
type: "text",
|
|
20833
|
+
text: "Images emitted by codemode:"
|
|
20834
|
+
}, ...images]
|
|
20835
|
+
});
|
|
20237
20836
|
}
|
|
20238
20837
|
} finally {
|
|
20239
|
-
|
|
20838
|
+
const saved = structuredClone(messages);
|
|
20839
|
+
if (codeMode) await seam.onMessages?.(saved, { codeModeStore: codeMode.snapshotStore() });
|
|
20840
|
+
else await seam.onMessages?.(saved);
|
|
20240
20841
|
}
|
|
20241
20842
|
const estimatedUsd = priceTokens({
|
|
20242
20843
|
model,
|
|
@@ -20256,6 +20857,10 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20256
20857
|
};
|
|
20257
20858
|
const out = {
|
|
20258
20859
|
content: lastText,
|
|
20860
|
+
...codeMode ? {
|
|
20861
|
+
codeModeStore: codeMode.snapshotStore(),
|
|
20862
|
+
modelToolNames: [...modelToolNames]
|
|
20863
|
+
} : {},
|
|
20259
20864
|
...observedModel !== void 0 ? { model: observedModel } : {},
|
|
20260
20865
|
messages,
|
|
20261
20866
|
turns,
|
|
@@ -20309,6 +20914,7 @@ const routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
20309
20914
|
provider: spec.profile.model?.provider ?? null,
|
|
20310
20915
|
maxTurns,
|
|
20311
20916
|
tools: seam.tools,
|
|
20917
|
+
...seam.codeMode ? { codeMode: seam.codeMode } : {},
|
|
20312
20918
|
temperature: profileExecution.temperature ?? null,
|
|
20313
20919
|
tokenLimits: profileExecution.tokenLimits,
|
|
20314
20920
|
retry: profileExecution.retry ?? null,
|
|
@@ -21474,6 +22080,7 @@ function routerProfileExecution(profile, seam, mode) {
|
|
|
21474
22080
|
const profileEffort = profile.model?.reasoningEffort;
|
|
21475
22081
|
const settings = profileModelExecutionSettings(profile, "routerInlineExecutor");
|
|
21476
22082
|
if (!mode.multiTurn && settings.maxTurns !== void 0) throw new ValidationError$1("routerInlineExecutor: AgentProfile.model.metadata.maxTurns requires the router-tools backend");
|
|
22083
|
+
if (!mode.multiTurn && settings.codeMode !== void 0) throw new ValidationError$1("routerInlineExecutor: AgentProfile.model.metadata.codeMode requires the router-tools backend");
|
|
21477
22084
|
if (settings.stream === true && seam.complete !== void 0) throw new ValidationError$1("routerInlineExecutor: AgentProfile.model.metadata.stream requires the HTTP Router transport; RouterSeam.complete returns one buffered completion and cannot serve a stream");
|
|
21478
22085
|
const declaredTools = profile.tools ?? {};
|
|
21479
22086
|
const suppliedTools = seam.tools ?? [];
|
|
@@ -22451,7 +23058,7 @@ async function startRetainedInteractiveRun(options) {
|
|
|
22451
23058
|
assertStableText(identity.executionId, "retained execution id");
|
|
22452
23059
|
const intent = interactiveIntent(startOptions, profile, identity);
|
|
22453
23060
|
if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
|
|
22454
|
-
else assertExactInteractiveIntent(startOptions.intent, intent);
|
|
23061
|
+
else assertExactInteractiveIntent(startOptions.intent, intent, () => interactiveIntent(startOptions, profile, identity, legacyRetainedCreateMaterial));
|
|
22455
23062
|
const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
|
|
22456
23063
|
assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
|
|
22457
23064
|
const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
|
|
@@ -22572,7 +23179,7 @@ function interactiveRequest(options, environment, profile, requestedProfileDiges
|
|
|
22572
23179
|
...start
|
|
22573
23180
|
});
|
|
22574
23181
|
}
|
|
22575
|
-
function interactiveIntent(options, profile, identity) {
|
|
23182
|
+
function interactiveIntent(options, profile, identity, createMaterial = retainedCreateMaterial) {
|
|
22576
23183
|
const requestedProfileDigest = canonicalAgentProfileDigest(profile);
|
|
22577
23184
|
const requestDigest = canonicalCandidateDigest({
|
|
22578
23185
|
kind: "retained-interactive-intent.v1",
|
|
@@ -22582,7 +23189,7 @@ function interactiveIntent(options, profile, identity) {
|
|
|
22582
23189
|
sessionId: identity.sessionId,
|
|
22583
23190
|
executionId: identity.executionId,
|
|
22584
23191
|
requestedProfileDigest,
|
|
22585
|
-
create:
|
|
23192
|
+
create: createMaterial(options.environment),
|
|
22586
23193
|
start: sanitizedStartMaterial(options)
|
|
22587
23194
|
});
|
|
22588
23195
|
return {
|
|
@@ -22605,8 +23212,11 @@ function sanitizedStartMaterial(options) {
|
|
|
22605
23212
|
...options.rows === void 0 ? {} : { rows: options.rows }
|
|
22606
23213
|
};
|
|
22607
23214
|
}
|
|
22608
|
-
function assertExactInteractiveIntent(received, expected) {
|
|
22609
|
-
|
|
23215
|
+
function assertExactInteractiveIntent(received, expected, legacyExpected) {
|
|
23216
|
+
const stableReceived = parseInteractiveIntent(received);
|
|
23217
|
+
if (canonicalCandidateDigest(stableReceived) !== canonicalCandidateDigest(expected)) {
|
|
23218
|
+
if (legacyExpected === void 0 || canonicalCandidateDigest(stableReceived) !== canonicalCandidateDigest(legacyExpected())) throw new Error("interactive intent conflicts with replay material");
|
|
23219
|
+
}
|
|
22610
23220
|
}
|
|
22611
23221
|
function parseInteractiveIntent(value) {
|
|
22612
23222
|
const stable = detachedSnapshot(value, "interactive intent");
|
|
@@ -24526,6 +25136,7 @@ async function captureBeforeCleanup(state, branching, event, events, parent) {
|
|
|
24526
25136
|
const provider = state.provider;
|
|
24527
25137
|
if (provider?.get === void 0) return refuse("the provider cannot reconstruct a fork of the checkpoint", false);
|
|
24528
25138
|
const get = provider.get.bind(provider);
|
|
25139
|
+
if (parent?.aborted) return refuse(`capture failed: ${errorText(abortError(parent, "capture stopped").message)}`, true);
|
|
24529
25140
|
if (branching === void 0) return refuse("source-scoped checkpoint handle unavailable", true);
|
|
24530
25141
|
const material = {
|
|
24531
25142
|
checkpoint: event.checkpoint,
|
|
@@ -24787,12 +25398,23 @@ async function scopeRetainedOwnerSettled(scope) {
|
|
|
24787
25398
|
await state.releasing?.catch(() => void 0);
|
|
24788
25399
|
}
|
|
24789
25400
|
/**
|
|
25401
|
+
* How long one release spends capturing the owner's pending checkpoints, all of them together. A
|
|
25402
|
+
* capture it cuts short keeps its checkpoint and the source, as a failed capture does, and the
|
|
25403
|
+
* release goes on to settle. Each capture is otherwise bounded only by its port, and one at a
|
|
25404
|
+
* time: on Discovery run terraform-dc-model-20261010h-c1 (Runtime 0.314.0) a director's release
|
|
25405
|
+
* waited 00:19:18Z to 01:19:38Z for one capture to reach the port's 60-minute bound, and the run
|
|
25406
|
+
* settled 98 minutes after its deadline. The release captures that finished there took 67 seconds
|
|
25407
|
+
* and 7 and 34 minutes, beside live captures of abandoned directors on the same slots.
|
|
25408
|
+
*/
|
|
25409
|
+
const RELEASE_CHECKPOINT_CAPTURES_MS = 15 * 6e4;
|
|
25410
|
+
/**
|
|
24790
25411
|
* Release the owner's environment once no turn of it will run again: at the run's final
|
|
24791
25412
|
* settlement for the root, and when a nested manager's own scope has finished. A second call while
|
|
24792
25413
|
* one is in flight joins it. The release first waits for the end-of-turn capture of the owner's
|
|
24793
|
-
* last turn, so the capture always precedes the destroy.
|
|
25414
|
+
* last turn, so the capture always precedes the destroy. `capturesMs` bounds the checkpoint
|
|
25415
|
+
* captures it runs ({@link RELEASE_CHECKPOINT_CAPTURES_MS}).
|
|
24794
25416
|
*/
|
|
24795
|
-
function releaseScopeRetainedOwnerEnvironment(scope) {
|
|
25417
|
+
function releaseScopeRetainedOwnerEnvironment(scope, { capturesMs = RELEASE_CHECKPOINT_CAPTURES_MS } = {}) {
|
|
24796
25418
|
const state = owners.get(scope);
|
|
24797
25419
|
const provider = state?.provider;
|
|
24798
25420
|
if (state === void 0 || provider === void 0) return Promise.resolve([]);
|
|
@@ -24800,14 +25422,14 @@ function releaseScopeRetainedOwnerEnvironment(scope) {
|
|
|
24800
25422
|
const tracked = (async () => {
|
|
24801
25423
|
await ownerDriveEnded(state);
|
|
24802
25424
|
await scopeRetainedOwnerTurnEnded(scope);
|
|
24803
|
-
return await releaseOwnerEnvironment(state, provider);
|
|
25425
|
+
return await releaseOwnerEnvironment(state, provider, capturesMs);
|
|
24804
25426
|
})().finally(() => {
|
|
24805
25427
|
if (state.releasing === tracked) delete state.releasing;
|
|
24806
25428
|
});
|
|
24807
25429
|
state.releasing = tracked;
|
|
24808
25430
|
return tracked;
|
|
24809
25431
|
}
|
|
24810
|
-
async function releaseOwnerEnvironment(state, provider) {
|
|
25432
|
+
async function releaseOwnerEnvironment(state, provider, capturesMs) {
|
|
24811
25433
|
const { args } = state;
|
|
24812
25434
|
state.checkpointsUnavailable ??= "released";
|
|
24813
25435
|
await state.checkpointing?.catch(() => void 0);
|
|
@@ -24825,11 +25447,17 @@ async function releaseOwnerEnvironment(state, provider) {
|
|
|
24825
25447
|
const checkpointsKept = [];
|
|
24826
25448
|
const uncapturedSources = /* @__PURE__ */ new Set();
|
|
24827
25449
|
const pending = pendingCheckpoints(events, state).filter((event) => !retentionFailures.has(event.environmentId));
|
|
24828
|
-
|
|
24829
|
-
|
|
24830
|
-
|
|
24831
|
-
|
|
24832
|
-
|
|
25450
|
+
const captures = new AbortController();
|
|
25451
|
+
const capturesTimer = setTimeout(() => captures.abort(/* @__PURE__ */ new Error(`the release's ${capturesMs} ms for checkpoint captures ran out; checkpoint and source kept`)), capturesMs);
|
|
25452
|
+
try {
|
|
25453
|
+
for (const sourceEnvironmentId of new Set(pending.map((event) => event.environmentId))) {
|
|
25454
|
+
const cleaned = await cleanCheckpoints(state, await checkpointHandle(state, sourceEnvironmentId, AbortSignal.any([captures.signal, AbortSignal.timeout(3e4)])), pending.filter((event) => event.environmentId === sourceEnvironmentId), events, captures.signal);
|
|
25455
|
+
checkpointFailures.push(...cleaned.unconfirmed);
|
|
25456
|
+
checkpointsKept.push(...cleaned.refused);
|
|
25457
|
+
for (const refusal of cleaned.refused) if (refusal.needsSource) uncapturedSources.add(sourceEnvironmentId);
|
|
25458
|
+
}
|
|
25459
|
+
} finally {
|
|
25460
|
+
clearTimeout(capturesTimer);
|
|
24833
25461
|
}
|
|
24834
25462
|
const forksUnresolved = await settleCaptureForks(state);
|
|
24835
25463
|
for (const event of checkpointFailures) pendingSources.add(event.environmentId);
|
|
@@ -28644,7 +29272,7 @@ function isUpstreamUnavailable(error) {
|
|
|
28644
29272
|
*/
|
|
28645
29273
|
function classifyDriverFailure(error, signal) {
|
|
28646
29274
|
if (signal?.aborted) return "terminal";
|
|
28647
|
-
if (error instanceof RetainedExecutionPendingError && error.pendingCause === "provider-contract") return "terminal";
|
|
29275
|
+
if (error instanceof RetainedExecutionPendingError && (error.pendingCause === "provider-contract" || error.pendingCause === "terminal-event-lost")) return "terminal";
|
|
28648
29276
|
const admission = retainedAdmissionCause(error);
|
|
28649
29277
|
if (admission !== void 0 && isDispatchNotAdmitted(admission)) return "terminal";
|
|
28650
29278
|
if (admission !== void 0) return classifyDriverFailure(admission, signal);
|
|
@@ -28882,6 +29510,7 @@ async function runDriverWithRetry(run) {
|
|
|
28882
29510
|
const after = run.progress();
|
|
28883
29511
|
const progressed = madeProgress(before, after);
|
|
28884
29512
|
if (progressed) abandonments = 0;
|
|
29513
|
+
const retainedFailure = error instanceof RetainedExecutionPendingError ? error : void 0;
|
|
28885
29514
|
const pending = abandonablePending(error);
|
|
28886
29515
|
samePending = pending === void 0 || classification !== "transient" ? void 0 : {
|
|
28887
29516
|
cause: pending.pendingCause,
|
|
@@ -28971,7 +29600,7 @@ async function runDriverWithRetry(run) {
|
|
|
28971
29600
|
classification,
|
|
28972
29601
|
madeProgress: progressed,
|
|
28973
29602
|
stop: retryStop,
|
|
28974
|
-
...
|
|
29603
|
+
...retainedFailure === void 0 ? {} : { pendingCause: retainedFailure.pendingCause }
|
|
28975
29604
|
});
|
|
28976
29605
|
throw new DriverAttemptsExhaustedError(error, attempts, retryStop);
|
|
28977
29606
|
}
|
|
@@ -30220,6 +30849,6 @@ function isNonEmptySpend(s) {
|
|
|
30220
30849
|
return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.values(s.resources ?? {}).some((resource) => resource.amount > 0 || !resource.known);
|
|
30221
30850
|
}
|
|
30222
30851
|
//#endregion
|
|
30223
|
-
export { environmentReader as $,
|
|
30852
|
+
export { environmentReader as $, runtimeOwnedScopeOwnerRuntime as $i, parseWorkerToolTraceArtifact as $n, loopEventToOtelSpan as $r, PEER_MAIL_WIRE_KEY as $t, scopeOwnerExecutorNodeContext as A, promptOnlyProfileMaterialization as Ai, resolveAgentEnvironmentProvider as An, resolveHarnessTranscriptCapture as Ar, captureReusableExecutorConfig as At, consumeScopeRetainedOwnerResult as B, authoredProfileDigest as Bi, InMemoryResultBlobStore as Bn, mergeTraceEnv as Br, createInPlaceCliExecutor as Bt, deriveNodeExecutionIdentity as C, promptFromAgentTurnInput as Ca, assertProfileMaterializes as Ci, readPromptOptions as Cn, abortError as Cr, createContinuationKeeper as Ct, recordScopeOwnerMaterialization as D, profileMaterializationAxes$1 as Di, createAgentEnvironmentProviderRegistry as Dn, harnessTranscriptArtifact as Dr, passedItems as Dt, recordScopeOwnerDriverAttempt as E, fullProfileMaterialization as Ei, LEAF_CONTINUATION_TASK as En, captureHarnessTranscript as Er, failedItems as Et, seatExecutionProfile as F, unsupportedProfileDimensions as Fi, retainedExecutorSeamKey as Fn, runCodeMode as Fr, snapshotExecutorConfig as Ft, scopeRetainedOwnerContext as G, newExecutionAttemptId as Gi, replaySpawnTree as Gn, resolveRedactor as Gr, workerTraceSeamKey as Gt, prepareScopeRetainedOwnerSeatSwitch as H, inheritRuntimeOwnedExecutorAttestation as Hi, insideCursorNamespace as Hn, traceContextToEnv as Hr, readWorkerTraceContext as Ht, abandonScopeRetainedOwnerInvocation as I, validateProfileMaterialization as Ii, unavailablePauseMs as In, priceTokens as Ir, createWorktreeCliExecutor as It, scopeRetainedOwnerResourceReader as J, runtimeOwnedDriveHarnessProviderEvidence as Ji, readCommittedJsonLines as Jn, buildRuntimeEventOtelSpans as Jr, createActivityLog as Jt, scopeRetainedOwnerJournalRoot as K, providerAttemptEvidence as Ki, isNoEntError as Kn, buildLoopOtelSpans as Kr, taskToPrompt as Kt, beginScopeRetainedOwnerDrive as L, worktreeCliProfileMaterialization as Li, unavailableSignalOfFailure as Ln, routerTokenPrice as Lr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as Lt, SeatChain as M, renderProfileMaterializationIssues as Mi, decodeToolPart as Mn, contentAddress as Mr, cliWorktreeExecutor as Mt, SeatChainExhaustedError as N, renderUnsupported as Ni, sandboxSessionTraceSource as Nn, createCodeModeTools as Nr, createExecutor as Nt, recordScopeOwnerPause as O, promptControlProfileMaterialization as Oi, providerAsExecutor as On, persistHarnessTranscript as Or, verdictFromJudgeScore as Ot, authoredSeatStages as P, sandboxActProfileMaterialization as Pi, registerRetainedExecutorPreparation as Pn, describeCodeModeTools as Pr, createExecutorRegistry as Pt, SPAWN_RESOURCE_PATH_MAX_BYTES as Q, runtimeOwnedPendingExecutorMaterialization as Qi, isTraceAnalysisStore as Qn, generateSpanId as Qr, DEFAULT_PEER_MAIL_LIMITS as Qt, bindScopeRetainedOwnerEnvironmentId as R, attestRuntimeOwnedPendingExecutor as Ri, FileResultBlobStore as Rn, ROUTER_PRICE_SOURCE as Rr, createSteerableSandboxSession as Rt, createScope as S, awaitAbortable$1 as Sa, assertProfileMaterialization as Si, assertBoxlessPromptOptions as Sn, RunCancellationReason as Sr, checkVerdictOf as St, meterRuntimeOwnedProviderAttempt as T, providerMessageText as Ta, defineProfileMaterializationContract as Ti, runBrainLoop as Tn, runAbortable as Tr, expandQuestions as Tt, prepareScopeRetainedOwnerTask as U, knownExecutionBindingReceipt as Ui, loadSpawnForest as Un, defaultRedactor as Ur, workerTraceEnv as Ut, noteScopeRetainedOwnerCoordination as V, finalizeRuntimeOwnedPendingExecutor as Vi, InMemorySpawnJournal as Vn, readTraceContextFromEnv as Vr, WORKER_TRACE_PROPAGATION as Vt, reconcileScopeRetainedOwnerEnvironment as W, knownMaterializationReceipt as Wi, materializeTreeView as Wn, defaultRedactorIdentityMaterial as Wr, workerTraceHeaders as Wt, scopeRetainedOwnerResult as X, runtimeOwnedExecutorMaterialization as Xi, WORKER_TOOL_TRACE_SCHEMA_VERSION as Xn, createOtelExporter as Xr, createInbox as Xt, scopeRetainedOwnerRestorePoint as Y, runtimeOwnedExecutorExecutionBinding as Yi, writeAllBytes as Yn, createOpenInferenceFileExporter as Yr, readWorkerProgress as Yt, scopeRetainedOwnerTurnEnded as Z, runtimeOwnedExecutorProviderEvidence as Zi, captureWorkerTraceEvidence as Zn, flatOtelSpan as Zr, AUTHORITY_MARKERS as Zt, isDriverSpec as _, sandboxEventServedBackend as _a, localHarnessExecutable as _i, runAgentRounds as _n, retainedCreateMaterial as _r, CONTINUATION_FACTS as _t, collectDelivered as a, detachedSnapshot as aa, sanitizeAgentRuntimeEvent as ai, isLiveNodeStatus as an, createBudgetPool as ar, interactiveAdmissionSeamKey as at, assertRecursiveReservationPolicy as b, decodeHarnessUsage as ba, terminateProcessTreeAndConfirm as bi, SandboxEvidenceRetentionError as bn, createWorkerSlots as br, admitFinding as bt, runTree as c, assertSandboxServedModel as ca, runSettledCommand as ci, bridgeModelRouteRefusal as cn, spendFromUsageEvents as cr, reconnectRetainedInteractiveRun as ct, classifyDriverFailure as d, createSandboxUsageLedger as da, createWorktree as di, harnessUsageIsEmpty as dn, bridgeStopSignalKey as dr, freeSlots as dt, unknownExecutionBindingReceipt as ea, padSpanId as ei, claimsAuthority as en, workerTraceAnalysisStore as er, hostDirectoryReader as et, runDriverWithRetry as f, extractLlmCallEvent as fa, removeWorktree as fi, readCodexRolloutSession as fn, errMessage as fr, queueOf as ft, driverExecutorFactory as g, notifySandboxEventObserver as ga, harnessSupportsReasoningEffort as gi, isTerminalDecision as gn, startRetainedRunInEnvironment as gr, CONTINUATIONS_DIR as gt, driverChild as h, mapSandboxToolEvent as ha, harnessInvocation as hi, defaultSelectWinner as hn, startRetainedRun as hr, mapExecutorResult as ht, bestDelivered as i, detachedFrozen as ia, createRuntimeStreamEventCollector as ii, peerMailVerbNames as in, assertValidBudget as ir, providerVisibleProfile as it, settledToIteration as j, promptResourceProfileMaterialization as ji, createPushTraceSource as jn, retainHarnessTranscript as jr, cliInPlaceExecutor as jt, restoreScopeOwnerAcceptedExecution as k, promptModelProfileMaterialization as ki, providerAsSandboxClient as kn, readHarnessTranscript as kr, bindReusableExecutorExecutionId as kt, DriverAttemptsExhaustedError as l, canonicalStreamEventFromSandboxEvent as la, runWorktreeHarness as li, addHarnessUsage as ln, spendFromUsageTotals as lr, recoverRetainedInteractiveRun as lt, upstreamUnavailableSignal as m, mapSandboxEvent as ma, LOCAL_HARNESSES as mi, createSandboxForSpec as mn, recoverRetainedRun as mr, gateOnDeliverable as mt, createRootHandle as n, executableAgentProfileSnapshot as na, toOtelAttributes as ni, isPeerMailEnvelope as nn, BudgetReconcileFault as nr, coordinationMcpAlias as nt, pickBestDelivered as o, projectSandboxOutcome as oa, sanitizeKnowledgeReadinessReport as oi, isTerminalNodeStatus as on, meterUsageEvent as or, attachWorker as ot, summarizeDriverAttempts as p, isSandboxTerminalEvent as pa, DEFAULT_LOCAL_HARNESS as pi, TERMINAL_DECISIONS as pn, reconnectRetainedRun as pr, rollingDispatch as pt, scopeRetainedOwnerPriorSpend as q, recordRuntimeOwnedDriveHarnessProviderEvidence as qi, prepareJsonlAppend as qn, buildLoopSpanNodes as qr, DEFAULT_STALL_AFTER_MS as qt, createSupervisor as r, executableAgentSpecSnapshot as ra, createRuntimeEventCollector as ri, peerMailTools as rn, ReservationWaitRefused as rr, coordinationProfileToolPrefix as rt, runFinalizer as s, readSandboxOutcome as sa, sanitizeRuntimeStreamEvent as si, bridgeAdmissionRefusal as sn, newUsageTotals as sr, readWorkerInteractiveBinding as st, DEFAULT_MAX_DEPTH as t, unknownMaterializationReceipt as ta, padTraceId as ti, createPeerMailbox as tn, executorFailure as tr, resolveSpawnResourcePaths as tt, HarnessTurnFailedError as u, createSandboxToolPartState as ua, captureWorktreeDiff as ui, createCodexRolloutStoreReader as un, bridgeRuntimeAttachmentsKey as ur, startRetainedInteractiveRun as ut, withDriverExecutor as v, sandboxProgressEvents as va, parseCodexTokenUsage as vi, createSandboxLineage as vn, destroyInteractiveEnvironment as vr, CheckUnavailableError as vt, meterRuntimeOwnedAccounting as w, promptOptionsFromAgentTurnInput as wa, controlProfileMaterialization as wi, routerBrain as wn, linkAbort as wr, distillFindings as wt, beginScopeOwnerAttempt as x, abortError$1 as xa, AGENT_PROFILE_MATERIALIZATION_AXES as xi, captureBeforeDestroy as xn, openSlotGroup as xr, bestComposite as xt, SUBTREE_RESULT_LIMIT as y, sumSandboxUsage as ya, CodexExecutionDiagnosticError as yi, acquireSandbox as yn, environmentGone as yr, admitContinuationPolicy as yt, bindScopeRetainedOwnerProvider as z, attestRuntimeOwnedScopeOwner as zi, FileSpawnJournal as zn, createPropagatingTraceEmitter as zr, createRouterTranscript as zt };
|
|
30224
30853
|
|
|
30225
|
-
//# sourceMappingURL=supervisor-
|
|
30854
|
+
//# sourceMappingURL=supervisor-Cqhu3xH-.js.map
|