@yielded/agent 0.1.0-beta.173 → 0.1.0-beta.174
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/{Admin-BX9ns28E.d.mts → Admin-BHmp2V9p.d.mts} +25 -16
- package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
- package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
- package/dist/Agent-BiRbr73L.mjs.map +1 -0
- package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-B6qZlD3f.mjs} +199 -191
- package/dist/AgentRuntime-B6qZlD3f.mjs.map +1 -0
- package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-BD3ZHAMq.d.mts} +10 -10
- package/dist/{Digest-DCuPlhNk.mjs → Digest-EpeqWEdv.mjs} +41 -14
- package/dist/Digest-EpeqWEdv.mjs.map +1 -0
- package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CBBjRNJN.mjs} +1447 -1424
- package/dist/DurableAgentRuntime-CBBjRNJN.mjs.map +1 -0
- package/dist/{EventSource-BwliwQz9.d.mts → EventSource-C9aaJaXT.d.mts} +2 -2
- package/dist/{MessageDelivery-B943ebI_.d.mts → MessageDelivery-BGDm-c46.d.mts} +42 -42
- package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
- package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
- package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-BvDqlgiP.d.mts} +3 -3
- package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-4ZATcVLB.mjs} +113 -56
- package/dist/RunContinuation-4ZATcVLB.mjs.map +1 -0
- package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-CTJ1jGrO.d.mts} +6 -6
- package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CNZqA3Ge.mjs} +33 -5
- package/dist/RunJournal-CNZqA3Ge.mjs.map +1 -0
- package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
- package/dist/{RunStorage-uqPxps09.mjs → RunStorage-BHjuuERI.mjs} +9 -6
- package/dist/RunStorage-BHjuuERI.mjs.map +1 -0
- package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-NG8slKdI.mjs} +11 -11
- package/dist/Scheduling-NG8slKdI.mjs.map +1 -0
- package/dist/{Subagent-vpffemql.mjs → Subagent-CTIpnzlB.mjs} +53 -40
- package/dist/Subagent-CTIpnzlB.mjs.map +1 -0
- package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-DKhZA72u.d.mts} +19 -8
- package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
- package/dist/{Subscription-DONig54Q.d.mts → Subscription-BNg9VCRl.d.mts} +2 -2
- package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-BUoXv-_K.d.mts} +2 -2
- package/dist/{ThreadImport-DpHxjBrA.d.mts → ThreadImport-CMgzttvr.d.mts} +5 -5
- package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CodYoJoa.mjs} +7 -7
- package/dist/ThreadImport-CodYoJoa.mjs.map +1 -0
- package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-59uDGXul.mjs} +163 -84
- package/dist/ThreadStore-59uDGXul.mjs.map +1 -0
- package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-3jigUl3g.mjs} +3 -3
- package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-3jigUl3g.mjs.map} +1 -1
- package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-DDYJdOsU.mjs} +4 -4
- package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-DDYJdOsU.mjs.map} +1 -1
- package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-DRbyhAu-.mjs} +69 -56
- package/dist/agent-registration-DRbyhAu-.mjs.map +1 -0
- package/dist/capabilities/Approval.mjs +2 -2
- package/dist/capabilities/Approval.mjs.map +1 -1
- package/dist/capabilities/BrowserUse.d.mts +102 -1867
- package/dist/capabilities/BrowserUse.mjs +74 -798
- package/dist/capabilities/BrowserUse.mjs.map +1 -1
- package/dist/capabilities/Budget.mjs +3 -1
- package/dist/capabilities/Budget.mjs.map +1 -1
- package/dist/capabilities/CodeMode.d.mts +1 -1
- package/dist/capabilities/CodeMode.mjs +16 -9
- package/dist/capabilities/CodeMode.mjs.map +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/McpClient.mjs +1 -1
- package/dist/capabilities/McpClient.mjs.map +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +4 -4
- package/dist/capabilities/Messaging.mjs.map +1 -1
- package/dist/capabilities/ModelContext.mjs +7 -5
- package/dist/capabilities/ModelContext.mjs.map +1 -1
- package/dist/capabilities/Redaction.mjs +49 -19
- package/dist/capabilities/Redaction.mjs.map +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/RunHooks.mjs +1 -1
- package/dist/capabilities/RunHooks.mjs.map +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/SubagentReservations.mjs +3 -1
- package/dist/capabilities/SubagentReservations.mjs.map +1 -1
- package/dist/capabilities/WebCapture.mjs.map +1 -1
- package/dist/capabilities/WebSearch.mjs +7 -7
- package/dist/capabilities/WebSearch.mjs.map +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/AgentUpdates.mjs +8 -8
- package/dist/core/AgentUpdates.mjs.map +1 -1
- package/dist/core/Thread.mjs +1 -1
- package/dist/core/Thread.mjs.map +1 -1
- package/dist/core/Usage.mjs +2 -2
- package/dist/core/Usage.mjs.map +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +2 -2
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +6 -6
- package/dist/durable/EventSource.mjs.map +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +1 -1
- package/dist/durable/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +3 -3
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +2 -2
- package/dist/durable/RecordFormat.mjs.map +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunContinuation.d.mts +2 -2
- package/dist/durable/RunContinuation.mjs +2 -2
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/RunStorage.d.mts +1 -1
- package/dist/durable/RunStorage.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SettlementPublisher.d.mts +1 -1
- package/dist/durable/SettlementPublisher.mjs +2 -2
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +5 -1
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +4 -4
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +3 -3
- package/dist/durable/SubscriptionInput.mjs.map +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +2 -2
- package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +2 -2
- package/dist/durable/Subscriptions.mjs.map +1 -1
- package/dist/durable/ThreadArchiveRange.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +1 -1
- package/dist/durable/ThreadImport.d.mts +1 -1
- package/dist/durable/ThreadImport.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +3 -3
- package/dist/durable/ThreadInvariants.mjs +4 -4
- package/dist/durable/ThreadInvariants.mjs.map +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadReader.d.mts +1 -1
- package/dist/durable/ThreadReader.mjs +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +3 -3
- package/dist/durable/ThreadTransfer.d.mts +1 -1
- package/dist/durable/ThreadTransfer.mjs +1 -1
- package/dist/durable/ThreadWork.d.mts +1 -1
- package/dist/durable/ThreadWork.mjs +4 -4
- package/dist/durable/ThreadWork.mjs.map +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +2 -2
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/index.d.mts +19 -19
- package/dist/index.mjs +14 -14
- package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-CC7ZD95F.d.mts} +2 -2
- package/package.json +1 -1
- package/src/capabilities/Approval.ts +58 -60
- package/src/capabilities/BrowserUse.ts +89 -944
- package/src/capabilities/Budget.ts +8 -1
- package/src/capabilities/CodeMode.ts +57 -33
- package/src/capabilities/McpClient.ts +2 -2
- package/src/capabilities/Messaging.ts +51 -55
- package/src/capabilities/ModelContext.ts +5 -2
- package/src/capabilities/Redaction.ts +64 -34
- package/src/capabilities/RunHooks.ts +52 -55
- package/src/capabilities/Subagent.ts +33 -33
- package/src/capabilities/SubagentReservations.ts +9 -1
- package/src/capabilities/WebCapture.ts +6 -0
- package/src/capabilities/WebSearch.ts +10 -7
- package/src/capabilities/internal/subagent-background.ts +202 -158
- package/src/core/Agent.ts +11 -6
- package/src/core/AgentUpdates.ts +8 -8
- package/src/core/Thread.ts +9 -10
- package/src/core/Usage.ts +7 -8
- package/src/core/internal/agent-updates.ts +1 -0
- package/src/durable/DurableAgentRuntime.ts +645 -625
- package/src/durable/EventSource.ts +15 -9
- package/src/durable/RecordFormat.ts +5 -3
- package/src/durable/RunContinuation.ts +233 -81
- package/src/durable/RunJournal.ts +10 -9
- package/src/durable/RunStorage.ts +122 -124
- package/src/durable/Scheduling.ts +639 -651
- package/src/durable/SubmissionLedger.ts +4 -0
- package/src/durable/SubscriptionInput.ts +5 -3
- package/src/durable/SubscriptionStoreConformance.ts +23 -23
- package/src/durable/Subscriptions.ts +18 -19
- package/src/durable/ThreadImport.ts +18 -19
- package/src/durable/ThreadInvariants.ts +2 -1
- package/src/durable/ThreadStore.ts +215 -111
- package/src/durable/ThreadWork.ts +1 -2
- package/src/durable/internal/StorageOwner.ts +10 -4
- package/src/durable/internal/agent-registration.ts +96 -89
- package/src/durable/internal/canonical-json.ts +61 -20
- package/src/durable/internal/prompt-history-cache.ts +13 -4
- package/src/durable/internal/record-encoding.ts +120 -64
- package/src/durable/internal/schedule-time.ts +6 -6
- package/src/durable/internal/usage-totals.ts +38 -0
- package/src/durable/internal/worker-host.ts +69 -74
- package/src/engine/internal/agent-runtime.ts +1067 -1018
- package/src/engine/internal/provisional-text.ts +12 -10
- package/src/engine/internal/tool-exposure.ts +22 -18
- package/src/engine/internal/tool-telemetry.ts +12 -7
- package/dist/Agent-0WvBWWbM.mjs.map +0 -1
- package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
- package/dist/Digest-DCuPlhNk.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
- package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
- package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
- package/dist/RunStorage-uqPxps09.mjs.map +0 -1
- package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
- package/dist/Subagent-vpffemql.mjs.map +0 -1
- package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
- package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
- package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
|
@@ -961,24 +961,20 @@ const schemaClassToolPartPreflight = <Tools extends Record<string, Tool.Any>>(
|
|
|
961
961
|
try {
|
|
962
962
|
if (part === null || typeof part !== "object") return undefined;
|
|
963
963
|
|
|
964
|
-
const read = (key: string):
|
|
964
|
+
const read = (key: string): PropertyDescriptor | undefined => {
|
|
965
965
|
const descriptor = Object.getOwnPropertyDescriptor(part, key);
|
|
966
966
|
|
|
967
|
-
|
|
968
|
-
throw new TypeError(`response part ${key} must be an own data property`);
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
return descriptor.value;
|
|
967
|
+
return descriptor !== undefined && "value" in descriptor ? descriptor : undefined;
|
|
972
968
|
};
|
|
973
969
|
|
|
974
|
-
const type = read("type");
|
|
970
|
+
const type = read("type")?.value;
|
|
975
971
|
|
|
976
972
|
if (type !== "tool-call" && type !== "tool-result") return undefined;
|
|
977
|
-
const name = read("name");
|
|
973
|
+
const name = read("name")?.value;
|
|
978
974
|
|
|
979
975
|
if (typeof name !== "string" || !hasTool(toolkit.tools, name)) return undefined;
|
|
980
976
|
const tool = toolkit.tools[name];
|
|
981
|
-
const payload = read(type === "tool-call" ? "params" : "result");
|
|
977
|
+
const payload: unknown = read(type === "tool-call" ? "params" : "result")?.value;
|
|
982
978
|
|
|
983
979
|
if (payload === null || typeof payload !== "object") return undefined;
|
|
984
980
|
const payloadPrototype = Object.getPrototypeOf(payload);
|
|
@@ -1007,7 +1003,10 @@ const schemaClassToolPartPreflight = <Tools extends Record<string, Tool.Any>>(
|
|
|
1007
1003
|
];
|
|
1008
1004
|
|
|
1009
1005
|
for (const key of retainedKeys) {
|
|
1010
|
-
|
|
1006
|
+
const descriptor = read(key);
|
|
1007
|
+
|
|
1008
|
+
if (descriptor === undefined) return undefined;
|
|
1009
|
+
preflight[key] = descriptor.value;
|
|
1011
1010
|
}
|
|
1012
1011
|
|
|
1013
1012
|
return preflight;
|
|
@@ -1170,11 +1169,14 @@ const captureModelResponsePartGeneral = Effect.fnUntraced(function* <
|
|
|
1170
1169
|
|
|
1171
1170
|
const retainedBytes = yield* inspectModelResponsePartCapacity(usage, encoded, limits);
|
|
1172
1171
|
|
|
1172
|
+
if (typeof structuredCloneFunction !== "function") {
|
|
1173
|
+
return yield* ModelProtocolError.make({
|
|
1174
|
+
message: "Model response part could not be converted into engine-owned data",
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1173
1178
|
const ownedEncoded = yield* Effect.try({
|
|
1174
1179
|
try: () => {
|
|
1175
|
-
if (typeof structuredCloneFunction !== "function") {
|
|
1176
|
-
throw new TypeError("structuredClone is unavailable");
|
|
1177
|
-
}
|
|
1178
1180
|
const cloned: unknown = Reflect.apply(structuredCloneFunction, globalThis, [encoded]);
|
|
1179
1181
|
|
|
1180
1182
|
return cloned;
|
|
@@ -1244,7 +1246,10 @@ interface PreparedToolCall<Tools extends Record<string, Tool.Any>> {
|
|
|
1244
1246
|
readonly call: Response.ToolCallPart<string, Schema.Json>;
|
|
1245
1247
|
readonly name: keyof Tools & string;
|
|
1246
1248
|
readonly toolCallId: ToolCallId;
|
|
1247
|
-
readonly validation: Result.Result<
|
|
1249
|
+
readonly validation: Result.Result<
|
|
1250
|
+
Option.Option<Tool.Parameters<ToolUnion<Tools>>>,
|
|
1251
|
+
ToolParameterRejection
|
|
1252
|
+
>;
|
|
1248
1253
|
readonly tool: ToolUnion<Tools>;
|
|
1249
1254
|
readonly declarationIndex: number;
|
|
1250
1255
|
}
|
|
@@ -1375,9 +1380,15 @@ const decodeToolCallParameters = <Tools extends Record<string, Tool.Any>>(
|
|
|
1375
1380
|
);
|
|
1376
1381
|
};
|
|
1377
1382
|
|
|
1383
|
+
/** Native identity proves encoding does not transform the already validated parameters. */
|
|
1384
|
+
const reusesValidatedToolParameters = (tool: Tool.Any): boolean =>
|
|
1385
|
+
(tool.needsApproval === undefined || tool.needsApproval === false) &&
|
|
1386
|
+
SchemaAST.toEncoded(tool.parametersSchema.ast) === tool.parametersSchema.ast;
|
|
1387
|
+
|
|
1378
1388
|
/**
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1389
|
+
* Fresh responses and resumed batches validate every call before reaching this boundary.
|
|
1390
|
+
* Identity encodings with no approval need no second decoded value. Other codecs retain the
|
|
1391
|
+
* complete batch preflight, including validation of their canonical round trip, before dispatch.
|
|
1381
1392
|
*/
|
|
1382
1393
|
const prepareToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
1383
1394
|
toolkit: Toolkit.WithHandler<Tools>,
|
|
@@ -1398,17 +1409,26 @@ const prepareToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
|
1398
1409
|
}
|
|
1399
1410
|
const tool = toolkit.tools[name] as ToolUnion<Tools>;
|
|
1400
1411
|
|
|
1401
|
-
return Effect.
|
|
1402
|
-
const
|
|
1412
|
+
return Effect.flatMap(decodeToolCallId(call.id), (toolCallId) => {
|
|
1413
|
+
const prepared = (
|
|
1414
|
+
validation: PreparedToolCall<Tools>["validation"],
|
|
1415
|
+
): PreparedToolCall<Tools> => ({
|
|
1416
|
+
call,
|
|
1417
|
+
name,
|
|
1418
|
+
toolCallId,
|
|
1419
|
+
validation,
|
|
1420
|
+
tool,
|
|
1421
|
+
declarationIndex,
|
|
1422
|
+
});
|
|
1403
1423
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
yield* decodeToolCallParameters<Tools>(tool, call.name, copyJson(call.params)),
|
|
1408
|
-
)
|
|
1409
|
-
: Result.fail(rejection);
|
|
1424
|
+
if (rejection !== undefined) return Effect.succeed(prepared(Result.fail(rejection)));
|
|
1425
|
+
if (reusesValidatedToolParameters(tool))
|
|
1426
|
+
return Effect.succeed(prepared(Result.succeed(Option.none())));
|
|
1410
1427
|
|
|
1411
|
-
return
|
|
1428
|
+
return Effect.map(
|
|
1429
|
+
decodeToolCallParameters<Tools>(tool, call.name, copyJson(call.params)),
|
|
1430
|
+
(parameters) => prepared(Result.succeed(Option.some(parameters))),
|
|
1431
|
+
);
|
|
1412
1432
|
});
|
|
1413
1433
|
};
|
|
1414
1434
|
|
|
@@ -1453,47 +1473,56 @@ const effectiveRunBounds = (
|
|
|
1453
1473
|
maxToolCalls: boundedAllowance(policy.maxToolCalls, options.toolCallAllowance),
|
|
1454
1474
|
});
|
|
1455
1475
|
|
|
1456
|
-
const
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
if (descriptor === undefined || !("value" in descriptor)) {
|
|
1467
|
-
throw new TypeError(`settled Tool Call ${key} must be an own data property`);
|
|
1468
|
-
}
|
|
1476
|
+
const readSnapshotProperty = Effect.fnUntraced(function* (
|
|
1477
|
+
input: object,
|
|
1478
|
+
key: string,
|
|
1479
|
+
invalid: () => ModelProtocolError,
|
|
1480
|
+
optional = false,
|
|
1481
|
+
): Effect.fn.Return<unknown, ModelProtocolError> {
|
|
1482
|
+
const descriptor = yield* Effect.try({
|
|
1483
|
+
try: () => Object.getOwnPropertyDescriptor(input, key),
|
|
1484
|
+
catch: invalid,
|
|
1485
|
+
});
|
|
1469
1486
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1487
|
+
if (descriptor === undefined && optional) return undefined;
|
|
1488
|
+
if (descriptor === undefined || !("value" in descriptor)) return yield* invalid();
|
|
1472
1489
|
|
|
1473
|
-
|
|
1490
|
+
return descriptor.value;
|
|
1491
|
+
});
|
|
1474
1492
|
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1493
|
+
const decodeResumedSettledCall = Effect.fnUntraced(function* (input: unknown) {
|
|
1494
|
+
const invalid = () =>
|
|
1495
|
+
ModelProtocolError.make({
|
|
1496
|
+
message: "Turn resume contains an invalid settled Tool Call",
|
|
1497
|
+
});
|
|
1478
1498
|
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1499
|
+
if (input === null || typeof input !== "object") return yield* invalid();
|
|
1500
|
+
const id = yield* readSnapshotProperty(input, "id", invalid);
|
|
1501
|
+
const resultValue = yield* readSnapshotProperty(input, "result", invalid);
|
|
1502
|
+
const isFailure = yield* readSnapshotProperty(input, "isFailure", invalid);
|
|
1482
1503
|
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
};
|
|
1490
|
-
},
|
|
1491
|
-
catch: () =>
|
|
1492
|
-
ModelProtocolError.make({
|
|
1493
|
-
message: "Turn resume contains an invalid settled Tool Call",
|
|
1494
|
-
}),
|
|
1504
|
+
const { selection, rejected } = yield* Effect.try({
|
|
1505
|
+
try: () => ({
|
|
1506
|
+
selection: Object.getOwnPropertyDescriptor(input, "toolSelection"),
|
|
1507
|
+
rejected: Object.getOwnPropertyDescriptor(input, "budgetRejected"),
|
|
1508
|
+
}),
|
|
1509
|
+
catch: invalid,
|
|
1495
1510
|
});
|
|
1496
1511
|
|
|
1512
|
+
if (
|
|
1513
|
+
(selection !== undefined && !("value" in selection)) ||
|
|
1514
|
+
(rejected !== undefined && !("value" in rejected))
|
|
1515
|
+
)
|
|
1516
|
+
return yield* invalid();
|
|
1517
|
+
|
|
1518
|
+
const raw = {
|
|
1519
|
+
id,
|
|
1520
|
+
result: resultValue,
|
|
1521
|
+
isFailure,
|
|
1522
|
+
...(rejected === undefined ? {} : { budgetRejected: rejected.value }),
|
|
1523
|
+
...(selection === undefined ? {} : { toolSelection: selection.value }),
|
|
1524
|
+
};
|
|
1525
|
+
|
|
1497
1526
|
const result = boundedCanonicalJsonSnapshot(raw.result, MAX_RESUMED_RESULT_BYTES);
|
|
1498
1527
|
|
|
1499
1528
|
if (result === undefined) {
|
|
@@ -1514,106 +1543,73 @@ const decodeResumedSettledCall = Effect.fnUntraced(function* (input: unknown) {
|
|
|
1514
1543
|
);
|
|
1515
1544
|
});
|
|
1516
1545
|
|
|
1517
|
-
const snapshotResumedSettledCalls = (resume: unknown, maximum: number)
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
}
|
|
1523
|
-
const settledDescriptor = Object.getOwnPropertyDescriptor(resume, "settled");
|
|
1524
|
-
|
|
1525
|
-
if (settledDescriptor === undefined || !("value" in settledDescriptor)) {
|
|
1526
|
-
throw new TypeError("Turn resume settled must be an own data property");
|
|
1527
|
-
}
|
|
1528
|
-
const settled = settledDescriptor.value;
|
|
1546
|
+
const snapshotResumedSettledCalls = Effect.fnUntraced(function* (resume: unknown, maximum: number) {
|
|
1547
|
+
const invalid = () =>
|
|
1548
|
+
ModelProtocolError.make({
|
|
1549
|
+
message: "Turn resume contains an invalid settled Tool Call collection",
|
|
1550
|
+
});
|
|
1529
1551
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const lengthDescriptor = Object.getOwnPropertyDescriptor(settled, "length");
|
|
1552
|
+
if (resume === null || typeof resume !== "object") return yield* invalid();
|
|
1553
|
+
const settled = yield* readSnapshotProperty(resume, "settled", invalid);
|
|
1554
|
+
const isArray = yield* Effect.try({ try: () => Array.isArray(settled), catch: invalid });
|
|
1534
1555
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
!("value" in lengthDescriptor) ||
|
|
1538
|
-
!Number.isSafeInteger(lengthDescriptor.value) ||
|
|
1539
|
-
lengthDescriptor.value < 0 ||
|
|
1540
|
-
lengthDescriptor.value > maximum
|
|
1541
|
-
) {
|
|
1542
|
-
throw new TypeError("Turn resume settled has an invalid length");
|
|
1543
|
-
}
|
|
1544
|
-
const snapshot: Array<unknown> = [];
|
|
1556
|
+
if (!isArray || settled === null || typeof settled !== "object") return yield* invalid();
|
|
1557
|
+
const length = yield* readSnapshotProperty(settled, "length", invalid);
|
|
1545
1558
|
|
|
1546
|
-
|
|
1547
|
-
|
|
1559
|
+
if (
|
|
1560
|
+
typeof length !== "number" ||
|
|
1561
|
+
!Number.isSafeInteger(length) ||
|
|
1562
|
+
length < 0 ||
|
|
1563
|
+
length > maximum
|
|
1564
|
+
) {
|
|
1565
|
+
return yield* invalid();
|
|
1566
|
+
}
|
|
1567
|
+
const snapshot: Array<unknown> = [];
|
|
1548
1568
|
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
snapshot.push(entryDescriptor.value);
|
|
1553
|
-
}
|
|
1569
|
+
for (let index = 0; index < length; index += 1) {
|
|
1570
|
+
snapshot.push(yield* readSnapshotProperty(settled, String(index), invalid));
|
|
1571
|
+
}
|
|
1554
1572
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
catch: () =>
|
|
1558
|
-
ModelProtocolError.make({
|
|
1559
|
-
message: "Turn resume contains an invalid settled Tool Call collection",
|
|
1560
|
-
}),
|
|
1561
|
-
});
|
|
1573
|
+
return snapshot;
|
|
1574
|
+
});
|
|
1562
1575
|
|
|
1563
1576
|
const decodeResumeUsage = Effect.fnUntraced(function* (input: unknown) {
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
const read = (key: keyof RunResumeUsage, optional = false): unknown => {
|
|
1571
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
1572
|
-
|
|
1573
|
-
if (descriptor === undefined && optional) return undefined;
|
|
1574
|
-
if (descriptor === undefined || !("value" in descriptor)) {
|
|
1575
|
-
throw new TypeError(`Run resume usage ${key} must be an own data property`);
|
|
1576
|
-
}
|
|
1577
|
+
const invalid = () =>
|
|
1578
|
+
ModelProtocolError.make({
|
|
1579
|
+
message:
|
|
1580
|
+
"Run resume usage requires own data properties with non-negative safe-integer totals and last-call tokens no greater than their cumulative totals",
|
|
1581
|
+
});
|
|
1577
1582
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1583
|
+
if (input === null || typeof input !== "object") return yield* invalid();
|
|
1584
|
+
const snapshot: Record<string, unknown> = {};
|
|
1580
1585
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
] as const
|
|
1591
|
-
)
|
|
1592
|
-
.map((key) => [key, read(key, true)])
|
|
1593
|
-
.filter(([, value]) => value !== undefined),
|
|
1594
|
-
);
|
|
1586
|
+
for (const key of [
|
|
1587
|
+
"usageStatus",
|
|
1588
|
+
"pricingStatus",
|
|
1589
|
+
"unobservedModelCalls",
|
|
1590
|
+
"children",
|
|
1591
|
+
"modelRestarts",
|
|
1592
|
+
"webSearchCalls",
|
|
1593
|
+
] satisfies ReadonlyArray<keyof RunResumeUsage>) {
|
|
1594
|
+
const value = yield* readSnapshotProperty(input, key, invalid, true);
|
|
1595
1595
|
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
message:
|
|
1614
|
-
"Run resume usage requires own data properties with non-negative safe-integer totals and last-call tokens no greater than their cumulative totals",
|
|
1615
|
-
}),
|
|
1616
|
-
});
|
|
1596
|
+
if (value !== undefined) snapshot[key] = value;
|
|
1597
|
+
}
|
|
1598
|
+
for (const key of [
|
|
1599
|
+
"modelCalls",
|
|
1600
|
+
"inputTokens",
|
|
1601
|
+
"outputTokens",
|
|
1602
|
+
"lastInputTokens",
|
|
1603
|
+
"lastOutputTokens",
|
|
1604
|
+
"costMicrousd",
|
|
1605
|
+
"committedTurns",
|
|
1606
|
+
"toolCalls",
|
|
1607
|
+
"programmaticToolCalls",
|
|
1608
|
+
"consecutiveToolFailures",
|
|
1609
|
+
"finalizationUsed",
|
|
1610
|
+
] satisfies ReadonlyArray<keyof RunResumeUsage>) {
|
|
1611
|
+
snapshot[key] = yield* readSnapshotProperty(input, key, invalid);
|
|
1612
|
+
}
|
|
1617
1613
|
|
|
1618
1614
|
return yield* Schema.decodeUnknownEffect(RunResumeUsageSchema)(snapshot).pipe(
|
|
1619
1615
|
Effect.mapError(() =>
|
|
@@ -1802,7 +1798,8 @@ const prepareApprovalRequest = <Tools extends Record<string, Tool.Any>>(
|
|
|
1802
1798
|
context,
|
|
1803
1799
|
Effect.gen(function* () {
|
|
1804
1800
|
if (Result.isFailure(prepared.validation)) return undefined;
|
|
1805
|
-
|
|
1801
|
+
if (Option.isNone(prepared.validation.success)) return undefined;
|
|
1802
|
+
const decodedParams = prepared.validation.success.value;
|
|
1806
1803
|
const approval = prepared.tool.needsApproval;
|
|
1807
1804
|
|
|
1808
1805
|
const required =
|
|
@@ -2392,22 +2389,21 @@ const executePreparedToolCall = Effect.fnUntraced(function* <
|
|
|
2392
2389
|
if (result.isFailure) return yield* failureMarker();
|
|
2393
2390
|
});
|
|
2394
2391
|
|
|
2395
|
-
const failTerminalResult = (cause: Cause.Cause<ToolExecutionError>)
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
);
|
|
2392
|
+
const failTerminalResult = Effect.fnUntraced(function* (cause: Cause.Cause<ToolExecutionError>) {
|
|
2393
|
+
terminal = true;
|
|
2394
|
+
terminalResult = undefined;
|
|
2395
|
+
propagatedFailure = cause;
|
|
2396
|
+
// The raw failure has no canonical success/result, matching the prior propagated path.
|
|
2397
|
+
yield* decodeToolCallId(call.id);
|
|
2398
|
+
trace.finalToolResultIds.add(call.id);
|
|
2399
|
+
terminalResultCommitted = true;
|
|
2400
|
+
yield* terminalTelemetry("failure", "propagated");
|
|
2401
|
+
yield* publishEvent(context, () =>
|
|
2402
|
+
makeToolFailedEvent(context, turnId, call, Cause.squash(cause), "propagated"),
|
|
2403
|
+
);
|
|
2408
2404
|
|
|
2409
|
-
|
|
2410
|
-
|
|
2405
|
+
return yield* failureMarker();
|
|
2406
|
+
});
|
|
2411
2407
|
|
|
2412
2408
|
const measured = started.pipe(
|
|
2413
2409
|
Effect.andThen(results),
|
|
@@ -2491,6 +2487,7 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2491
2487
|
| AgentUpdateAcceptance
|
|
2492
2488
|
| ToolSpanTelemetry
|
|
2493
2489
|
| ProgrammaticToolAuthorization
|
|
2490
|
+
| Scope.Scope
|
|
2494
2491
|
| Tool.HandlerServices<ToolUnion<Tools>>
|
|
2495
2492
|
> {
|
|
2496
2493
|
const exposed = context.toolExposure?.exposedToolNames;
|
|
@@ -2513,22 +2510,38 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2513
2510
|
message: "Tool batch calls a Tool outside its request exposure or current visibility",
|
|
2514
2511
|
});
|
|
2515
2512
|
|
|
2516
|
-
const
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
calls.flatMap((call, declarationIndex) =>
|
|
2520
|
-
settledCallIds?.has(call.id) ? [] : [{ call, declarationIndex }],
|
|
2521
|
-
),
|
|
2522
|
-
({ call, declarationIndex }) =>
|
|
2523
|
-
prepareToolCall(
|
|
2524
|
-
toolkit,
|
|
2525
|
-
call,
|
|
2526
|
-
declarationIndex,
|
|
2527
|
-
trace.toolParameterRejections.get(call.id),
|
|
2528
|
-
),
|
|
2513
|
+
const prepareCalls = Effect.forEach(
|
|
2514
|
+
calls.flatMap((call, declarationIndex) =>
|
|
2515
|
+
settledCallIds?.has(call.id) ? [] : [{ call, declarationIndex }],
|
|
2529
2516
|
),
|
|
2517
|
+
({ call, declarationIndex }) =>
|
|
2518
|
+
prepareToolCall(toolkit, call, declarationIndex, trace.toolParameterRejections.get(call.id)),
|
|
2519
|
+
);
|
|
2520
|
+
|
|
2521
|
+
const needsParameterDecoding = calls.some(
|
|
2522
|
+
(call) =>
|
|
2523
|
+
!settledCallIds?.has(call.id) &&
|
|
2524
|
+
!trace.toolParameterRejections.has(call.id) &&
|
|
2525
|
+
hasTool(toolkit.tools, call.name) &&
|
|
2526
|
+
!reusesValidatedToolParameters(toolkit.tools[call.name]),
|
|
2530
2527
|
);
|
|
2531
2528
|
|
|
2529
|
+
const prepared = yield* needsParameterDecoding
|
|
2530
|
+
? prepareWithinDeadline(context, prepareCalls)
|
|
2531
|
+
: Effect.flatMap(
|
|
2532
|
+
Clock.currentTimeMillis,
|
|
2533
|
+
(
|
|
2534
|
+
now,
|
|
2535
|
+
): Effect.Effect<
|
|
2536
|
+
Array<PreparedToolCall<Tools>>,
|
|
2537
|
+
ModelProtocolError | AgentPolicyError,
|
|
2538
|
+
Tool.HandlerServices<ToolUnion<Tools>>
|
|
2539
|
+
> =>
|
|
2540
|
+
context.durationDeadlineMillis - now <= 0
|
|
2541
|
+
? Effect.fail(context.durationFailure)
|
|
2542
|
+
: prepareCalls,
|
|
2543
|
+
);
|
|
2544
|
+
|
|
2532
2545
|
if (
|
|
2533
2546
|
prepared.some((call) => Context.get(call.tool.annotations, ContextRolloverTool)) &&
|
|
2534
2547
|
calls.length !== 1
|
|
@@ -2692,7 +2705,7 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2692
2705
|
"SubagentInterrupted",
|
|
2693
2706
|
"SubagentJoined",
|
|
2694
2707
|
].includes(payload._tag)
|
|
2695
|
-
? Effect.fail(
|
|
2708
|
+
? Effect.fail(RunEventSinkClosedError.make({ message: "Unsupported Tool event payload" }))
|
|
2696
2709
|
: emitPayload(payload),
|
|
2697
2710
|
};
|
|
2698
2711
|
|
|
@@ -2702,28 +2715,28 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2702
2715
|
emit: (request) =>
|
|
2703
2716
|
context.updatePermits.withPermit(
|
|
2704
2717
|
Effect.gen(function* () {
|
|
2705
|
-
if (!updatesOpen) return yield*
|
|
2718
|
+
if (!updatesOpen) return yield* UpdateError.make({ reason: "unavailable" });
|
|
2706
2719
|
if (
|
|
2707
2720
|
request.target.id !== context.agentId ||
|
|
2708
2721
|
request.target.updates !== context.definition.updates ||
|
|
2709
2722
|
context.definition.updates === undefined
|
|
2710
2723
|
)
|
|
2711
|
-
return yield*
|
|
2724
|
+
return yield* UpdateError.make({ reason: "identity" });
|
|
2712
2725
|
|
|
2713
2726
|
const updateId = yield* Schema.decodeEffect(IdempotencyKey)(request.updateId).pipe(
|
|
2714
|
-
Effect.mapError(() =>
|
|
2727
|
+
Effect.mapError(() => UpdateError.make({ reason: "validation" })),
|
|
2715
2728
|
);
|
|
2716
2729
|
|
|
2717
2730
|
const value = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Json))(
|
|
2718
2731
|
JSON.stringify(request.value),
|
|
2719
|
-
).pipe(Effect.mapError(() =>
|
|
2732
|
+
).pipe(Effect.mapError(() => UpdateError.make({ reason: "validation" })));
|
|
2720
2733
|
|
|
2721
2734
|
yield* context.validateUpdate(value);
|
|
2722
2735
|
const existing = context.updates.get(updateId);
|
|
2723
2736
|
|
|
2724
2737
|
if (existing !== undefined) {
|
|
2725
2738
|
if (!Schema.toEquivalence(Schema.Json)(existing.value, value))
|
|
2726
|
-
return yield*
|
|
2739
|
+
return yield* UpdateError.make({ reason: "conflict" });
|
|
2727
2740
|
|
|
2728
2741
|
return existing;
|
|
2729
2742
|
}
|
|
@@ -2739,11 +2752,11 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2739
2752
|
context.updates.size >= maxCount ||
|
|
2740
2753
|
context.updateBytes + bytes > maxBytes
|
|
2741
2754
|
)
|
|
2742
|
-
return yield*
|
|
2755
|
+
return yield* UpdateError.make({ reason: "capacity" });
|
|
2743
2756
|
|
|
2744
2757
|
const snapshot = boundedCanonicalJsonSnapshot(value, bytes);
|
|
2745
2758
|
|
|
2746
|
-
if (snapshot === undefined) return yield*
|
|
2759
|
+
if (snapshot === undefined) return yield* UpdateError.make({ reason: "validation" });
|
|
2747
2760
|
|
|
2748
2761
|
const accepted = yield* updateAcceptance.accept(
|
|
2749
2762
|
Object.freeze(
|
|
@@ -2760,7 +2773,7 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2760
2773
|
);
|
|
2761
2774
|
|
|
2762
2775
|
const validated = yield* Schema.decodeEffect(Update)(accepted).pipe(
|
|
2763
|
-
Effect.mapError(() =>
|
|
2776
|
+
Effect.mapError(() => UpdateError.make({ reason: "validation" })),
|
|
2764
2777
|
);
|
|
2765
2778
|
|
|
2766
2779
|
if (
|
|
@@ -2770,7 +2783,7 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2770
2783
|
validated.updateId !== request.updateId ||
|
|
2771
2784
|
!Schema.toEquivalence(Schema.Json)(validated.value, value)
|
|
2772
2785
|
)
|
|
2773
|
-
return yield*
|
|
2786
|
+
return yield* UpdateError.make({ reason: "identity" });
|
|
2774
2787
|
|
|
2775
2788
|
// Keep acknowledgements, replay, and retries on the same owned value even when
|
|
2776
2789
|
// the accepting host retains its own mutable Update instance.
|
|
@@ -2780,7 +2793,7 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2780
2793
|
context.updateBytes += bytes;
|
|
2781
2794
|
|
|
2782
2795
|
yield* emitPayload({ _tag: "AgentUpdateEmitted", update }).pipe(
|
|
2783
|
-
Effect.mapError(() =>
|
|
2796
|
+
Effect.mapError(() => UpdateError.make({ reason: "unavailable" })),
|
|
2784
2797
|
);
|
|
2785
2798
|
|
|
2786
2799
|
return update;
|
|
@@ -2788,9 +2801,9 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2788
2801
|
),
|
|
2789
2802
|
};
|
|
2790
2803
|
|
|
2791
|
-
//
|
|
2792
|
-
//
|
|
2793
|
-
//
|
|
2804
|
+
// The permit covers the child's complete lifetime, including descendant cleanup. The call
|
|
2805
|
+
// owns its resource Scope and its fiber belongs to the enclosing Turn Scope. The native bracket
|
|
2806
|
+
// joins or interrupts it before releasing the permit, without another supervisor Scope.
|
|
2794
2807
|
const permits = yield* Semaphore.make(concurrency);
|
|
2795
2808
|
|
|
2796
2809
|
const handlers = Effect.gen(function* () {
|
|
@@ -2799,9 +2812,9 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2799
2812
|
group,
|
|
2800
2813
|
(call) =>
|
|
2801
2814
|
permits.withPermit(
|
|
2802
|
-
Effect.
|
|
2803
|
-
Effect.
|
|
2804
|
-
|
|
2815
|
+
Effect.acquireUseRelease(
|
|
2816
|
+
Effect.forkScoped(
|
|
2817
|
+
Effect.scoped(
|
|
2805
2818
|
Effect.gen(function* () {
|
|
2806
2819
|
yield* checkpointExecution(context, durability);
|
|
2807
2820
|
const subagentHost = yield* SubagentHost.forTool;
|
|
@@ -2827,6 +2840,11 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2827
2840
|
hookServices,
|
|
2828
2841
|
});
|
|
2829
2842
|
|
|
2843
|
+
const step = stepServiceFor(call);
|
|
2844
|
+
const subagent = subagentHost(source);
|
|
2845
|
+
const messaging = messagingHost(source);
|
|
2846
|
+
const catalog = { entries: context.toolCatalog };
|
|
2847
|
+
|
|
2830
2848
|
return yield* executePreparedToolCall(
|
|
2831
2849
|
context,
|
|
2832
2850
|
turnId,
|
|
@@ -2838,23 +2856,31 @@ const executeToolBatch = Effect.fnUntraced(function* <
|
|
|
2838
2856
|
waitingByDeclaration.set(call.declarationIndex, waiting);
|
|
2839
2857
|
},
|
|
2840
2858
|
).pipe(
|
|
2841
|
-
|
|
2842
|
-
Effect.
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2859
|
+
// Match the original providers' outer-to-inner order with one restoration.
|
|
2860
|
+
Effect.updateContext(
|
|
2861
|
+
(
|
|
2862
|
+
services: Context.Context<
|
|
2863
|
+
ToolSpanTelemetry | Tool.HandlerServices<ToolUnion<Tools>>
|
|
2864
|
+
>,
|
|
2865
|
+
) =>
|
|
2866
|
+
services.pipe(
|
|
2867
|
+
Context.add(CurrentToolCatalog, catalog),
|
|
2868
|
+
Context.add(ToolBroker, broker.service),
|
|
2869
|
+
Context.add(MessagingHost, messaging),
|
|
2870
|
+
Context.add(SubagentHost, subagent),
|
|
2871
|
+
Context.add(DurableStep, step),
|
|
2872
|
+
),
|
|
2873
|
+
),
|
|
2846
2874
|
Effect.ensuring(Effect.sync(() => broker.close())),
|
|
2847
2875
|
);
|
|
2848
2876
|
}),
|
|
2849
|
-
)
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
return yield* Fiber.join(fiber);
|
|
2854
|
-
}),
|
|
2877
|
+
),
|
|
2878
|
+
),
|
|
2879
|
+
Fiber.join,
|
|
2880
|
+
Fiber.interrupt,
|
|
2855
2881
|
),
|
|
2856
2882
|
),
|
|
2857
|
-
{ concurrency: "unbounded", discard: true },
|
|
2883
|
+
{ concurrency: group.length === 1 ? 1 : "unbounded", discard: true },
|
|
2858
2884
|
);
|
|
2859
2885
|
yield* checkpointExecution(context, durability);
|
|
2860
2886
|
}
|
|
@@ -4127,76 +4153,75 @@ const compactContext = <AgentValue extends Agent.Any, HookError, HookRequirement
|
|
|
4127
4153
|
const textParts = new Map<string, PartLifecycle>();
|
|
4128
4154
|
const reasoningParts = new Map<string, PartLifecycle>();
|
|
4129
4155
|
|
|
4130
|
-
const consumeSummaryPart = (owned: OwnedModelResponsePart)
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
summaryFinishMetadata = ownedPart.metadata;
|
|
4142
|
-
}
|
|
4143
|
-
} else if (ownedPart.type === "response-metadata") {
|
|
4144
|
-
summaryResponse = yield* responseIdentity(ownedPart, summaryResponse);
|
|
4156
|
+
const consumeSummaryPart = Effect.fnUntraced(function* (owned: OwnedModelResponsePart) {
|
|
4157
|
+
responseUsage.responsePartCount++;
|
|
4158
|
+
responseUsage.responsePartBytes += owned.retainedBytes;
|
|
4159
|
+
const ownedPart = owned.ownedPart;
|
|
4160
|
+
|
|
4161
|
+
if (ownedPart.type === "text-delta") {
|
|
4162
|
+
pieces.push(ownedPart.delta);
|
|
4163
|
+
} else if (ownedPart.type === "finish") {
|
|
4164
|
+
if (summaryUsage === undefined) {
|
|
4165
|
+
summaryUsage = ownedPart.usage;
|
|
4166
|
+
summaryFinishMetadata = ownedPart.metadata;
|
|
4145
4167
|
}
|
|
4146
|
-
|
|
4147
|
-
yield*
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
});
|
|
4175
|
-
}
|
|
4176
|
-
|
|
4177
|
-
return;
|
|
4178
|
-
}
|
|
4179
|
-
case "tool-params-start":
|
|
4180
|
-
case "tool-params-delta":
|
|
4181
|
-
case "tool-params-end":
|
|
4182
|
-
case "tool-approval-request":
|
|
4183
|
-
case "error":
|
|
4168
|
+
} else if (ownedPart.type === "response-metadata") {
|
|
4169
|
+
summaryResponse = yield* responseIdentity(ownedPart, summaryResponse);
|
|
4170
|
+
}
|
|
4171
|
+
// Drain malformed responses within the buffer bounds so reported usage is charged.
|
|
4172
|
+
yield* Effect.gen(function* () {
|
|
4173
|
+
switch (ownedPart.type) {
|
|
4174
|
+
case "text-start":
|
|
4175
|
+
return yield* startPart(textParts, ownedPart.id, "compaction text");
|
|
4176
|
+
case "text-delta":
|
|
4177
|
+
return yield* continuePart(textParts, ownedPart.id, "compaction text delta");
|
|
4178
|
+
case "text-end":
|
|
4179
|
+
return yield* endPart(textParts, ownedPart.id, "compaction text");
|
|
4180
|
+
case "reasoning-start":
|
|
4181
|
+
return yield* startPart(reasoningParts, ownedPart.id, "compaction reasoning");
|
|
4182
|
+
case "reasoning-delta":
|
|
4183
|
+
return yield* continuePart(
|
|
4184
|
+
reasoningParts,
|
|
4185
|
+
ownedPart.id,
|
|
4186
|
+
"compaction reasoning delta",
|
|
4187
|
+
);
|
|
4188
|
+
case "reasoning-end":
|
|
4189
|
+
return yield* endPart(reasoningParts, ownedPart.id, "compaction reasoning");
|
|
4190
|
+
case "finish": {
|
|
4191
|
+
summaryFinished = true;
|
|
4192
|
+
if (
|
|
4193
|
+
ownedPart.reason !== "stop" ||
|
|
4194
|
+
[...textParts.values(), ...reasoningParts.values()].includes("open")
|
|
4195
|
+
) {
|
|
4184
4196
|
return yield* ModelProtocolError.make({
|
|
4185
|
-
message:
|
|
4197
|
+
message:
|
|
4198
|
+
"Compaction response did not finish with complete text and a stop reason",
|
|
4186
4199
|
});
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
return;
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
return;
|
|
4191
4203
|
}
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4204
|
+
case "tool-params-start":
|
|
4205
|
+
case "tool-params-delta":
|
|
4206
|
+
case "tool-params-end":
|
|
4207
|
+
case "tool-approval-request":
|
|
4208
|
+
case "error":
|
|
4209
|
+
return yield* ModelProtocolError.make({
|
|
4210
|
+
message: `Compaction response contained an unusable ${ownedPart.type} part`,
|
|
4211
|
+
});
|
|
4212
|
+
case "file":
|
|
4213
|
+
case "response-metadata":
|
|
4214
|
+
case "source":
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
4217
|
+
}).pipe(
|
|
4218
|
+
Effect.catch((error) =>
|
|
4219
|
+
Effect.sync(() => {
|
|
4220
|
+
summaryFailure ??= error;
|
|
4221
|
+
}),
|
|
4222
|
+
),
|
|
4223
|
+
);
|
|
4224
|
+
});
|
|
4200
4225
|
|
|
4201
4226
|
const summaryExit = yield* enforceDurationDeadline(
|
|
4202
4227
|
guardBudgetStream(LanguageModel.streamText({ prompt: summarizerPrompt }), options.budget),
|
|
@@ -4449,7 +4474,7 @@ const decodeInput = <AgentValue extends Agent.Any>(
|
|
|
4449
4474
|
AgentInputDecodeError,
|
|
4450
4475
|
AgentValue["definition"]["input"]["DecodingServices"]
|
|
4451
4476
|
> =>
|
|
4452
|
-
Schema.decodeUnknownEffect(agent.definition.input)(input).pipe(
|
|
4477
|
+
Schema.decodeUnknownEffect<AgentValue["definition"]["input"]>(agent.definition.input)(input).pipe(
|
|
4453
4478
|
Effect.mapError((cause) =>
|
|
4454
4479
|
AgentInputDecodeError.make({
|
|
4455
4480
|
message: cause.message,
|
|
@@ -4475,7 +4500,7 @@ const encodeInput = <AgentValue extends Agent.Any>(
|
|
|
4475
4500
|
AgentInputError,
|
|
4476
4501
|
AgentValue["definition"]["input"]["EncodingServices"]
|
|
4477
4502
|
> =>
|
|
4478
|
-
Schema.encodeEffect(agent.definition.input)(input).pipe(
|
|
4503
|
+
Schema.encodeEffect<AgentValue["definition"]["input"]>(agent.definition.input)(input).pipe(
|
|
4479
4504
|
Effect.mapError((cause) =>
|
|
4480
4505
|
AgentInputError.make({
|
|
4481
4506
|
message: `Unable to encode Agent input: ${cause.message}`,
|
|
@@ -4489,20 +4514,21 @@ const renderInputPromptEffect = <Input, Error, Services>(
|
|
|
4489
4514
|
encodedInput: unknown,
|
|
4490
4515
|
): Effect.Effect<Prompt.RawInput, Error | AgentInputError, Services> =>
|
|
4491
4516
|
inputPrompt === undefined
|
|
4492
|
-
? Effect.
|
|
4493
|
-
|
|
4494
|
-
|
|
4517
|
+
? Effect.gen(function* () {
|
|
4518
|
+
const encoded = yield* Effect.try({
|
|
4519
|
+
try: () => JSON.stringify(encodedInput),
|
|
4520
|
+
catch: (cause) =>
|
|
4521
|
+
AgentInputError.make({
|
|
4522
|
+
message: `Unable to materialize Agent input: ${errorMessage(cause)}`,
|
|
4523
|
+
}),
|
|
4524
|
+
});
|
|
4495
4525
|
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4526
|
+
if (encoded === undefined)
|
|
4527
|
+
return yield* AgentInputError.make({
|
|
4528
|
+
message: "Unable to materialize Agent input: Agent input cannot be represented as JSON",
|
|
4529
|
+
});
|
|
4499
4530
|
|
|
4500
|
-
|
|
4501
|
-
},
|
|
4502
|
-
catch: (cause) =>
|
|
4503
|
-
AgentInputError.make({
|
|
4504
|
-
message: `Unable to materialize Agent input: ${errorMessage(cause)}`,
|
|
4505
|
-
}),
|
|
4531
|
+
return encoded;
|
|
4506
4532
|
})
|
|
4507
4533
|
: Effect.suspend(() => {
|
|
4508
4534
|
const result = inputPrompt(decodedInput);
|
|
@@ -4524,11 +4550,11 @@ export function renderInputPrompt<
|
|
|
4524
4550
|
InputPromptRequirementsOf<InputPromptValue, Input>
|
|
4525
4551
|
>;
|
|
4526
4552
|
|
|
4527
|
-
export function renderInputPrompt<Input>(
|
|
4528
|
-
inputPrompt: InputPromptSource<Input,
|
|
4553
|
+
export function renderInputPrompt<Input, Error, Requirements>(
|
|
4554
|
+
inputPrompt: InputPromptSource<Input, Error, Requirements> | undefined,
|
|
4529
4555
|
decodedInput: Input,
|
|
4530
4556
|
encodedInput: unknown,
|
|
4531
|
-
): Effect.Effect<Prompt.RawInput,
|
|
4557
|
+
): Effect.Effect<Prompt.RawInput, Error | AgentInputError, Requirements> {
|
|
4532
4558
|
return renderInputPromptEffect(inputPrompt, decodedInput, encodedInput);
|
|
4533
4559
|
}
|
|
4534
4560
|
|
|
@@ -4908,7 +4934,7 @@ const processModelPart = Effect.fnUntraced(function* <Tools extends Record<strin
|
|
|
4908
4934
|
const error = AiError.make({
|
|
4909
4935
|
module: "Toolkit",
|
|
4910
4936
|
method: `${part.name}.handle`,
|
|
4911
|
-
reason:
|
|
4937
|
+
reason: AiError.ToolParameterValidationError.make({
|
|
4912
4938
|
toolName: part.name,
|
|
4913
4939
|
description: decoded.failure.message,
|
|
4914
4940
|
}),
|
|
@@ -5142,7 +5168,9 @@ const decodeFinalOutput = Effect.fnUntraced(function* <AgentValue extends Agent.
|
|
|
5142
5168
|
|
|
5143
5169
|
const candidateOutput: unknown = eventJson;
|
|
5144
5170
|
|
|
5145
|
-
const decoded = yield* Schema.decodeUnknownEffect
|
|
5171
|
+
const decoded = yield* Schema.decodeUnknownEffect<AgentValue["definition"]["output"]>(
|
|
5172
|
+
agent.definition.output,
|
|
5173
|
+
)(candidateOutput).pipe(
|
|
5146
5174
|
Effect.mapError((cause) =>
|
|
5147
5175
|
AgentOutputError.make({
|
|
5148
5176
|
message: cause.message,
|
|
@@ -5157,7 +5185,9 @@ const encodeOutputCandidate = Effect.fnUntraced(function* <AgentValue extends Ag
|
|
|
5157
5185
|
agent: AgentValue,
|
|
5158
5186
|
candidate: unknown,
|
|
5159
5187
|
) {
|
|
5160
|
-
const encoded = yield* Schema.encodeUnknownEffect
|
|
5188
|
+
const encoded = yield* Schema.encodeUnknownEffect<AgentValue["definition"]["output"]>(
|
|
5189
|
+
agent.definition.output,
|
|
5190
|
+
)(candidate).pipe(
|
|
5161
5191
|
Effect.mapError((cause) =>
|
|
5162
5192
|
AgentOutputError.make({
|
|
5163
5193
|
message: `Completion Tool output failed Schema encoding: ${cause.message}`,
|
|
@@ -5165,7 +5195,9 @@ const encodeOutputCandidate = Effect.fnUntraced(function* <AgentValue extends Ag
|
|
|
5165
5195
|
),
|
|
5166
5196
|
);
|
|
5167
5197
|
|
|
5168
|
-
const decoded = yield* Schema.decodeUnknownEffect
|
|
5198
|
+
const decoded = yield* Schema.decodeUnknownEffect<AgentValue["definition"]["output"]>(
|
|
5199
|
+
agent.definition.output,
|
|
5200
|
+
)(encoded).pipe(
|
|
5169
5201
|
Effect.mapError((cause) =>
|
|
5170
5202
|
AgentOutputError.make({
|
|
5171
5203
|
message: `Completion Tool output failed canonical decoding: ${cause.message}`,
|
|
@@ -5194,7 +5226,8 @@ const projectToolResult = Effect.fnUntraced(function* <AgentValue extends Agent.
|
|
|
5194
5226
|
AgentOutputError | ModelProtocolError,
|
|
5195
5227
|
AgentCompletionProjectionRequirements<AgentValue>
|
|
5196
5228
|
> {
|
|
5197
|
-
const
|
|
5229
|
+
const tools: AgentValue["definition"]["toolkit"]["tools"] = agent.definition.toolkit.tools;
|
|
5230
|
+
const tool = tools[declaration.tool];
|
|
5198
5231
|
|
|
5199
5232
|
if (tool === undefined) {
|
|
5200
5233
|
return yield* ModelProtocolError.make({
|
|
@@ -5202,9 +5235,9 @@ const projectToolResult = Effect.fnUntraced(function* <AgentValue extends Agent.
|
|
|
5202
5235
|
});
|
|
5203
5236
|
}
|
|
5204
5237
|
|
|
5205
|
-
const decodedParameters = yield* Schema.decodeUnknownEffect
|
|
5206
|
-
|
|
5207
|
-
).pipe(
|
|
5238
|
+
const decodedParameters = yield* Schema.decodeUnknownEffect<
|
|
5239
|
+
AgentValue["definition"]["toolkit"]["tools"][string]["parametersSchema"]
|
|
5240
|
+
>(tool.parametersSchema)(parameters).pipe(
|
|
5208
5241
|
Effect.mapError((cause) =>
|
|
5209
5242
|
AgentOutputError.make({
|
|
5210
5243
|
message: `Completion Tool parameters failed canonical decoding: ${cause.message}`,
|
|
@@ -5212,7 +5245,9 @@ const projectToolResult = Effect.fnUntraced(function* <AgentValue extends Agent.
|
|
|
5212
5245
|
),
|
|
5213
5246
|
);
|
|
5214
5247
|
|
|
5215
|
-
const decodedResult = yield* Schema.decodeUnknownEffect
|
|
5248
|
+
const decodedResult = yield* Schema.decodeUnknownEffect<
|
|
5249
|
+
AgentValue["definition"]["toolkit"]["tools"][string]["successSchema"]
|
|
5250
|
+
>(tool.successSchema)(result).pipe(
|
|
5216
5251
|
Effect.mapError((cause) =>
|
|
5217
5252
|
AgentOutputError.make({
|
|
5218
5253
|
message: `Completion Tool result failed canonical decoding: ${cause.message}`,
|
|
@@ -5512,10 +5547,10 @@ const makeTurn = <
|
|
|
5512
5547
|
: yield* prepareWithinDeadline(context, options.context.prepare(contextRequest));
|
|
5513
5548
|
|
|
5514
5549
|
if (context.resolvedModel && modelContext.modelCall !== undefined) {
|
|
5515
|
-
return yield*
|
|
5550
|
+
return yield* AiError.AiError.make({
|
|
5516
5551
|
module: "AgentRuntime",
|
|
5517
5552
|
method: "resolveModel",
|
|
5518
|
-
reason:
|
|
5553
|
+
reason: AiError.InvalidRequestError.make({
|
|
5519
5554
|
description: "Context preparation cannot replace a thread-resolved model",
|
|
5520
5555
|
}),
|
|
5521
5556
|
});
|
|
@@ -6337,7 +6372,14 @@ const makeTurn = <
|
|
|
6337
6372
|
if (Exit.isFailure(exit)) failedUsageCause = exit.cause;
|
|
6338
6373
|
});
|
|
6339
6374
|
|
|
6340
|
-
const attempt = (
|
|
6375
|
+
const attempt = (
|
|
6376
|
+
basis: Prompt.Prompt,
|
|
6377
|
+
): Effect.Effect<
|
|
6378
|
+
void,
|
|
6379
|
+
AgentRuntimeFailure<typeof agent, HookError, InstructionError>,
|
|
6380
|
+
| InterpreterRequirements<typeof agent, HookRequirements, InstructionRequirements>
|
|
6381
|
+
| Scope.Scope
|
|
6382
|
+
> =>
|
|
6341
6383
|
Effect.flatten(
|
|
6342
6384
|
outgoingModelPrompt(
|
|
6343
6385
|
policy,
|
|
@@ -6430,6 +6472,8 @@ const makeTurn = <
|
|
|
6430
6472
|
|
|
6431
6473
|
return yield* trackContext.pipe(
|
|
6432
6474
|
Effect.as(
|
|
6475
|
+
// Transport-only tools retain existential schema services; the enclosing attempt keeps the Agent's declared requirements.
|
|
6476
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off
|
|
6433
6477
|
guardBudgetStream(
|
|
6434
6478
|
LanguageModel.streamText({
|
|
6435
6479
|
// Every attempt, including an overflow retry, places the
|
|
@@ -6511,7 +6555,9 @@ const makeTurn = <
|
|
|
6511
6555
|
if (events !== undefined) yield* publishEvents(context, events);
|
|
6512
6556
|
}),
|
|
6513
6557
|
),
|
|
6514
|
-
|
|
6558
|
+
<Value, Error, Requirements>(
|
|
6559
|
+
effect: Effect.Effect<Value, Error, Requirements>,
|
|
6560
|
+
) => prepareWithinDeadline(context, effect),
|
|
6515
6561
|
Effect.onExit((exit) => {
|
|
6516
6562
|
if (Exit.isSuccess(exit)) return Effect.void;
|
|
6517
6563
|
provisionalText?.discard();
|
|
@@ -6534,18 +6580,23 @@ const makeTurn = <
|
|
|
6534
6580
|
Schedule.upTo({ times: policy.modelRetries ?? 0 }),
|
|
6535
6581
|
Schedule.while(({ input: error }) => {
|
|
6536
6582
|
const lastPart = trace.parts.at(-1);
|
|
6583
|
+
const providerError: unknown = error;
|
|
6537
6584
|
|
|
6538
6585
|
return (
|
|
6539
6586
|
canRepeatModelCall &&
|
|
6540
6587
|
!hasStreamedContent(trace) &&
|
|
6541
6588
|
((lastPart?.type === "error" && isTransientErrorPayload(lastPart.error)) ||
|
|
6542
|
-
(AiError.isAiError(
|
|
6589
|
+
(AiError.isAiError(providerError) && providerError.isRetryable))
|
|
6543
6590
|
);
|
|
6544
6591
|
}),
|
|
6545
6592
|
Schedule.modifyDelay(({ input: error, duration }) =>
|
|
6546
6593
|
Effect.gen(function* () {
|
|
6547
6594
|
const backoff = Duration.min(duration, MODEL_RETRY_MAX_DELAY);
|
|
6548
|
-
const
|
|
6595
|
+
const providerError: unknown = error;
|
|
6596
|
+
|
|
6597
|
+
const retryAfter = AiError.isAiError(providerError)
|
|
6598
|
+
? providerError.retryAfter
|
|
6599
|
+
: undefined;
|
|
6549
6600
|
|
|
6550
6601
|
const requested =
|
|
6551
6602
|
retryAfter === undefined ? backoff : Duration.max(backoff, retryAfter);
|
|
@@ -7031,16 +7082,15 @@ const makeTurn = <
|
|
|
7031
7082
|
* steering at the safe seam, and start the next Turn. The `maxTurns`
|
|
7032
7083
|
* guard already ran for these Tool Call sites.
|
|
7033
7084
|
*/
|
|
7034
|
-
const continueTurn = (history: Prompt.Prompt)
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
});
|
|
7085
|
+
const continueTurn = Effect.fnUntraced(function* (history: Prompt.Prompt) {
|
|
7086
|
+
trace.historyAccepted = true;
|
|
7087
|
+
yield* advanceHistory(context, history, options);
|
|
7088
|
+
yield* settleTurn(context, trace, turn, turnId, options);
|
|
7089
|
+
const steering = yield* drainInputs(context, options);
|
|
7090
|
+
const nextPrompt = yield* appendInputs(context, history, steering, options);
|
|
7091
|
+
|
|
7092
|
+
return nextTurn(nextPrompt, turn + 1, toolCalls);
|
|
7093
|
+
});
|
|
7044
7094
|
|
|
7045
7095
|
/**
|
|
7046
7096
|
* The otherwise-stop seam: advance official history, drain steering,
|
|
@@ -7048,86 +7098,81 @@ const makeTurn = <
|
|
|
7048
7098
|
* under the `maxTurns` and repeated-failure Stop Policy bounds or
|
|
7049
7099
|
* complete the Run with the Turn's decoded final output.
|
|
7050
7100
|
*/
|
|
7051
|
-
const settleOrFollowUp = (history: Prompt.Prompt)
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
yield* advanceHistory(context, history, options);
|
|
7101
|
+
const settleOrFollowUp = Effect.fnUntraced(function* (history: Prompt.Prompt) {
|
|
7102
|
+
trace.historyAccepted = true;
|
|
7103
|
+
yield* advanceHistory(context, history, options);
|
|
7055
7104
|
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7105
|
+
// Do not consume durable receipts that this completed Turn cannot cover.
|
|
7106
|
+
// Final-answer mode permits one grace Turn, but never a second finalization.
|
|
7107
|
+
const turnsBlocked =
|
|
7108
|
+
policy.onExhaustion === "fail" ? turn >= bounds.maxTurns : turn > bounds.maxTurns;
|
|
7060
7109
|
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
? []
|
|
7064
|
-
: yield* drainInputs(context, options);
|
|
7065
|
-
|
|
7066
|
-
const queued =
|
|
7067
|
-
steering.length > 0
|
|
7068
|
-
? steering
|
|
7069
|
-
: takeFollowUps(context, options.commandDrainPolicy ?? "one");
|
|
7070
|
-
|
|
7071
|
-
if (queued.length > 0) {
|
|
7072
|
-
// Final-answer mode admits exactly one grace Turn past
|
|
7073
|
-
// `maxTurns` (RUN-019): `turn > maxTurns` can only be
|
|
7074
|
-
// `maxTurns + 1`, so a second grace is structurally
|
|
7075
|
-
// impossible.
|
|
7076
|
-
if (turnsBlocked) {
|
|
7077
|
-
return failExecution(
|
|
7078
|
-
AgentPolicyError.make({
|
|
7079
|
-
limit: "turns",
|
|
7080
|
-
message: `Agent exceeded its ${bounds.maxTurns} Turn limit`,
|
|
7081
|
-
}),
|
|
7082
|
-
);
|
|
7083
|
-
}
|
|
7084
|
-
yield* applyRepeatedFailurePolicy(
|
|
7085
|
-
context,
|
|
7086
|
-
trace,
|
|
7087
|
-
agent.definition.policy.repeatedFailureLimit,
|
|
7088
|
-
);
|
|
7089
|
-
yield* settleTurn(context, trace, turn, turnId, options);
|
|
7090
|
-
const nextPrompt = yield* appendInputs(context, history, queued, options);
|
|
7110
|
+
const steering =
|
|
7111
|
+
turnsBlocked || context.finalizationUsed ? [] : yield* drainInputs(context, options);
|
|
7091
7112
|
|
|
7092
|
-
|
|
7093
|
-
|
|
7113
|
+
const queued =
|
|
7114
|
+
steering.length > 0
|
|
7115
|
+
? steering
|
|
7116
|
+
: takeFollowUps(context, options.commandDrainPolicy ?? "one");
|
|
7094
7117
|
|
|
7095
|
-
|
|
7118
|
+
if (queued.length > 0) {
|
|
7119
|
+
// Final-answer mode admits exactly one grace Turn past
|
|
7120
|
+
// `maxTurns` (RUN-019): `turn > maxTurns` can only be
|
|
7121
|
+
// `maxTurns + 1`, so a second grace is structurally
|
|
7122
|
+
// impossible.
|
|
7123
|
+
if (turnsBlocked) {
|
|
7124
|
+
return failExecution(
|
|
7125
|
+
AgentPolicyError.make({
|
|
7126
|
+
limit: "turns",
|
|
7127
|
+
message: `Agent exceeded its ${bounds.maxTurns} Turn limit`,
|
|
7128
|
+
}),
|
|
7129
|
+
);
|
|
7130
|
+
}
|
|
7131
|
+
yield* applyRepeatedFailurePolicy(
|
|
7096
7132
|
context,
|
|
7097
|
-
|
|
7133
|
+
trace,
|
|
7134
|
+
agent.definition.policy.repeatedFailureLimit,
|
|
7098
7135
|
);
|
|
7136
|
+
yield* settleTurn(context, trace, turn, turnId, options);
|
|
7137
|
+
const nextPrompt = yield* appendInputs(context, history, queued, options);
|
|
7099
7138
|
|
|
7100
|
-
|
|
7139
|
+
return nextTurn(nextPrompt, turn + 1, toolCalls);
|
|
7140
|
+
}
|
|
7101
7141
|
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
context,
|
|
7107
|
-
encodeRunDisposition(agent, output.decoded),
|
|
7108
|
-
);
|
|
7142
|
+
const output = yield* prepareWithinDeadline(
|
|
7143
|
+
context,
|
|
7144
|
+
decodeFinalOutput(agent, trace.text.join("")),
|
|
7145
|
+
);
|
|
7109
7146
|
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
}),
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7147
|
+
const declaration = agent.definition.runDisposition;
|
|
7148
|
+
|
|
7149
|
+
const runDisposition =
|
|
7150
|
+
finalAnswerOnly || declaration === undefined
|
|
7151
|
+
? undefined
|
|
7152
|
+
: yield* prepareWithinDeadline(
|
|
7153
|
+
context,
|
|
7154
|
+
encodeRunDisposition(agent, output.decoded),
|
|
7155
|
+
);
|
|
7156
|
+
|
|
7157
|
+
const completionUsage = yield* usageReportOf(context);
|
|
7158
|
+
|
|
7159
|
+
return Effect.map(eventBase(context), (base) =>
|
|
7160
|
+
RunCompleted.make({
|
|
7161
|
+
...base,
|
|
7162
|
+
output: output.encoded,
|
|
7163
|
+
...(runDisposition === undefined ? {} : { runDisposition }),
|
|
7164
|
+
turns: turn,
|
|
7165
|
+
// A Run settled under the final-answer constraint reports
|
|
7166
|
+
// the exhaustion honestly (RUN-011), never a plain model
|
|
7167
|
+
// stop, and carries the dimension that bound.
|
|
7168
|
+
finishReason: finalAnswerOnly ? "budget-exhausted" : "model-stop",
|
|
7169
|
+
...(finalAnswerOnly && context.exhaustedDimension !== undefined
|
|
7170
|
+
? { exhausted: context.exhaustedDimension }
|
|
7171
|
+
: {}),
|
|
7172
|
+
...completionUsage,
|
|
7173
|
+
}),
|
|
7174
|
+
).pipe(Effect.tap((event) => settleTurn(context, trace, turn, turnId, options, event)));
|
|
7175
|
+
});
|
|
7131
7176
|
|
|
7132
7177
|
if (providerOnly && trace.finishReason === "stop") {
|
|
7133
7178
|
if (agent.definition.completion?.required === true) {
|
|
@@ -8601,12 +8646,12 @@ function executeWithCompletion<
|
|
|
8601
8646
|
|
|
8602
8647
|
const validateUpdate =
|
|
8603
8648
|
updateSchema === undefined
|
|
8604
|
-
? () => Effect.fail(
|
|
8649
|
+
? () => Effect.fail(UpdateError.make({ reason: "unavailable" }))
|
|
8605
8650
|
: (value: Schema.Json) =>
|
|
8606
8651
|
Schema.decodeEffect(updateSchema)(value).pipe(
|
|
8607
8652
|
Effect.provide(updateContext),
|
|
8608
8653
|
Effect.asVoid,
|
|
8609
|
-
Effect.mapError(() =>
|
|
8654
|
+
Effect.mapError(() => UpdateError.make({ reason: "validation" })),
|
|
8610
8655
|
);
|
|
8611
8656
|
|
|
8612
8657
|
const languageModel = yield* LanguageModel.LanguageModel;
|
|
@@ -8983,15 +9028,14 @@ function executeWithCompletion<
|
|
|
8983
9028
|
const selectionPrompt = yield* Schema.encodeEffect(
|
|
8984
9029
|
Schema.fromJsonString(Prompt.Prompt),
|
|
8985
9030
|
)(pending.prompt).pipe(
|
|
8986
|
-
Effect.mapError(
|
|
8987
|
-
(
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
description: `Cannot encode model selection context: ${cause.message}`,
|
|
8993
|
-
}),
|
|
9031
|
+
Effect.mapError((cause) =>
|
|
9032
|
+
AiError.AiError.make({
|
|
9033
|
+
module: "AgentRuntime",
|
|
9034
|
+
method: "resolveModel",
|
|
9035
|
+
reason: AiError.InvalidRequestError.make({
|
|
9036
|
+
description: `Cannot encode model selection context: ${cause.message}`,
|
|
8994
9037
|
}),
|
|
9038
|
+
}),
|
|
8995
9039
|
),
|
|
8996
9040
|
);
|
|
8997
9041
|
|
|
@@ -9030,34 +9074,36 @@ function executeWithCompletion<
|
|
|
9030
9074
|
agent.definition.updates === undefined || nativeUpdateTool === undefined
|
|
9031
9075
|
? Context.empty()
|
|
9032
9076
|
: yield* Toolkit.make(nativeUpdateTool).toHandlers({
|
|
9033
|
-
emit_update: (
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9077
|
+
emit_update: Effect.fnUntraced(function* (
|
|
9078
|
+
parameters: unknown,
|
|
9079
|
+
call: Toolkit.HandlerContext<Tool.Any>,
|
|
9080
|
+
) {
|
|
9081
|
+
if (call.toolCallId === undefined)
|
|
9082
|
+
return yield* UpdateError.make({ reason: "unavailable" });
|
|
9037
9083
|
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9084
|
+
const decoded = yield* Schema.decodeUnknownEffect(
|
|
9085
|
+
Schema.Struct({ value: Schema.Unknown }),
|
|
9086
|
+
)(parameters).pipe(
|
|
9087
|
+
Effect.mapError(() => UpdateError.make({ reason: "validation" })),
|
|
9088
|
+
);
|
|
9043
9089
|
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9090
|
+
const value = yield* Schema.encodeUnknownEffect(agent.definition.updates!)(
|
|
9091
|
+
decoded.value,
|
|
9092
|
+
).pipe(
|
|
9093
|
+
Effect.flatMap(Schema.decodeUnknownEffect(Schema.Json)),
|
|
9094
|
+
Effect.mapError(() => UpdateError.make({ reason: "validation" })),
|
|
9095
|
+
);
|
|
9050
9096
|
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9097
|
+
const updateId = yield* Schema.decodeEffect(IdempotencyKey)(
|
|
9098
|
+
`tool:${context.runId}:${call.toolCallId}`,
|
|
9099
|
+
).pipe(Effect.mapError(() => UpdateError.make({ reason: "validation" })));
|
|
9054
9100
|
|
|
9055
|
-
|
|
9101
|
+
const emitter = yield* Emitter;
|
|
9056
9102
|
|
|
9057
|
-
|
|
9103
|
+
yield* emitter.emit({ target: agent.definition, updateId, value });
|
|
9058
9104
|
|
|
9059
|
-
|
|
9060
|
-
|
|
9105
|
+
return { emitted: true };
|
|
9106
|
+
}),
|
|
9061
9107
|
});
|
|
9062
9108
|
|
|
9063
9109
|
const engineToolServices = Context.make(
|
|
@@ -9114,7 +9160,7 @@ function executeWithCompletion<
|
|
|
9114
9160
|
}),
|
|
9115
9161
|
Context.merge(updateHandlers),
|
|
9116
9162
|
Context.add(Emitter, {
|
|
9117
|
-
emit: () => Effect.fail(
|
|
9163
|
+
emit: () => Effect.fail(UpdateError.make({ reason: "unavailable" })),
|
|
9118
9164
|
}),
|
|
9119
9165
|
Context.add(CurrentToolCatalog, { entries: [] }),
|
|
9120
9166
|
Context.add(RunToolVisibility, visibility),
|
|
@@ -9330,9 +9376,9 @@ const completeRun = <AgentValue extends Agent.Any, Error, Requirements>(
|
|
|
9330
9376
|
Effect.gen(function* () {
|
|
9331
9377
|
const candidateOutput: unknown = completed.output;
|
|
9332
9378
|
|
|
9333
|
-
const output = yield* Schema.decodeUnknownEffect
|
|
9334
|
-
|
|
9335
|
-
).pipe(
|
|
9379
|
+
const output = yield* Schema.decodeUnknownEffect<AgentValue["definition"]["output"]>(
|
|
9380
|
+
agent.definition.output,
|
|
9381
|
+
)(candidateOutput).pipe(
|
|
9336
9382
|
Effect.mapError((cause) =>
|
|
9337
9383
|
AgentOutputError.make({
|
|
9338
9384
|
message: cause.message,
|
|
@@ -9577,9 +9623,11 @@ function runUnknown<H = never, R = never>(
|
|
|
9577
9623
|
input: unknown,
|
|
9578
9624
|
options: RunOptions<H, R> = {},
|
|
9579
9625
|
) {
|
|
9580
|
-
const program = "definition" in agent ? agent :
|
|
9626
|
+
const program = { definition: "definition" in agent ? agent.definition : agent };
|
|
9581
9627
|
|
|
9582
9628
|
return runProgram(program, (onCompleted) =>
|
|
9629
|
+
// The overload retains each Agent's R; this implementation executes an existential model binding without narrowing its services.
|
|
9630
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off
|
|
9583
9631
|
executeWithCompletion(agent, input, options, onCompleted).pipe(
|
|
9584
9632
|
Effect.provide(
|
|
9585
9633
|
Layer.mergeAll(ModelUsageAccounting.layerEphemeral, AgentUpdateAcceptance.layerEphemeral),
|
|
@@ -9614,11 +9662,13 @@ function startUnknown<H = never, R = never>(
|
|
|
9614
9662
|
input: unknown,
|
|
9615
9663
|
options: RunOptions<H, R> = {},
|
|
9616
9664
|
) {
|
|
9617
|
-
const program = "definition" in agent ? agent :
|
|
9665
|
+
const program = { definition: "definition" in agent ? agent.definition : agent };
|
|
9618
9666
|
|
|
9619
9667
|
return startProgram(
|
|
9620
9668
|
program,
|
|
9621
9669
|
(executionOptions, onCompleted, onUsage, publish) =>
|
|
9670
|
+
// The overload retains each Agent's R; detached execution captures the same existential binding inside the caller's Scope.
|
|
9671
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off
|
|
9622
9672
|
executeWithCompletion(agent, input, executionOptions, onCompleted, onUsage, publish).pipe(
|
|
9623
9673
|
Effect.provide(
|
|
9624
9674
|
Layer.mergeAll(ModelUsageAccounting.layerEphemeral, AgentUpdateAcceptance.layerEphemeral),
|
|
@@ -9888,588 +9938,588 @@ const makeToolBrokerService = Effect.fnUntraced(function* <HookError, HookRequir
|
|
|
9888
9938
|
observer === undefined ? undefined : { observer, permits: Semaphore.makeUnsafe(1) };
|
|
9889
9939
|
|
|
9890
9940
|
const service: ToolBrokerService = {
|
|
9891
|
-
openPass: (
|
|
9892
|
-
|
|
9893
|
-
|
|
9941
|
+
openPass: Effect.fnUntraced(function* <Tools extends Record<string, Tool.Any>>(
|
|
9942
|
+
toolkit: Toolkit.WithHandler<Tools>,
|
|
9943
|
+
passOptions: Parameters<ToolBrokerService["openPass"]>[1],
|
|
9944
|
+
) {
|
|
9945
|
+
const inheritedAuthority = yield* CurrentSubagentAuthority;
|
|
9894
9946
|
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9947
|
+
if (lifecycle.closed) {
|
|
9948
|
+
return yield* ToolBrokerUnavailableError.make({
|
|
9949
|
+
message: "The outer Tool Call for this broker has already settled",
|
|
9950
|
+
});
|
|
9951
|
+
}
|
|
9952
|
+
// A malformed result bound would fail open (`NaN` defeats every
|
|
9953
|
+
// comparison), so it is rejected typed before the pass opens.
|
|
9954
|
+
if (
|
|
9955
|
+
passOptions === undefined ||
|
|
9956
|
+
!Number.isSafeInteger(passOptions.maxResultBytes) ||
|
|
9957
|
+
passOptions.maxResultBytes <= 0
|
|
9958
|
+
) {
|
|
9959
|
+
return yield* ToolBrokerConfigurationError.make({
|
|
9960
|
+
message: `maxResultBytes must be a positive safe integer; received ${String(passOptions?.maxResultBytes)}`,
|
|
9961
|
+
});
|
|
9962
|
+
}
|
|
9963
|
+
// Capture the declared handler services at the pass boundary once.
|
|
9964
|
+
const handlerServices = yield* Effect.context<Tool.HandlerServices<Tools[keyof Tools]>>();
|
|
9965
|
+
|
|
9966
|
+
// Toolkit.handle decodes unknown parameters itself. Widen only that input boundary;
|
|
9967
|
+
// retain its declared schema failures and handler services for this exact Toolkit.
|
|
9968
|
+
const handle = toolkit.handle as (
|
|
9969
|
+
name: keyof Tools,
|
|
9970
|
+
parameters: unknown,
|
|
9971
|
+
id: string,
|
|
9972
|
+
) => ReturnType<Toolkit.WithHandler<Tools>["handle"]>;
|
|
9973
|
+
|
|
9974
|
+
const concurrency = passOptions.concurrency ?? 4;
|
|
9975
|
+
|
|
9976
|
+
if (!Number.isSafeInteger(concurrency) || concurrency < 1 || concurrency > 64) {
|
|
9977
|
+
return yield* ToolBrokerConfigurationError.make({
|
|
9978
|
+
message: "concurrency must be an integer between 1 and 64",
|
|
9979
|
+
});
|
|
9980
|
+
}
|
|
9981
|
+
const permits = yield* Semaphore.make(concurrency);
|
|
9982
|
+
const records: Array<ProgrammaticCallRecord> = [];
|
|
9983
|
+
|
|
9984
|
+
const preflightFailure = (
|
|
9985
|
+
input: ProgrammaticToolInput,
|
|
9986
|
+
kind: "infrastructure" | "protocol",
|
|
9987
|
+
tag: string,
|
|
9988
|
+
message: string,
|
|
9989
|
+
cause?: Cause.Cause<unknown>,
|
|
9990
|
+
): Effect.Effect<ProgrammaticCallOutcome> => {
|
|
9991
|
+
const outcome = programmaticOutcomeError(undefined, tag, message);
|
|
9992
|
+
|
|
9993
|
+
if (preflightObserver === undefined) return Effect.succeed(outcome);
|
|
9994
|
+
|
|
9995
|
+
return deliverToolFailure(preflightObserver.observer, {
|
|
9996
|
+
_tag: "ProgrammaticPreflightFailure",
|
|
9997
|
+
agentId: binding.context.agentId,
|
|
9998
|
+
threadId: binding.context.threadId,
|
|
9999
|
+
runId: binding.context.runId,
|
|
10000
|
+
turnId: binding.turnId,
|
|
10001
|
+
parentToolCallId: binding.outerToolCallId,
|
|
10002
|
+
toolName: input.toolName,
|
|
10003
|
+
...(hasTool(toolkit.tools, input.toolName)
|
|
10004
|
+
? { executionClass: getToolExecutionClass(toolkit.tools[input.toolName]) }
|
|
10005
|
+
: {}),
|
|
10006
|
+
kind,
|
|
10007
|
+
tag,
|
|
10008
|
+
message: toolFailureMessage(message),
|
|
10009
|
+
...(cause === undefined ? {} : { cause }),
|
|
10010
|
+
}).pipe(preflightObserver.permits.withPermits(1), Effect.as(outcome));
|
|
10011
|
+
};
|
|
9953
10012
|
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
10013
|
+
const body = (
|
|
10014
|
+
input: ProgrammaticToolInput,
|
|
10015
|
+
sequenceIndex: number,
|
|
10016
|
+
): Effect.Effect<ProgrammaticCallOutcome> =>
|
|
10017
|
+
Effect.gen(function* () {
|
|
10018
|
+
if (!hasTool(toolkit.tools, input.toolName)) {
|
|
10019
|
+
return yield* preflightFailure(
|
|
10020
|
+
input,
|
|
10021
|
+
"infrastructure",
|
|
10022
|
+
"ProgrammaticToolUnknownError",
|
|
10023
|
+
`Tool ${input.toolName} is not part of this pass's allowlisted Toolkit`,
|
|
10024
|
+
);
|
|
10025
|
+
}
|
|
10026
|
+
const tool = toolkit.tools[input.toolName];
|
|
9968
10027
|
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
10028
|
+
const advertised = Object.values(binding.context.definition.toolkit.tools).some((outer) =>
|
|
10029
|
+
Context.get(outer.annotations, AdditionalToolCatalog).some(
|
|
10030
|
+
(entry) => entry.tool.name === input.toolName,
|
|
10031
|
+
),
|
|
10032
|
+
);
|
|
10033
|
+
|
|
10034
|
+
if (
|
|
10035
|
+
advertised &&
|
|
10036
|
+
!binding.context.toolCatalog.some(
|
|
10037
|
+
(entry) => entry.kind === "code-mode" && entry.tool.name === input.toolName,
|
|
10038
|
+
)
|
|
10039
|
+
)
|
|
10040
|
+
return yield* preflightFailure(
|
|
10041
|
+
input,
|
|
10042
|
+
"infrastructure",
|
|
10043
|
+
"ProgrammaticToolAuthorizationDenied",
|
|
10044
|
+
"Tool is excluded by the current host visibility policy",
|
|
9974
10045
|
);
|
|
9975
10046
|
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
10047
|
+
if (
|
|
10048
|
+
!isSubagentToolAllowed(
|
|
10049
|
+
inheritedAuthority?.grant,
|
|
10050
|
+
inheritedAuthority?.depth ?? 0,
|
|
10051
|
+
input.toolName,
|
|
10052
|
+
tool.annotations,
|
|
9981
10053
|
)
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
10054
|
+
) {
|
|
10055
|
+
return yield* preflightFailure(
|
|
10056
|
+
input,
|
|
10057
|
+
"infrastructure",
|
|
10058
|
+
"ProgrammaticToolAuthorizationDenied",
|
|
10059
|
+
"Tool exceeds the inherited subagent grant",
|
|
10060
|
+
);
|
|
10061
|
+
}
|
|
9988
10062
|
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10063
|
+
if (Context.get(tool.annotations, ContextRolloverTool)) {
|
|
10064
|
+
return yield* preflightFailure(
|
|
10065
|
+
input,
|
|
10066
|
+
"infrastructure",
|
|
10067
|
+
"ProgrammaticContextRolloverUnsupportedError",
|
|
10068
|
+
"Context rollover requires a direct, singleton model Tool Call",
|
|
10069
|
+
);
|
|
10070
|
+
}
|
|
10071
|
+
const approval = tool.needsApproval;
|
|
10072
|
+
|
|
10073
|
+
if (approval !== undefined && approval !== false) {
|
|
10074
|
+
return yield* preflightFailure(
|
|
10075
|
+
input,
|
|
10076
|
+
"infrastructure",
|
|
10077
|
+
"ProgrammaticApprovalUnsupportedError",
|
|
10078
|
+
`Tool ${input.toolName} requires approval; approval-requiring Tools never start programmatically in the ephemeral slice`,
|
|
10079
|
+
);
|
|
10080
|
+
}
|
|
10004
10081
|
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
}
|
|
10013
|
-
const approval = tool.needsApproval;
|
|
10082
|
+
// Validate the encoded arguments against the owning parameter
|
|
10083
|
+
// Schema before the handler can start; the pinned `Toolkit.handle`
|
|
10084
|
+
// decodes internally, so the validated encoded form passes through
|
|
10085
|
+
// (the same inversion as `prepareToolCall`).
|
|
10086
|
+
const decodeParameters = Schema.decodeUnknownEffect(tool.parametersSchema) as (
|
|
10087
|
+
value: unknown,
|
|
10088
|
+
) => Effect.Effect<unknown, Schema.SchemaError>;
|
|
10014
10089
|
|
|
10015
|
-
|
|
10016
|
-
|
|
10090
|
+
const invalidParameters = yield* decodeParameters(input.encodedArguments).pipe(
|
|
10091
|
+
Effect.map(() => undefined),
|
|
10092
|
+
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10093
|
+
preflightFailure(
|
|
10017
10094
|
input,
|
|
10018
|
-
"
|
|
10019
|
-
"
|
|
10020
|
-
`Tool ${input.toolName}
|
|
10021
|
-
|
|
10022
|
-
|
|
10095
|
+
"protocol",
|
|
10096
|
+
"ModelProtocolError",
|
|
10097
|
+
`Invalid parameters for Tool ${input.toolName}: ${error.message}`,
|
|
10098
|
+
cause,
|
|
10099
|
+
),
|
|
10100
|
+
),
|
|
10101
|
+
);
|
|
10023
10102
|
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10103
|
+
if (invalidParameters !== undefined) {
|
|
10104
|
+
return invalidParameters;
|
|
10105
|
+
}
|
|
10106
|
+
|
|
10107
|
+
const handleId = ToolCallId.make(`${binding.outerToolCallId}#${sequenceIndex}`);
|
|
10108
|
+
|
|
10109
|
+
const denied = yield* authorization
|
|
10110
|
+
.authorize({
|
|
10111
|
+
threadId: binding.context.threadId,
|
|
10112
|
+
runId: binding.context.runId,
|
|
10113
|
+
turnId: binding.turnId,
|
|
10114
|
+
turn: binding.turn,
|
|
10115
|
+
input: binding.context.input,
|
|
10116
|
+
programmatic: { parentToolCallId: binding.outerToolCallId, sequenceIndex },
|
|
10117
|
+
call: {
|
|
10118
|
+
toolCallId: handleId,
|
|
10119
|
+
toolName: input.toolName,
|
|
10120
|
+
parameters: input.encodedArguments,
|
|
10121
|
+
executionClass: getToolExecutionClass(tool),
|
|
10122
|
+
executionKind: getToolExecutionKind(tool.annotations),
|
|
10123
|
+
},
|
|
10124
|
+
})
|
|
10125
|
+
.pipe(
|
|
10126
|
+
Effect.flatMap((decision) =>
|
|
10127
|
+
decision._tag === "allowed"
|
|
10128
|
+
? Effect.succeed(undefined)
|
|
10129
|
+
: preflightFailure(
|
|
10130
|
+
input,
|
|
10131
|
+
"infrastructure",
|
|
10132
|
+
"ProgrammaticToolAuthorizationDenied",
|
|
10133
|
+
decision.reason,
|
|
10134
|
+
),
|
|
10135
|
+
),
|
|
10136
|
+
Effect.catch((failure) =>
|
|
10035
10137
|
preflightFailure(
|
|
10036
10138
|
input,
|
|
10037
|
-
"
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
cause,
|
|
10139
|
+
"infrastructure",
|
|
10140
|
+
errorTag(failure.error),
|
|
10141
|
+
errorMessage(failure.error),
|
|
10142
|
+
failure.cause,
|
|
10041
10143
|
),
|
|
10042
10144
|
),
|
|
10043
10145
|
);
|
|
10044
10146
|
|
|
10045
|
-
|
|
10046
|
-
return invalidParameters;
|
|
10047
|
-
}
|
|
10147
|
+
if (denied !== undefined) return denied;
|
|
10048
10148
|
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
turnId: binding.turnId,
|
|
10056
|
-
turn: binding.turn,
|
|
10057
|
-
input: binding.context.input,
|
|
10058
|
-
programmatic: { parentToolCallId: binding.outerToolCallId, sequenceIndex },
|
|
10059
|
-
call: {
|
|
10060
|
-
toolCallId: handleId,
|
|
10061
|
-
toolName: input.toolName,
|
|
10062
|
-
parameters: input.encodedArguments,
|
|
10063
|
-
executionClass: getToolExecutionClass(tool),
|
|
10064
|
-
executionKind: getToolExecutionKind(tool.annotations),
|
|
10065
|
-
},
|
|
10066
|
-
})
|
|
10067
|
-
.pipe(
|
|
10068
|
-
Effect.flatMap((decision) =>
|
|
10069
|
-
decision._tag === "allowed"
|
|
10070
|
-
? Effect.succeed(undefined)
|
|
10071
|
-
: preflightFailure(
|
|
10072
|
-
input,
|
|
10073
|
-
"infrastructure",
|
|
10074
|
-
"ProgrammaticToolAuthorizationDenied",
|
|
10075
|
-
decision.reason,
|
|
10076
|
-
),
|
|
10077
|
-
),
|
|
10078
|
-
Effect.catch((failure) =>
|
|
10079
|
-
preflightFailure(
|
|
10080
|
-
input,
|
|
10081
|
-
"infrastructure",
|
|
10082
|
-
errorTag(failure.error),
|
|
10083
|
-
errorMessage(failure.error),
|
|
10084
|
-
failure.cause,
|
|
10085
|
-
),
|
|
10086
|
-
),
|
|
10087
|
-
);
|
|
10088
|
-
|
|
10089
|
-
if (denied !== undefined) return denied;
|
|
10149
|
+
// Serialize admission and durable reservation across outer handlers.
|
|
10150
|
+
// Once reserved, a slot is never refunded: ownership may be lost
|
|
10151
|
+
// after the append but before the Handler starts.
|
|
10152
|
+
const rejected = yield* binding.context.policyReservations.withPermit(
|
|
10153
|
+
Effect.gen(function* () {
|
|
10154
|
+
const used = binding.declaredToolCalls + binding.context.programmaticToolCalls;
|
|
10090
10155
|
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10156
|
+
if (used + 1 > binding.maxToolCalls) {
|
|
10157
|
+
return yield* preflightFailure(
|
|
10158
|
+
input,
|
|
10159
|
+
"infrastructure",
|
|
10160
|
+
"AgentPolicyError",
|
|
10161
|
+
`Agent exceeded its ${binding.maxToolCalls} Tool Call limit`,
|
|
10162
|
+
);
|
|
10163
|
+
}
|
|
10164
|
+
if (binding.budget !== undefined) {
|
|
10165
|
+
const exhausted = yield* provideHookServices(
|
|
10166
|
+
binding.budget.consume({
|
|
10167
|
+
modelCalls: 0,
|
|
10168
|
+
inputTokens: 0,
|
|
10169
|
+
outputTokens: 0,
|
|
10170
|
+
totalTokens: 0,
|
|
10171
|
+
toolCalls: 1,
|
|
10172
|
+
costMicrousd: 0,
|
|
10173
|
+
usage: emptyProgrammaticUsage,
|
|
10174
|
+
}),
|
|
10175
|
+
binding.hookServices,
|
|
10176
|
+
).pipe(
|
|
10177
|
+
Effect.map(() => undefined),
|
|
10178
|
+
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10179
|
+
Effect.succeed({ error, cause }),
|
|
10180
|
+
),
|
|
10181
|
+
);
|
|
10097
10182
|
|
|
10098
|
-
if (
|
|
10183
|
+
if (exhausted !== undefined) {
|
|
10099
10184
|
return yield* preflightFailure(
|
|
10100
10185
|
input,
|
|
10101
10186
|
"infrastructure",
|
|
10102
|
-
|
|
10103
|
-
|
|
10187
|
+
errorTag(exhausted.error),
|
|
10188
|
+
errorMessage(exhausted.error),
|
|
10189
|
+
exhausted.cause,
|
|
10104
10190
|
);
|
|
10105
10191
|
}
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
Effect.map(() => undefined),
|
|
10120
|
-
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10121
|
-
Effect.succeed({ error, cause }),
|
|
10122
|
-
),
|
|
10123
|
-
);
|
|
10124
|
-
|
|
10125
|
-
if (exhausted !== undefined) {
|
|
10126
|
-
return yield* preflightFailure(
|
|
10192
|
+
}
|
|
10193
|
+
binding.context.programmaticToolCalls += 1;
|
|
10194
|
+
if (binding.reservePolicyUsage !== undefined) {
|
|
10195
|
+
return yield* provideHookServices(
|
|
10196
|
+
binding.reservePolicyUsage({
|
|
10197
|
+
programmaticToolCalls: binding.context.programmaticToolCalls,
|
|
10198
|
+
finalizationUsed: binding.context.finalizationUsed,
|
|
10199
|
+
}),
|
|
10200
|
+
binding.hookServices,
|
|
10201
|
+
).pipe(
|
|
10202
|
+
Effect.as(undefined),
|
|
10203
|
+
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10204
|
+
preflightFailure(
|
|
10127
10205
|
input,
|
|
10128
10206
|
"infrastructure",
|
|
10129
|
-
errorTag(
|
|
10130
|
-
errorMessage(
|
|
10131
|
-
|
|
10132
|
-
);
|
|
10133
|
-
}
|
|
10134
|
-
}
|
|
10135
|
-
binding.context.programmaticToolCalls += 1;
|
|
10136
|
-
if (binding.reservePolicyUsage !== undefined) {
|
|
10137
|
-
return yield* provideHookServices(
|
|
10138
|
-
binding.reservePolicyUsage({
|
|
10139
|
-
programmaticToolCalls: binding.context.programmaticToolCalls,
|
|
10140
|
-
finalizationUsed: binding.context.finalizationUsed,
|
|
10141
|
-
}),
|
|
10142
|
-
binding.hookServices,
|
|
10143
|
-
).pipe(
|
|
10144
|
-
Effect.as(undefined),
|
|
10145
|
-
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10146
|
-
preflightFailure(
|
|
10147
|
-
input,
|
|
10148
|
-
"infrastructure",
|
|
10149
|
-
errorTag(error),
|
|
10150
|
-
errorMessage(error),
|
|
10151
|
-
cause,
|
|
10152
|
-
),
|
|
10207
|
+
errorTag(error),
|
|
10208
|
+
errorMessage(error),
|
|
10209
|
+
cause,
|
|
10153
10210
|
),
|
|
10154
|
-
)
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
return undefined;
|
|
10158
|
-
}),
|
|
10159
|
-
);
|
|
10211
|
+
),
|
|
10212
|
+
);
|
|
10213
|
+
}
|
|
10160
10214
|
|
|
10161
|
-
|
|
10215
|
+
return undefined;
|
|
10216
|
+
}),
|
|
10217
|
+
);
|
|
10162
10218
|
|
|
10163
|
-
|
|
10219
|
+
if (rejected !== undefined) return rejected;
|
|
10164
10220
|
|
|
10165
|
-
|
|
10166
|
-
sequenceIndex,
|
|
10167
|
-
toolName: input.toolName,
|
|
10168
|
-
status: "uncertain",
|
|
10169
|
-
};
|
|
10170
|
-
const executionClass = getToolExecutionClass(tool);
|
|
10171
|
-
let failureObservation: ProgrammaticToolFailure | undefined;
|
|
10172
|
-
|
|
10173
|
-
const startedFailure = (
|
|
10174
|
-
kind: "infrastructure" | "protocol",
|
|
10175
|
-
tag: string,
|
|
10176
|
-
message: string,
|
|
10177
|
-
): Effect.Effect<ProgrammaticCallOutcome> => {
|
|
10178
|
-
const outcome = programmaticOutcomeError(index, tag, message);
|
|
10179
|
-
|
|
10180
|
-
if (observer === undefined) return Effect.succeed(outcome);
|
|
10181
|
-
failureObservation = {
|
|
10182
|
-
_tag: "ProgrammaticToolFailure",
|
|
10183
|
-
agentId: binding.context.agentId,
|
|
10184
|
-
threadId: binding.context.threadId,
|
|
10185
|
-
runId: binding.context.runId,
|
|
10186
|
-
turnId: binding.turnId,
|
|
10187
|
-
toolCallId: handleId,
|
|
10188
|
-
parentToolCallId: binding.outerToolCallId,
|
|
10189
|
-
sequenceIndex: index,
|
|
10190
|
-
toolName: input.toolName,
|
|
10191
|
-
executionClass,
|
|
10192
|
-
kind,
|
|
10193
|
-
tag,
|
|
10194
|
-
message: toolFailureMessage(message),
|
|
10195
|
-
};
|
|
10196
|
-
|
|
10197
|
-
return Effect.succeed(outcome);
|
|
10198
|
-
};
|
|
10221
|
+
const index = sequenceIndex;
|
|
10199
10222
|
|
|
10200
|
-
|
|
10201
|
-
|
|
10223
|
+
records[sequenceIndex] = {
|
|
10224
|
+
sequenceIndex,
|
|
10225
|
+
toolName: input.toolName,
|
|
10226
|
+
status: "uncertain",
|
|
10227
|
+
};
|
|
10228
|
+
const executionClass = getToolExecutionClass(tool);
|
|
10229
|
+
let failureObservation: ProgrammaticToolFailure | undefined;
|
|
10230
|
+
|
|
10231
|
+
const startedFailure = (
|
|
10232
|
+
kind: "infrastructure" | "protocol",
|
|
10233
|
+
tag: string,
|
|
10234
|
+
message: string,
|
|
10235
|
+
): Effect.Effect<ProgrammaticCallOutcome> => {
|
|
10236
|
+
const outcome = programmaticOutcomeError(index, tag, message);
|
|
10237
|
+
|
|
10238
|
+
if (observer === undefined) return Effect.succeed(outcome);
|
|
10239
|
+
failureObservation = {
|
|
10240
|
+
_tag: "ProgrammaticToolFailure",
|
|
10241
|
+
agentId: binding.context.agentId,
|
|
10242
|
+
threadId: binding.context.threadId,
|
|
10243
|
+
runId: binding.context.runId,
|
|
10202
10244
|
turnId: binding.turnId,
|
|
10203
10245
|
toolCallId: handleId,
|
|
10204
|
-
toolName: input.toolName,
|
|
10205
|
-
executionClass,
|
|
10206
|
-
invocationKind: "programmatic",
|
|
10207
|
-
failureMode: tool.failureMode,
|
|
10208
10246
|
parentToolCallId: binding.outerToolCallId,
|
|
10209
10247
|
sequenceIndex: index,
|
|
10248
|
+
toolName: input.toolName,
|
|
10249
|
+
executionClass,
|
|
10250
|
+
kind,
|
|
10251
|
+
tag,
|
|
10252
|
+
message: toolFailureMessage(message),
|
|
10210
10253
|
};
|
|
10211
10254
|
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10255
|
+
return Effect.succeed(outcome);
|
|
10256
|
+
};
|
|
10257
|
+
|
|
10258
|
+
const telemetryDescriptor: ToolTelemetryDescriptor = {
|
|
10259
|
+
context: binding.context,
|
|
10260
|
+
turnId: binding.turnId,
|
|
10261
|
+
toolCallId: handleId,
|
|
10262
|
+
toolName: input.toolName,
|
|
10263
|
+
executionClass,
|
|
10264
|
+
invocationKind: "programmatic",
|
|
10265
|
+
failureMode: tool.failureMode,
|
|
10266
|
+
parentToolCallId: binding.outerToolCallId,
|
|
10267
|
+
sequenceIndex: index,
|
|
10268
|
+
};
|
|
10269
|
+
|
|
10270
|
+
const execution = measureProgrammaticToolCall(
|
|
10271
|
+
toolSpanTelemetry,
|
|
10272
|
+
telemetryDescriptor,
|
|
10273
|
+
Effect.gen(function* () {
|
|
10274
|
+
yield* Effect.logDebug("agent programmatic tool handler started").pipe(
|
|
10275
|
+
Effect.annotateLogs({
|
|
10276
|
+
agentId: binding.context.agentId,
|
|
10277
|
+
runId: binding.context.runId,
|
|
10278
|
+
turnId: binding.turnId,
|
|
10279
|
+
toolCallId: handleId,
|
|
10280
|
+
parentToolCallId: binding.outerToolCallId,
|
|
10281
|
+
toolName: input.toolName,
|
|
10282
|
+
sequenceIndex: index,
|
|
10283
|
+
}),
|
|
10284
|
+
);
|
|
10285
|
+
yield* Metric.update(toolCounter, 1);
|
|
10286
|
+
|
|
10287
|
+
let terminal:
|
|
10288
|
+
| {
|
|
10289
|
+
readonly encodedResult: unknown;
|
|
10290
|
+
readonly isFailure: boolean;
|
|
10291
|
+
readonly tag: string | undefined;
|
|
10292
|
+
}
|
|
10293
|
+
| undefined;
|
|
10294
|
+
|
|
10295
|
+
let resultAfterTerminal = false;
|
|
10296
|
+
|
|
10297
|
+
const handlerFailed = yield* Stream.unwrap(
|
|
10298
|
+
toolSpanTelemetry.isolateToolkitHandle(
|
|
10299
|
+
handle(input.toolName, input.encodedArguments, handleId),
|
|
10300
|
+
),
|
|
10301
|
+
).pipe(
|
|
10302
|
+
Stream.runForEach((result) =>
|
|
10303
|
+
Effect.sync(() => {
|
|
10304
|
+
// The direct path rejects a second result after the terminal
|
|
10305
|
+
// one; the broker preserves that protocol violation instead
|
|
10306
|
+
// of silently keeping the last value.
|
|
10307
|
+
if (terminal !== undefined) {
|
|
10308
|
+
resultAfterTerminal = true;
|
|
10309
|
+
|
|
10310
|
+
return;
|
|
10311
|
+
}
|
|
10312
|
+
if (!result.preliminary) {
|
|
10313
|
+
terminal = {
|
|
10314
|
+
encodedResult: toolResultForJson(tool, result),
|
|
10315
|
+
isFailure: result.isFailure,
|
|
10316
|
+
tag:
|
|
10317
|
+
observer === undefined || !result.isFailure
|
|
10318
|
+
? undefined
|
|
10319
|
+
: errorTag(result.result),
|
|
10320
|
+
};
|
|
10321
|
+
}
|
|
10322
|
+
}),
|
|
10323
|
+
),
|
|
10324
|
+
Effect.map(() => undefined),
|
|
10325
|
+
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10326
|
+
Effect.succeed(new BrokerCallFailure(error, cause)),
|
|
10327
|
+
),
|
|
10328
|
+
);
|
|
10329
|
+
|
|
10330
|
+
if (handlerFailed instanceof BrokerCallFailure) {
|
|
10331
|
+
const tag = errorTag(handlerFailed.error);
|
|
10332
|
+
|
|
10333
|
+
if (observer !== undefined) {
|
|
10334
|
+
failureObservation = {
|
|
10335
|
+
_tag: "ProgrammaticToolFailure",
|
|
10218
10336
|
agentId: binding.context.agentId,
|
|
10337
|
+
threadId: binding.context.threadId,
|
|
10219
10338
|
runId: binding.context.runId,
|
|
10220
10339
|
turnId: binding.turnId,
|
|
10221
10340
|
toolCallId: handleId,
|
|
10222
10341
|
parentToolCallId: binding.outerToolCallId,
|
|
10223
|
-
toolName: input.toolName,
|
|
10224
10342
|
sequenceIndex: index,
|
|
10225
|
-
|
|
10343
|
+
toolName: input.toolName,
|
|
10344
|
+
executionClass,
|
|
10345
|
+
kind: "handler-error",
|
|
10346
|
+
tag,
|
|
10347
|
+
cause: handlerFailed.cause,
|
|
10348
|
+
};
|
|
10349
|
+
}
|
|
10350
|
+
|
|
10351
|
+
return programmaticOutcomeError(index, tag, errorMessage(handlerFailed.error));
|
|
10352
|
+
}
|
|
10353
|
+
if (resultAfterTerminal) {
|
|
10354
|
+
return yield* startedFailure(
|
|
10355
|
+
"protocol",
|
|
10356
|
+
"ModelProtocolError",
|
|
10357
|
+
`Tool Call ${handleId} produced more than one terminal result`,
|
|
10358
|
+
);
|
|
10359
|
+
}
|
|
10360
|
+
if (terminal === undefined) {
|
|
10361
|
+
return yield* startedFailure(
|
|
10362
|
+
"protocol",
|
|
10363
|
+
"ModelProtocolError",
|
|
10364
|
+
`Tool Call ${handleId} completed without a terminal result`,
|
|
10226
10365
|
);
|
|
10227
|
-
|
|
10366
|
+
}
|
|
10367
|
+
if (terminal.isFailure) {
|
|
10368
|
+
if (observer !== undefined) {
|
|
10369
|
+
failureObservation = {
|
|
10370
|
+
_tag: "ProgrammaticToolFailure",
|
|
10371
|
+
agentId: binding.context.agentId,
|
|
10372
|
+
threadId: binding.context.threadId,
|
|
10373
|
+
runId: binding.context.runId,
|
|
10374
|
+
turnId: binding.turnId,
|
|
10375
|
+
toolCallId: handleId,
|
|
10376
|
+
parentToolCallId: binding.outerToolCallId,
|
|
10377
|
+
sequenceIndex: index,
|
|
10378
|
+
toolName: input.toolName,
|
|
10379
|
+
executionClass,
|
|
10380
|
+
kind: "declared-failure",
|
|
10381
|
+
tag: terminal.tag ?? "UnknownError",
|
|
10382
|
+
};
|
|
10383
|
+
}
|
|
10228
10384
|
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
toolSpanTelemetry.isolateToolkitHandle(
|
|
10241
|
-
(
|
|
10242
|
-
toolkit.handle as (
|
|
10243
|
-
name: string,
|
|
10244
|
-
params: unknown,
|
|
10245
|
-
id: string,
|
|
10246
|
-
) => Effect.Effect<
|
|
10247
|
-
Stream.Stream<Tool.HandlerResult<Tool.Any>, unknown, unknown>,
|
|
10248
|
-
unknown,
|
|
10249
|
-
unknown
|
|
10250
|
-
>
|
|
10251
|
-
)(input.toolName, input.encodedArguments, handleId),
|
|
10252
|
-
),
|
|
10253
|
-
).pipe(
|
|
10254
|
-
Stream.runForEach((result) =>
|
|
10255
|
-
Effect.sync(() => {
|
|
10256
|
-
// The direct path rejects a second result after the terminal
|
|
10257
|
-
// one; the broker preserves that protocol violation instead
|
|
10258
|
-
// of silently keeping the last value.
|
|
10259
|
-
if (terminal !== undefined) {
|
|
10260
|
-
resultAfterTerminal = true;
|
|
10261
|
-
|
|
10262
|
-
return;
|
|
10263
|
-
}
|
|
10264
|
-
if (!result.preliminary) {
|
|
10265
|
-
terminal = {
|
|
10266
|
-
encodedResult: toolResultForJson(tool, result),
|
|
10267
|
-
isFailure: result.isFailure,
|
|
10268
|
-
tag:
|
|
10269
|
-
observer === undefined || !result.isFailure
|
|
10270
|
-
? undefined
|
|
10271
|
-
: errorTag(result.result),
|
|
10272
|
-
};
|
|
10273
|
-
}
|
|
10274
|
-
}),
|
|
10275
|
-
),
|
|
10276
|
-
Effect.map(() => undefined),
|
|
10277
|
-
Effect.catchCauseFilter(Cause.findError, (error, cause) =>
|
|
10278
|
-
Effect.succeed(new BrokerCallFailure(error, cause)),
|
|
10279
|
-
),
|
|
10385
|
+
return {
|
|
10386
|
+
_tag: "ProgrammaticCallFailure",
|
|
10387
|
+
index,
|
|
10388
|
+
encodedResult: terminal.encodedResult,
|
|
10389
|
+
} as const;
|
|
10390
|
+
}
|
|
10391
|
+
if (Option.isNone(brokerDecodeJson(terminal.encodedResult))) {
|
|
10392
|
+
return yield* startedFailure(
|
|
10393
|
+
"protocol",
|
|
10394
|
+
"ModelProtocolError",
|
|
10395
|
+
`Tool ${input.toolName} produced a success encoding outside JSON`,
|
|
10280
10396
|
);
|
|
10397
|
+
}
|
|
10398
|
+
let encodedResult = terminal.encodedResult;
|
|
10281
10399
|
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
failureObservation = {
|
|
10287
|
-
_tag: "ProgrammaticToolFailure",
|
|
10288
|
-
agentId: binding.context.agentId,
|
|
10289
|
-
threadId: binding.context.threadId,
|
|
10290
|
-
runId: binding.context.runId,
|
|
10291
|
-
turnId: binding.turnId,
|
|
10292
|
-
toolCallId: handleId,
|
|
10293
|
-
parentToolCallId: binding.outerToolCallId,
|
|
10294
|
-
sequenceIndex: index,
|
|
10295
|
-
toolName: input.toolName,
|
|
10296
|
-
executionClass,
|
|
10297
|
-
kind: "handler-error",
|
|
10298
|
-
tag,
|
|
10299
|
-
cause: handlerFailed.cause,
|
|
10300
|
-
};
|
|
10301
|
-
}
|
|
10400
|
+
if (passOptions.redactResult !== undefined) {
|
|
10401
|
+
// A redactor is a substitution point: its replacement re-crosses
|
|
10402
|
+
// the JSON boundary or the call fails closed.
|
|
10403
|
+
const redacted = brokerDecodeJson(yield* passOptions.redactResult(encodedResult));
|
|
10302
10404
|
|
|
10303
|
-
|
|
10304
|
-
}
|
|
10305
|
-
if (resultAfterTerminal) {
|
|
10306
|
-
return yield* startedFailure(
|
|
10307
|
-
"protocol",
|
|
10308
|
-
"ModelProtocolError",
|
|
10309
|
-
`Tool Call ${handleId} produced more than one terminal result`,
|
|
10310
|
-
);
|
|
10311
|
-
}
|
|
10312
|
-
if (terminal === undefined) {
|
|
10405
|
+
if (Option.isNone(redacted)) {
|
|
10313
10406
|
return yield* startedFailure(
|
|
10314
10407
|
"protocol",
|
|
10315
10408
|
"ModelProtocolError",
|
|
10316
|
-
`Tool
|
|
10409
|
+
`The redacted result for Tool ${input.toolName} is outside the JSON surface`,
|
|
10317
10410
|
);
|
|
10318
10411
|
}
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
_tag: "ProgrammaticToolFailure",
|
|
10323
|
-
agentId: binding.context.agentId,
|
|
10324
|
-
threadId: binding.context.threadId,
|
|
10325
|
-
runId: binding.context.runId,
|
|
10326
|
-
turnId: binding.turnId,
|
|
10327
|
-
toolCallId: handleId,
|
|
10328
|
-
parentToolCallId: binding.outerToolCallId,
|
|
10329
|
-
sequenceIndex: index,
|
|
10330
|
-
toolName: input.toolName,
|
|
10331
|
-
executionClass,
|
|
10332
|
-
kind: "declared-failure",
|
|
10333
|
-
tag: terminal.tag ?? "UnknownError",
|
|
10334
|
-
};
|
|
10335
|
-
}
|
|
10412
|
+
encodedResult = redacted.value;
|
|
10413
|
+
}
|
|
10414
|
+
const snapshot = brokerSerializeJson(encodedResult);
|
|
10336
10415
|
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
}
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
return yield* startedFailure(
|
|
10345
|
-
"protocol",
|
|
10346
|
-
"ModelProtocolError",
|
|
10347
|
-
`Tool ${input.toolName} produced a success encoding outside JSON`,
|
|
10348
|
-
);
|
|
10349
|
-
}
|
|
10350
|
-
let encodedResult = terminal.encodedResult;
|
|
10351
|
-
|
|
10352
|
-
if (passOptions.redactResult !== undefined) {
|
|
10353
|
-
// A redactor is a substitution point: its replacement re-crosses
|
|
10354
|
-
// the JSON boundary or the call fails closed.
|
|
10355
|
-
const redacted = brokerDecodeJson(yield* passOptions.redactResult(encodedResult));
|
|
10356
|
-
|
|
10357
|
-
if (Option.isNone(redacted)) {
|
|
10358
|
-
return yield* startedFailure(
|
|
10359
|
-
"protocol",
|
|
10360
|
-
"ModelProtocolError",
|
|
10361
|
-
`The redacted result for Tool ${input.toolName} is outside the JSON surface`,
|
|
10362
|
-
);
|
|
10363
|
-
}
|
|
10364
|
-
encodedResult = redacted.value;
|
|
10365
|
-
}
|
|
10366
|
-
const snapshot = brokerSerializeJson(encodedResult);
|
|
10416
|
+
if (snapshot === undefined || snapshot.bytes > passOptions.maxResultBytes) {
|
|
10417
|
+
return yield* startedFailure(
|
|
10418
|
+
"infrastructure",
|
|
10419
|
+
"ProgrammaticResultLimitError",
|
|
10420
|
+
`Tool ${input.toolName} result of ${snapshot?.bytes ?? "unencodable"} bytes exceeds the ${passOptions.maxResultBytes}-byte broker bound`,
|
|
10421
|
+
);
|
|
10422
|
+
}
|
|
10367
10423
|
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
"ProgrammaticResultLimitError",
|
|
10372
|
-
`Tool ${input.toolName} result of ${snapshot?.bytes ?? "unencodable"} bytes exceeds the ${passOptions.maxResultBytes}-byte broker bound`,
|
|
10373
|
-
);
|
|
10374
|
-
}
|
|
10424
|
+
// Retain the exact representation admitted above. Reusing the handler or redactor
|
|
10425
|
+
// value would let later mutation or stateful getters escape the byte bound.
|
|
10426
|
+
const owned = Schema.decodeOption(Schema.fromJsonString(Schema.Json))(snapshot.text);
|
|
10375
10427
|
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10428
|
+
if (Option.isNone(owned)) {
|
|
10429
|
+
return yield* startedFailure(
|
|
10430
|
+
"protocol",
|
|
10431
|
+
"ModelProtocolError",
|
|
10432
|
+
`Tool ${input.toolName} produced a success encoding outside JSON`,
|
|
10380
10433
|
);
|
|
10434
|
+
}
|
|
10381
10435
|
|
|
10382
|
-
|
|
10383
|
-
|
|
10384
|
-
|
|
10385
|
-
|
|
10386
|
-
|
|
10387
|
-
|
|
10388
|
-
|
|
10436
|
+
return {
|
|
10437
|
+
_tag: "ProgrammaticCallSuccess",
|
|
10438
|
+
index,
|
|
10439
|
+
encodedResult: owned.value,
|
|
10440
|
+
} as const;
|
|
10441
|
+
}),
|
|
10442
|
+
);
|
|
10389
10443
|
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
|
|
10444
|
+
// Fix the broker outcome and terminal telemetry before delivery. Interruption of an
|
|
10445
|
+
// observer cannot turn a settled inner failure into an interrupted Handler attempt.
|
|
10446
|
+
// This still runs inline under the outer call's permit, before pass.invoke returns.
|
|
10447
|
+
const recorded = execution.pipe(
|
|
10448
|
+
Effect.tap((outcome) =>
|
|
10449
|
+
Effect.sync(() => {
|
|
10450
|
+
records[sequenceIndex] = {
|
|
10451
|
+
sequenceIndex,
|
|
10452
|
+
toolName: input.toolName,
|
|
10453
|
+
status:
|
|
10454
|
+
outcome._tag === "ProgrammaticCallSuccess"
|
|
10455
|
+
? "succeeded"
|
|
10456
|
+
: outcome._tag === "ProgrammaticCallFailure"
|
|
10457
|
+
? "failed"
|
|
10458
|
+
: "uncertain",
|
|
10459
|
+
...(outcome._tag === "ProgrammaticCallError"
|
|
10460
|
+
? { errorTag: outcome.errorTag }
|
|
10461
|
+
: {}),
|
|
10462
|
+
};
|
|
10395
10463
|
}),
|
|
10396
|
-
)
|
|
10464
|
+
),
|
|
10465
|
+
);
|
|
10397
10466
|
|
|
10398
|
-
|
|
10399
|
-
|
|
10400
|
-
|
|
10401
|
-
|
|
10402
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
: "uncertain",
|
|
10413
|
-
...(outcome._tag === "ProgrammaticCallError"
|
|
10414
|
-
? { errorTag: outcome.errorTag }
|
|
10415
|
-
: {}),
|
|
10416
|
-
};
|
|
10417
|
-
}),
|
|
10418
|
-
),
|
|
10419
|
-
);
|
|
10467
|
+
return yield* observer === undefined
|
|
10468
|
+
? recorded
|
|
10469
|
+
: recorded.pipe(
|
|
10470
|
+
Effect.tap(() =>
|
|
10471
|
+
failureObservation === undefined
|
|
10472
|
+
? Effect.void
|
|
10473
|
+
: deliverToolFailure(observer, failureObservation),
|
|
10474
|
+
),
|
|
10475
|
+
);
|
|
10476
|
+
}).pipe(
|
|
10477
|
+
Effect.updateContext((current: Context.Context<never>) =>
|
|
10478
|
+
Context.merge(current, handlerServices),
|
|
10479
|
+
),
|
|
10480
|
+
);
|
|
10420
10481
|
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
? Effect.void
|
|
10427
|
-
: deliverToolFailure(observer, failureObservation),
|
|
10428
|
-
),
|
|
10429
|
-
);
|
|
10430
|
-
}).pipe(Effect.provideContext(handlerServices)) as Effect.Effect<ProgrammaticCallOutcome>;
|
|
10431
|
-
|
|
10432
|
-
const pass: ToolBrokerPass = {
|
|
10433
|
-
snapshot: Effect.sync(() => records.map((record) => ({ ...record }))),
|
|
10434
|
-
invoke: (input) =>
|
|
10435
|
-
Effect.suspend(() => {
|
|
10436
|
-
const sequenceIndex = records.length;
|
|
10437
|
-
|
|
10438
|
-
records.push({ sequenceIndex, toolName: input.toolName, status: "not-started" });
|
|
10439
|
-
|
|
10440
|
-
// Check after acquiring the permit too: queued work cannot start after its owner exits.
|
|
10441
|
-
return permits
|
|
10442
|
-
.withPermit(
|
|
10443
|
-
Effect.suspend(() =>
|
|
10444
|
-
lifecycle.closed
|
|
10445
|
-
? preflightFailure(
|
|
10446
|
-
input,
|
|
10447
|
-
"infrastructure",
|
|
10448
|
-
"ToolBrokerUnavailableError",
|
|
10449
|
-
"The outer Tool Call for this pass has already settled",
|
|
10450
|
-
)
|
|
10451
|
-
: body(input, sequenceIndex),
|
|
10452
|
-
),
|
|
10453
|
-
)
|
|
10454
|
-
.pipe(
|
|
10455
|
-
Effect.tap((outcome) =>
|
|
10456
|
-
Effect.sync(() => {
|
|
10457
|
-
if (outcome._tag === "ProgrammaticCallError" && outcome.index === undefined) {
|
|
10458
|
-
records[sequenceIndex] = {
|
|
10459
|
-
sequenceIndex,
|
|
10460
|
-
toolName: input.toolName,
|
|
10461
|
-
status: "not-started",
|
|
10462
|
-
errorTag: outcome.errorTag,
|
|
10463
|
-
};
|
|
10464
|
-
}
|
|
10465
|
-
}),
|
|
10466
|
-
),
|
|
10467
|
-
);
|
|
10468
|
-
}),
|
|
10469
|
-
};
|
|
10482
|
+
const pass: ToolBrokerPass = {
|
|
10483
|
+
snapshot: Effect.sync(() => records.map((record) => ({ ...record }))),
|
|
10484
|
+
invoke: (input) =>
|
|
10485
|
+
Effect.suspend(() => {
|
|
10486
|
+
const sequenceIndex = records.length;
|
|
10470
10487
|
|
|
10471
|
-
|
|
10472
|
-
|
|
10488
|
+
records.push({ sequenceIndex, toolName: input.toolName, status: "not-started" });
|
|
10489
|
+
|
|
10490
|
+
// Check after acquiring the permit too: queued work cannot start after its owner exits.
|
|
10491
|
+
return permits
|
|
10492
|
+
.withPermit(
|
|
10493
|
+
Effect.suspend(() =>
|
|
10494
|
+
lifecycle.closed
|
|
10495
|
+
? preflightFailure(
|
|
10496
|
+
input,
|
|
10497
|
+
"infrastructure",
|
|
10498
|
+
"ToolBrokerUnavailableError",
|
|
10499
|
+
"The outer Tool Call for this pass has already settled",
|
|
10500
|
+
)
|
|
10501
|
+
: body(input, sequenceIndex),
|
|
10502
|
+
),
|
|
10503
|
+
)
|
|
10504
|
+
.pipe(
|
|
10505
|
+
Effect.tap((outcome) =>
|
|
10506
|
+
Effect.sync(() => {
|
|
10507
|
+
if (outcome._tag === "ProgrammaticCallError" && outcome.index === undefined) {
|
|
10508
|
+
records[sequenceIndex] = {
|
|
10509
|
+
sequenceIndex,
|
|
10510
|
+
toolName: input.toolName,
|
|
10511
|
+
status: "not-started",
|
|
10512
|
+
errorTag: outcome.errorTag,
|
|
10513
|
+
};
|
|
10514
|
+
}
|
|
10515
|
+
}),
|
|
10516
|
+
),
|
|
10517
|
+
);
|
|
10518
|
+
}),
|
|
10519
|
+
};
|
|
10520
|
+
|
|
10521
|
+
return pass;
|
|
10522
|
+
}),
|
|
10473
10523
|
};
|
|
10474
10524
|
|
|
10475
10525
|
return {
|
|
@@ -10553,98 +10603,97 @@ const makeDurableStepService = <HookError, HookRequirements>(
|
|
|
10553
10603
|
const usedNames = new Set<string>();
|
|
10554
10604
|
|
|
10555
10605
|
return {
|
|
10556
|
-
do: <Output extends Schema.Top, BodyError, BodyServices>(
|
|
10606
|
+
do: Effect.fnUntraced(function* <Output extends Schema.Top, BodyError, BodyServices>(
|
|
10557
10607
|
name: string,
|
|
10558
10608
|
output: Output,
|
|
10559
10609
|
execute: Effect.Effect<Output["Type"], BodyError, BodyServices>,
|
|
10560
|
-
)
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10610
|
+
) {
|
|
10611
|
+
if (usedNames.has(name)) {
|
|
10612
|
+
return yield* DurableStepError.make({
|
|
10613
|
+
toolCallId,
|
|
10614
|
+
stepName: name,
|
|
10615
|
+
reason: "duplicate-step-name",
|
|
10616
|
+
message: "Durable Step name was reused within one Tool Call",
|
|
10617
|
+
});
|
|
10618
|
+
}
|
|
10619
|
+
usedNames.add(name);
|
|
10620
|
+
const key: RunStepKey = { toolCallId, stepName: name };
|
|
10621
|
+
|
|
10622
|
+
const recorded = yield* provideHookServices(hook.lookup(key), hookServices).pipe(
|
|
10623
|
+
Effect.mapError((cause) =>
|
|
10624
|
+
DurableStepError.make({
|
|
10564
10625
|
toolCallId,
|
|
10565
10626
|
stepName: name,
|
|
10566
|
-
reason: "
|
|
10567
|
-
message: "Durable Step
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10627
|
+
reason: "lookup-failed",
|
|
10628
|
+
message: "Durable Step lookup failed",
|
|
10629
|
+
cause,
|
|
10630
|
+
}),
|
|
10631
|
+
),
|
|
10632
|
+
);
|
|
10572
10633
|
|
|
10573
|
-
|
|
10574
|
-
|
|
10634
|
+
if (Option.isSome(recorded)) {
|
|
10635
|
+
return yield* Schema.decodeUnknownEffect(output)(recorded.value.encodedOutput).pipe(
|
|
10636
|
+
Effect.mapError(() =>
|
|
10575
10637
|
DurableStepError.make({
|
|
10576
10638
|
toolCallId,
|
|
10577
10639
|
stepName: name,
|
|
10578
|
-
reason: "
|
|
10579
|
-
message: "Durable Step
|
|
10580
|
-
cause,
|
|
10640
|
+
reason: "recorded-result-invalid",
|
|
10641
|
+
message: "Recorded Durable Step result failed the declared output Schema",
|
|
10581
10642
|
}),
|
|
10582
10643
|
),
|
|
10583
10644
|
);
|
|
10645
|
+
}
|
|
10584
10646
|
|
|
10585
|
-
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
DurableStepError.make({
|
|
10602
|
-
toolCallId,
|
|
10603
|
-
stepName: name,
|
|
10604
|
-
reason:
|
|
10605
|
-
cause instanceof AgentPersistenceCapacityError
|
|
10606
|
-
? "capacity-exhausted"
|
|
10607
|
-
: "reservation-failed",
|
|
10608
|
-
message:
|
|
10609
|
-
cause instanceof AgentPersistenceCapacityError
|
|
10610
|
-
? "Durable Step has no room for a valid saved result"
|
|
10611
|
-
: "Durable Step capacity reservation failed",
|
|
10612
|
-
cause,
|
|
10613
|
-
}),
|
|
10614
|
-
),
|
|
10647
|
+
return yield* Effect.acquireUseRelease(
|
|
10648
|
+
provideHookServices(hook.reserve(key), hookServices).pipe(
|
|
10649
|
+
Effect.mapError((cause) =>
|
|
10650
|
+
DurableStepError.make({
|
|
10651
|
+
toolCallId,
|
|
10652
|
+
stepName: name,
|
|
10653
|
+
reason:
|
|
10654
|
+
cause instanceof AgentPersistenceCapacityError
|
|
10655
|
+
? "capacity-exhausted"
|
|
10656
|
+
: "reservation-failed",
|
|
10657
|
+
message:
|
|
10658
|
+
cause instanceof AgentPersistenceCapacityError
|
|
10659
|
+
? "Durable Step has no room for a valid saved result"
|
|
10660
|
+
: "Durable Step capacity reservation failed",
|
|
10661
|
+
cause,
|
|
10662
|
+
}),
|
|
10615
10663
|
),
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
),
|
|
10629
|
-
)
|
|
10664
|
+
),
|
|
10665
|
+
() =>
|
|
10666
|
+
Effect.gen(function* () {
|
|
10667
|
+
const value = yield* execute;
|
|
10668
|
+
|
|
10669
|
+
const encodedOutput = yield* Schema.encodeEffect(output)(value).pipe(
|
|
10670
|
+
Effect.mapError(() =>
|
|
10671
|
+
DurableStepError.make({
|
|
10672
|
+
toolCallId,
|
|
10673
|
+
stepName: name,
|
|
10674
|
+
reason: "output-encoding-failed",
|
|
10675
|
+
message: "Durable Step output failed the declared output Schema",
|
|
10676
|
+
}),
|
|
10677
|
+
),
|
|
10678
|
+
);
|
|
10630
10679
|
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
|
|
10680
|
+
yield* provideHookServices(hook.commit(key, encodedOutput), hookServices).pipe(
|
|
10681
|
+
Effect.mapError((cause) =>
|
|
10682
|
+
DurableStepError.make({
|
|
10683
|
+
toolCallId,
|
|
10684
|
+
stepName: name,
|
|
10685
|
+
reason: "commit-failed",
|
|
10686
|
+
message: "Durable Step commit failed",
|
|
10687
|
+
cause,
|
|
10688
|
+
}),
|
|
10689
|
+
),
|
|
10690
|
+
);
|
|
10642
10691
|
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
|
|
10647
|
-
|
|
10692
|
+
return value;
|
|
10693
|
+
}),
|
|
10694
|
+
(release) => release,
|
|
10695
|
+
);
|
|
10696
|
+
}),
|
|
10648
10697
|
};
|
|
10649
10698
|
};
|
|
10650
10699
|
|