effect-agent 0.1.0-beta.93 → 0.1.0-beta.94
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/{Agent-RklVROrm.mjs → Agent-CG_VMrtA.mjs} +2 -2
- package/dist/{Agent-RklVROrm.mjs.map → Agent-CG_VMrtA.mjs.map} +1 -1
- package/dist/{Agent-CN0EWRsR.d.mts → Agent-CM6JubNX.d.mts} +2 -2
- package/dist/{AgentPolicy-CetmQrf3.d.mts → AgentPolicy-BqDoSXO6.d.mts} +2 -2
- package/dist/{AgentRuntime-BPjQM1Nv.mjs → AgentRuntime-Cdvqw7l_.mjs} +88 -32
- package/dist/AgentRuntime-Cdvqw7l_.mjs.map +1 -0
- package/dist/{AgentRuntime-uxR_a4VM.d.mts → AgentRuntime-CufqQ4JM.d.mts} +8 -8
- package/dist/{ContextCompactor-Dxu5zhOL.d.mts → ContextCompactor-WwSIG_Z2.d.mts} +2 -2
- package/dist/{DurableAgentRuntime-CdrBuKZY.mjs → DurableAgentRuntime-BaGsWDHO.mjs} +9 -5
- package/dist/DurableAgentRuntime-BaGsWDHO.mjs.map +1 -0
- package/dist/{EventSource-c6GRTCsl.d.mts → EventSource-DVfX1GRH.d.mts} +3 -3
- package/dist/{Messaging-CkcIdt4I.d.mts → Messaging-QMYhp297.d.mts} +3 -3
- package/dist/{MessagingHost-CRk0kXzT.d.mts → MessagingHost-gAxs5gme.d.mts} +3 -3
- package/dist/{Output-D6SkedVx.d.mts → Output-CjocJzsl.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-QzFbW2LQ.d.mts → PreparedInputAdmission-DoWaMC2R.d.mts} +4 -4
- package/dist/{Records-vFp_ZQ9Y.d.mts → Records-B84j3Jq_.d.mts} +21 -9
- package/dist/{Records-C9cezOEf.mjs → Records-CsEsSW2o.mjs} +5 -2
- package/dist/Records-CsEsSW2o.mjs.map +1 -0
- package/dist/{RunJournal-lwbrh2hZ.mjs → RunJournal-yYpUlTOE.mjs} +3 -2
- package/dist/RunJournal-yYpUlTOE.mjs.map +1 -0
- package/dist/{RunOptions-g1aigcKI.d.mts → RunOptions-CE-G3niT.d.mts} +14 -8
- package/dist/{Schedule-BkZvKyMw.d.mts → Schedule-DCYBfhgT.d.mts} +2 -2
- package/dist/{Scheduling-D0QqOoeT.mjs → Scheduling-CUuYc3-D.mjs} +3 -3
- package/dist/{Scheduling-D0QqOoeT.mjs.map → Scheduling-CUuYc3-D.mjs.map} +1 -1
- package/dist/{Subagent-CnTzCy8k.mjs → Subagent-Cbfzylz1.mjs} +3 -3
- package/dist/{Subagent-CnTzCy8k.mjs.map → Subagent-Cbfzylz1.mjs.map} +1 -1
- package/dist/{Subagent-DyfzHNdv.d.mts → Subagent-DscbtbNY.d.mts} +6 -6
- package/dist/{SubagentHost-CJUBQlcc.d.mts → SubagentHost-DaFMZnVR.d.mts} +4 -4
- package/dist/{Subscription-CKQ0KDHN.d.mts → Subscription-C8IHdmFk.d.mts} +4 -4
- package/dist/{SubscriptionInput-Cth8F_7b.d.mts → SubscriptionInput-DhM3jUW2.d.mts} +3 -3
- package/dist/{ToolResult-DmmgoChv.d.mts → ToolResult-BKdqWRff.d.mts} +20 -3
- package/dist/{Worker-CaPYykpe.d.mts → Worker--j87JI__.d.mts} +2 -2
- package/dist/capabilities/Approval.mjs +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/Messaging.d.mts +2 -2
- package/dist/capabilities/ModelContext.mjs +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +2 -2
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/ToolDiscovery.d.mts +19 -4
- package/dist/capabilities/ToolDiscovery.mjs +33 -14
- package/dist/capabilities/ToolDiscovery.mjs.map +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/AgentPolicy.d.mts +1 -1
- package/dist/core/Thread.mjs +1 -1
- package/dist/core/ToolResult.d.mts +2 -2
- package/dist/core/ToolResult.mjs +17 -1
- package/dist/core/ToolResult.mjs.map +1 -1
- package/dist/core/Worker.d.mts +1 -1
- package/dist/core/Worker.mjs +1 -1
- package/dist/durable/ActivityStore.d.mts +1 -1
- package/dist/durable/ActivityStore.mjs +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/Admin.mjs +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +1 -1
- package/dist/durable/Digest.d.mts +1 -1
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +1 -1
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/GitHubWorkflowSource.mjs +1 -1
- package/dist/durable/MessageDelivery.d.mts +23 -23
- package/dist/durable/MessageDelivery.mjs +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +40 -40
- package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +2 -2
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +1 -1
- package/dist/durable/Records.mjs +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/Recovery.mjs +1 -1
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/Schedule.d.mts +1 -1
- package/dist/durable/Schedule.mjs +1 -1
- package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
- package/dist/durable/ScheduleStoreConformance.mjs +1 -1
- package/dist/durable/ScheduleTransition.d.mts +1 -1
- package/dist/durable/ScheduleTransition.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +2 -2
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
- package/dist/durable/SqlStorageV2Upgrade.mjs +1 -1
- package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
- package/dist/durable/SqlSubscriptionStore.mjs +1 -1
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +2 -2
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +1 -1
- package/dist/durable/SubscriptionTools.d.mts +3 -3
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/SubscriptionTransition.mjs +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +2 -2
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +1 -1
- package/dist/durable/ThreadInvariants.mjs +1 -1
- package/dist/durable/ThreadProjection.d.mts +1 -1
- package/dist/durable/ThreadProjection.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +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 +1 -1
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +4 -4
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/Compaction.d.mts +1 -1
- package/dist/engine/ContextCompactor.d.mts +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/RunOptions.mjs.map +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/index.d.mts +18 -18
- package/dist/index.mjs +8 -8
- package/package.json +1 -1
- package/src/capabilities/ToolDiscovery.ts +48 -18
- package/src/core/ToolResult.ts +20 -0
- package/src/durable/DurableAgentRuntime.ts +7 -0
- package/src/durable/Records.ts +3 -0
- package/src/durable/RunJournal.ts +5 -0
- package/src/engine/RunOptions.ts +9 -3
- package/src/engine/internal/agent-runtime.ts +254 -67
- package/dist/AgentRuntime-BPjQM1Nv.mjs.map +0 -1
- package/dist/DurableAgentRuntime-CdrBuKZY.mjs.map +0 -1
- package/dist/Records-C9cezOEf.mjs.map +0 -1
- package/dist/RunJournal-lwbrh2hZ.mjs.map +0 -1
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
Queue,
|
|
18
18
|
Result,
|
|
19
19
|
Schema,
|
|
20
|
+
SchemaGetter,
|
|
20
21
|
Scope,
|
|
21
22
|
Semaphore,
|
|
22
23
|
Stream,
|
|
@@ -100,6 +101,7 @@ import {
|
|
|
100
101
|
import type { Selection } from "../../core/ToolExposure.ts";
|
|
101
102
|
import { AdditionalToolCatalog, DiscoveryTool, Snapshot } from "../../core/ToolExposure.ts";
|
|
102
103
|
import {
|
|
104
|
+
ToolParameterRejection,
|
|
103
105
|
applyToolResultBounds,
|
|
104
106
|
unserializableToolResult,
|
|
105
107
|
type ToolResultBounds,
|
|
@@ -646,6 +648,8 @@ interface TurnTrace {
|
|
|
646
648
|
/** Turn completion held with provider results so malformed trailing parts append neither. */
|
|
647
649
|
turnCompletion: { readonly finishReason: Response.FinishReason } | undefined;
|
|
648
650
|
readonly applicationToolCalls: Array<Response.ToolCallPart<string, unknown>>;
|
|
651
|
+
/** Fresh validation failures retained independently of executable parameters. */
|
|
652
|
+
readonly toolParameterRejections: Map<string, ToolParameterRejection>;
|
|
649
653
|
/** Durable-hook view of the application calls, in declaration order (encoded parameters). */
|
|
650
654
|
readonly applicationCallDescriptors: Array<RunToolCallDescriptor>;
|
|
651
655
|
readonly applicationToolResults: Array<{
|
|
@@ -861,15 +865,58 @@ const inspectModelResponsePartCapacity = (
|
|
|
861
865
|
});
|
|
862
866
|
|
|
863
867
|
/**
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
868
|
+
* LanguageModel validates encoded parameters even with automatic resolution disabled.
|
|
869
|
+
* Defer only recoverable application parameter validation; the declaration's JSON codec
|
|
870
|
+
* still exposes the original schema to providers and preserves their wire normalization.
|
|
871
|
+
* No handler is installed or executed by this transport-only Toolkit.
|
|
868
872
|
*/
|
|
873
|
+
const defersToolParameters = (tool: Tool.Any): boolean =>
|
|
874
|
+
tool.failureMode === "return" &&
|
|
875
|
+
!(Tool.isProviderDefined(tool) && !tool.requiresHandler) &&
|
|
876
|
+
!(Tool.isDynamic(tool) && tool.jsonSchema !== undefined);
|
|
877
|
+
|
|
878
|
+
const deferredToolParameterToolkit = <Tools extends Record<string, Tool.Any>>(
|
|
879
|
+
toolkit: Toolkit.Toolkit<Tools>,
|
|
880
|
+
): Toolkit.Toolkit<Record<string, Tool.Any>> => {
|
|
881
|
+
// Preserve the native request unchanged when it has no recoverable parameters.
|
|
882
|
+
// Toolkit's handler parameter variance is irrelevant to this resolution-disabled transport.
|
|
883
|
+
if (!Object.values(toolkit.tools).some(defersToolParameters))
|
|
884
|
+
return toolkit as unknown as Toolkit.Toolkit<Record<string, Tool.Any>>;
|
|
885
|
+
|
|
886
|
+
return Toolkit.make(
|
|
887
|
+
...Object.values(toolkit.tools).map((tool) =>
|
|
888
|
+
!defersToolParameters(tool)
|
|
889
|
+
? tool
|
|
890
|
+
: tool.setParameters(
|
|
891
|
+
Schema.declareConstructor<unknown>()(
|
|
892
|
+
[],
|
|
893
|
+
() => (input) =>
|
|
894
|
+
Schema.decodeUnknownEffect(Schema.toEncoded(tool.parametersSchema))(input).pipe(
|
|
895
|
+
Effect.orElseSucceed(() => input),
|
|
896
|
+
),
|
|
897
|
+
{
|
|
898
|
+
description: Tool.getDescription(tool),
|
|
899
|
+
toCodecJson: () =>
|
|
900
|
+
Schema.link<unknown>()(Schema.toEncoded(tool.parametersSchema), {
|
|
901
|
+
decode: SchemaGetter.passthrough(),
|
|
902
|
+
encode: SchemaGetter.passthrough(),
|
|
903
|
+
}),
|
|
904
|
+
},
|
|
905
|
+
),
|
|
906
|
+
),
|
|
907
|
+
),
|
|
908
|
+
);
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
/** Own fresh JSON arguments without accepting them as executable parameters. */
|
|
869
912
|
const encodedToolParameterToolkit = (toolkit: Toolkit.Any): Toolkit.Any =>
|
|
870
913
|
Toolkit.make(
|
|
871
914
|
...Object.values(toolkit.tools).map((tool) =>
|
|
872
|
-
tool.setParameters(
|
|
915
|
+
tool.setParameters(
|
|
916
|
+
tool.failureMode === "return" && !(Tool.isProviderDefined(tool) && !tool.requiresHandler)
|
|
917
|
+
? Schema.Json
|
|
918
|
+
: Schema.toEncoded(tool.parametersSchema),
|
|
919
|
+
),
|
|
873
920
|
),
|
|
874
921
|
);
|
|
875
922
|
|
|
@@ -1011,7 +1058,7 @@ interface PreparedToolCall<Tools extends Record<string, Tool.Any>> {
|
|
|
1011
1058
|
readonly call: Response.ToolCallPart<string, unknown>;
|
|
1012
1059
|
readonly name: keyof Tools & string;
|
|
1013
1060
|
readonly toolCallId: ToolCallId;
|
|
1014
|
-
readonly
|
|
1061
|
+
readonly validation: Result.Result<Tool.Parameters<ToolUnion<Tools>>, ToolParameterRejection>;
|
|
1015
1062
|
readonly tool: ToolUnion<Tools>;
|
|
1016
1063
|
readonly declarationIndex: number;
|
|
1017
1064
|
}
|
|
@@ -1128,7 +1175,7 @@ const decodeToolCallParameters = <Tools extends Record<string, Tool.Any>>(
|
|
|
1128
1175
|
tool: ToolUnion<Tools>,
|
|
1129
1176
|
toolName: string,
|
|
1130
1177
|
encodedParams: unknown,
|
|
1131
|
-
boundary: "execution" | "resume" = "execution",
|
|
1178
|
+
boundary: "model" | "execution" | "resume" = "execution",
|
|
1132
1179
|
): Effect.Effect<
|
|
1133
1180
|
Tool.Parameters<ToolUnion<Tools>>,
|
|
1134
1181
|
ModelProtocolError,
|
|
@@ -1145,20 +1192,24 @@ const decodeToolCallParameters = <Tools extends Record<string, Tool.Any>>(
|
|
|
1145
1192
|
return decodeParameters(encodedParams).pipe(
|
|
1146
1193
|
Effect.mapError((cause) =>
|
|
1147
1194
|
ModelProtocolError.make({
|
|
1148
|
-
message:
|
|
1195
|
+
message:
|
|
1196
|
+
boundary === "model"
|
|
1197
|
+
? `Invalid parameters for Tool ${toolName}: ${cause.message}`
|
|
1198
|
+
: `Recorded parameters for Tool ${toolName} failed validation${boundary === "resume" ? " on resume" : ""}: ${cause.message}`,
|
|
1149
1199
|
}),
|
|
1150
1200
|
),
|
|
1151
1201
|
);
|
|
1152
1202
|
};
|
|
1153
1203
|
|
|
1154
1204
|
/**
|
|
1155
|
-
* Decode
|
|
1156
|
-
*
|
|
1205
|
+
* Decode executable parameters for approval while retaining their encoded form for
|
|
1206
|
+
* Toolkit.handle. A recorded rejection is a terminal failure, never an executable call.
|
|
1157
1207
|
*/
|
|
1158
1208
|
const prepareToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
1159
1209
|
toolkit: Toolkit.WithHandler<Tools>,
|
|
1160
1210
|
call: Response.ToolCallPart<string, unknown>,
|
|
1161
1211
|
declarationIndex: number,
|
|
1212
|
+
rejection?: ToolParameterRejection,
|
|
1162
1213
|
): Effect.Effect<
|
|
1163
1214
|
PreparedToolCall<Tools>,
|
|
1164
1215
|
ModelProtocolError,
|
|
@@ -1173,20 +1224,16 @@ const prepareToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
|
1173
1224
|
}
|
|
1174
1225
|
const tool = toolkit.tools[name] as ToolUnion<Tools>;
|
|
1175
1226
|
|
|
1176
|
-
return
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
})),
|
|
1187
|
-
),
|
|
1188
|
-
),
|
|
1189
|
-
);
|
|
1227
|
+
return Effect.gen(function* () {
|
|
1228
|
+
const toolCallId = yield* decodeToolCallId(call.id);
|
|
1229
|
+
|
|
1230
|
+
const validation: PreparedToolCall<Tools>["validation"] =
|
|
1231
|
+
rejection === undefined
|
|
1232
|
+
? Result.succeed(yield* decodeToolCallParameters<Tools>(tool, call.name, call.params))
|
|
1233
|
+
: Result.fail(rejection);
|
|
1234
|
+
|
|
1235
|
+
return { call, name, toolCallId, validation, tool, declarationIndex };
|
|
1236
|
+
});
|
|
1190
1237
|
};
|
|
1191
1238
|
|
|
1192
1239
|
/**
|
|
@@ -1577,6 +1624,9 @@ const approvalDecision = <Tools extends Record<string, Tool.Any>, Error, Require
|
|
|
1577
1624
|
Requirements
|
|
1578
1625
|
> =>
|
|
1579
1626
|
Effect.gen(function* () {
|
|
1627
|
+
if (Result.isFailure(prepared.validation)) return { required: false } as const;
|
|
1628
|
+
const decodedParams = prepared.validation.success;
|
|
1629
|
+
|
|
1580
1630
|
const approval = prepared.tool.needsApproval;
|
|
1581
1631
|
|
|
1582
1632
|
if (approval === undefined || approval === false) {
|
|
@@ -1586,7 +1636,7 @@ const approvalDecision = <Tools extends Record<string, Tool.Any>, Error, Require
|
|
|
1586
1636
|
const required =
|
|
1587
1637
|
typeof approval === "function"
|
|
1588
1638
|
? yield* Effect.suspend(() => {
|
|
1589
|
-
const result = approval(
|
|
1639
|
+
const result = approval(decodedParams, {
|
|
1590
1640
|
toolCallId: prepared.call.id,
|
|
1591
1641
|
messages: context.history.content,
|
|
1592
1642
|
});
|
|
@@ -1623,7 +1673,7 @@ const approvalDecision = <Tools extends Record<string, Tool.Any>, Error, Require
|
|
|
1623
1673
|
turnId,
|
|
1624
1674
|
toolCallId,
|
|
1625
1675
|
toolName: prepared.call.name,
|
|
1626
|
-
parameters:
|
|
1676
|
+
parameters: decodedParams,
|
|
1627
1677
|
});
|
|
1628
1678
|
|
|
1629
1679
|
return {
|
|
@@ -2044,29 +2094,31 @@ const executePreparedToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
|
2044
2094
|
);
|
|
2045
2095
|
};
|
|
2046
2096
|
|
|
2047
|
-
const started =
|
|
2048
|
-
|
|
2049
|
-
|
|
2097
|
+
const started = Result.isFailure(prepared.validation)
|
|
2098
|
+
? Stream.empty
|
|
2099
|
+
: Stream.fromEffect(
|
|
2100
|
+
Effect.gen(function* () {
|
|
2101
|
+
const toolCallId = yield* decodeToolCallId(call.id);
|
|
2050
2102
|
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2103
|
+
yield* Effect.logDebug("agent tool handler started").pipe(
|
|
2104
|
+
Effect.annotateLogs({
|
|
2105
|
+
agentId: context.agentId,
|
|
2106
|
+
runId: context.runId,
|
|
2107
|
+
turnId,
|
|
2108
|
+
...(telemetryToolCallId === undefined ? {} : { toolCallId: telemetryToolCallId }),
|
|
2109
|
+
toolName: call.name,
|
|
2110
|
+
}),
|
|
2111
|
+
);
|
|
2112
|
+
yield* Metric.update(toolCounter, 1);
|
|
2061
2113
|
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2114
|
+
return ToolCallStarted.make({
|
|
2115
|
+
...(yield* eventBase(context)),
|
|
2116
|
+
turnId,
|
|
2117
|
+
toolCallId,
|
|
2118
|
+
toolName: call.name,
|
|
2119
|
+
});
|
|
2120
|
+
}).pipe(Effect.withLogSpan("AgentRuntime.tool")),
|
|
2121
|
+
);
|
|
2070
2122
|
|
|
2071
2123
|
// Dynamic Tool lookup erases the name/ParametersEncoded correlation. The native handler
|
|
2072
2124
|
// decodes these already-preflighted canonical parameters; only its input signature is widened.
|
|
@@ -2076,15 +2128,37 @@ const executePreparedToolCall = <Tools extends Record<string, Tool.Any>>(
|
|
|
2076
2128
|
toolCallId: string,
|
|
2077
2129
|
) => ReturnType<typeof toolkit.handle>;
|
|
2078
2130
|
|
|
2131
|
+
const rejection = Result.isFailure(prepared.validation) ? prepared.validation.failure : undefined;
|
|
2132
|
+
|
|
2133
|
+
const handlerResults: Stream.Stream<
|
|
2134
|
+
Tool.HandlerResult<Tool.Any>,
|
|
2135
|
+
ToolExecutionError,
|
|
2136
|
+
ToolSpanTelemetry | Tool.HandlerServices<ToolUnion<Tools>>
|
|
2137
|
+
> = rejection === undefined
|
|
2138
|
+
? Stream.unwrap(
|
|
2139
|
+
Effect.flatMap(ToolSpanTelemetry, ({ isolateToolkitHandle }) =>
|
|
2140
|
+
isolateToolkitHandle(handle.call(toolkit, prepared.name, call.params, call.id)),
|
|
2141
|
+
),
|
|
2142
|
+
)
|
|
2143
|
+
: Stream.fromEffect(
|
|
2144
|
+
Schema.decodeEffect(Schema.toCodecJson(AiError.AiError))(rejection.error).pipe(
|
|
2145
|
+
Effect.mapError(() =>
|
|
2146
|
+
ModelProtocolError.make({ message: "Invalid parameter rejection evidence" }),
|
|
2147
|
+
),
|
|
2148
|
+
Effect.map((error) => ({
|
|
2149
|
+
result: error,
|
|
2150
|
+
encodedResult: rejection.error,
|
|
2151
|
+
isFailure: true,
|
|
2152
|
+
preliminary: false,
|
|
2153
|
+
})),
|
|
2154
|
+
),
|
|
2155
|
+
);
|
|
2156
|
+
|
|
2079
2157
|
const results: Stream.Stream<
|
|
2080
2158
|
RunEvent,
|
|
2081
2159
|
ToolExecutionError,
|
|
2082
2160
|
ToolSpanTelemetry | Tool.HandlerServices<ToolUnion<Tools>>
|
|
2083
|
-
> =
|
|
2084
|
-
Effect.flatMap(ToolSpanTelemetry, ({ isolateToolkitHandle }) =>
|
|
2085
|
-
isolateToolkitHandle(handle.call(toolkit, prepared.name, call.params, call.id)),
|
|
2086
|
-
),
|
|
2087
|
-
).pipe(
|
|
2161
|
+
> = handlerResults.pipe(
|
|
2088
2162
|
Stream.mapEffect((result): Effect.Effect<RunEvent | undefined, ModelProtocolError> =>
|
|
2089
2163
|
Effect.gen(function* () {
|
|
2090
2164
|
if (terminal || trace.finalToolResultIds.has(call.id)) {
|
|
@@ -2395,9 +2469,15 @@ const executeToolBatch = <Tools extends Record<string, Tool.Any>, HookError, Hoo
|
|
|
2395
2469
|
});
|
|
2396
2470
|
}
|
|
2397
2471
|
|
|
2398
|
-
// Resolve
|
|
2472
|
+
// Resolve the whole batch before constructing streams. Only calls with recorded
|
|
2473
|
+
// parameter rejection evidence bypass executable-parameter decoding and approval.
|
|
2399
2474
|
const prepared = yield* Effect.forEach(calls, (call, declarationIndex) =>
|
|
2400
|
-
prepareToolCall(
|
|
2475
|
+
prepareToolCall(
|
|
2476
|
+
toolkit,
|
|
2477
|
+
call,
|
|
2478
|
+
declarationIndex,
|
|
2479
|
+
trace.toolParameterRejections.get(call.id),
|
|
2480
|
+
),
|
|
2401
2481
|
);
|
|
2402
2482
|
|
|
2403
2483
|
if (
|
|
@@ -2425,7 +2505,9 @@ const executeToolBatch = <Tools extends Record<string, Tool.Any>, HookError, Hoo
|
|
|
2425
2505
|
// Reuse the canonical wire-form descriptors already committed with the response. Handler
|
|
2426
2506
|
// parameters were decoded/re-encoded separately above, so the host policy never receives
|
|
2427
2507
|
// the handler's live parameter object.
|
|
2428
|
-
const descriptors = trace.applicationCallDescriptors
|
|
2508
|
+
const descriptors = trace.applicationCallDescriptors.filter(
|
|
2509
|
+
(call) => !trace.toolParameterRejections.has(call.toolCallId),
|
|
2510
|
+
);
|
|
2429
2511
|
|
|
2430
2512
|
const durability = options.durability;
|
|
2431
2513
|
// The hook's requirements are captured here (they are already part of
|
|
@@ -4711,19 +4793,52 @@ const eventsForPart = Effect.fnUntraced(function* <Tools extends Record<string,
|
|
|
4711
4793
|
const toolCallId = yield* decodeToolCallId(part.id);
|
|
4712
4794
|
const tool = tools[part.name] as ToolUnion<Tools>;
|
|
4713
4795
|
|
|
4714
|
-
const
|
|
4715
|
-
tool,
|
|
4716
|
-
part.name,
|
|
4717
|
-
part.params,
|
|
4796
|
+
const decoded = yield* Effect.result(
|
|
4797
|
+
decodeToolCallParameters<Tools>(tool, part.name, part.params, "model"),
|
|
4718
4798
|
);
|
|
4719
4799
|
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4800
|
+
let parameters: Schema.Json;
|
|
4801
|
+
|
|
4802
|
+
if (Result.isFailure(decoded)) {
|
|
4803
|
+
if (part.providerExecuted || tool.failureMode !== "return") return yield* decoded.failure;
|
|
4804
|
+
parameters = yield* decodeEventJson(part.params, "Tool parameters");
|
|
4805
|
+
|
|
4806
|
+
// Approval needs decoded arguments, so validation precedes Toolkit.handle. Use
|
|
4807
|
+
// Effect's native error and codec; calling the handler to discover this failure
|
|
4808
|
+
// would cross the authorization boundary if a decoder changed its answer.
|
|
4809
|
+
const error = AiError.make({
|
|
4810
|
+
module: "Toolkit",
|
|
4811
|
+
method: `${part.name}.handle`,
|
|
4812
|
+
reason: new AiError.ToolParameterValidationError({
|
|
4813
|
+
toolName: part.name,
|
|
4814
|
+
description: decoded.failure.message,
|
|
4815
|
+
}),
|
|
4816
|
+
});
|
|
4817
|
+
|
|
4818
|
+
const encodedError = yield* Schema.encodeEffect(Schema.toCodecJson(AiError.AiError))(
|
|
4819
|
+
error,
|
|
4820
|
+
).pipe(
|
|
4821
|
+
Effect.mapError(() =>
|
|
4822
|
+
ModelProtocolError.make({ message: "Unable to encode parameter rejection" }),
|
|
4823
|
+
),
|
|
4824
|
+
);
|
|
4725
4825
|
|
|
4726
|
-
|
|
4826
|
+
const rejection = yield* Schema.decodeUnknownEffect(ToolParameterRejection)({
|
|
4827
|
+
toolCallId,
|
|
4828
|
+
parameters,
|
|
4829
|
+
error: encodedError,
|
|
4830
|
+
}).pipe(
|
|
4831
|
+
Effect.mapError(() =>
|
|
4832
|
+
ModelProtocolError.make({ message: "Invalid parameter rejection evidence" }),
|
|
4833
|
+
),
|
|
4834
|
+
);
|
|
4835
|
+
|
|
4836
|
+
trace.toolParameterRejections.set(part.id, rejection);
|
|
4837
|
+
} else {
|
|
4838
|
+
parameters = yield* encodeToolCallParameters<Tools>(tool, part.name, decoded.success).pipe(
|
|
4839
|
+
Effect.flatMap((encoded) => decodeEventJson(encoded, "Tool parameters")),
|
|
4840
|
+
);
|
|
4841
|
+
}
|
|
4727
4842
|
|
|
4728
4843
|
const canonicalCall = Response.makePart("tool-call", {
|
|
4729
4844
|
id: part.id,
|
|
@@ -5397,6 +5512,7 @@ const makeTurn = <
|
|
|
5397
5512
|
providerStagedPayloadBytes: 0,
|
|
5398
5513
|
turnCompletion: undefined,
|
|
5399
5514
|
applicationToolCalls: [],
|
|
5515
|
+
toolParameterRejections: new Map(),
|
|
5400
5516
|
applicationCallDescriptors: [],
|
|
5401
5517
|
applicationToolResults: [],
|
|
5402
5518
|
finished: false,
|
|
@@ -6081,7 +6197,7 @@ const makeTurn = <
|
|
|
6081
6197
|
// including the overflow retry — carries it at the last
|
|
6082
6198
|
// system block.
|
|
6083
6199
|
prompt: providerPrompt,
|
|
6084
|
-
toolkit: requestToolkit,
|
|
6200
|
+
toolkit: deferredToolParameterToolkit(requestToolkit),
|
|
6085
6201
|
disableToolCallResolution: true,
|
|
6086
6202
|
// Exact required Tool selection preserves the toolkit. A oneOf
|
|
6087
6203
|
// subset can drop other schemas and break the cached prefix.
|
|
@@ -6758,6 +6874,11 @@ const makeTurn = <
|
|
|
6758
6874
|
turnId,
|
|
6759
6875
|
responseMessages: promptFromTurnParts(trace),
|
|
6760
6876
|
calls: trace.applicationCallDescriptors,
|
|
6877
|
+
...(trace.toolParameterRejections.size === 0
|
|
6878
|
+
? {}
|
|
6879
|
+
: {
|
|
6880
|
+
toolParameterRejections: [...trace.toolParameterRejections.values()],
|
|
6881
|
+
}),
|
|
6761
6882
|
toolExposure: snapshot,
|
|
6762
6883
|
});
|
|
6763
6884
|
}
|
|
@@ -7148,6 +7269,7 @@ const makeResumeTurn = <
|
|
|
7148
7269
|
providerStagedPayloadBytes: 0,
|
|
7149
7270
|
turnCompletion: undefined,
|
|
7150
7271
|
applicationToolCalls: [],
|
|
7272
|
+
toolParameterRejections: new Map(),
|
|
7151
7273
|
applicationCallDescriptors: [],
|
|
7152
7274
|
applicationToolResults: [],
|
|
7153
7275
|
finished: true,
|
|
@@ -7160,6 +7282,49 @@ const makeResumeTurn = <
|
|
|
7160
7282
|
{ readonly index: number; readonly name: string; readonly providerExecuted: boolean }
|
|
7161
7283
|
>();
|
|
7162
7284
|
|
|
7285
|
+
const rejections = yield* Schema.decodeEffect(Schema.Array(ToolParameterRejection))(
|
|
7286
|
+
resume.toolParameterRejections ?? [],
|
|
7287
|
+
).pipe(
|
|
7288
|
+
Effect.mapError(() =>
|
|
7289
|
+
ModelProtocolError.make({ message: "Invalid parameter rejection evidence on resume" }),
|
|
7290
|
+
),
|
|
7291
|
+
);
|
|
7292
|
+
|
|
7293
|
+
const sameJson = Schema.toEquivalence(Schema.Json);
|
|
7294
|
+
|
|
7295
|
+
for (const rejection of rejections) {
|
|
7296
|
+
const call = resume.calls.find((call) => call.id === rejection.toolCallId);
|
|
7297
|
+
|
|
7298
|
+
if (
|
|
7299
|
+
call === undefined ||
|
|
7300
|
+
call.providerExecuted ||
|
|
7301
|
+
call.name !== rejection.error.reason.toolName ||
|
|
7302
|
+
!sameJson(yield* decodeEventJson(call.params, "Tool parameters"), rejection.parameters) ||
|
|
7303
|
+
trace.toolParameterRejections.has(call.id) ||
|
|
7304
|
+
tools[call.name]?.failureMode !== "return"
|
|
7305
|
+
) {
|
|
7306
|
+
return yield* ModelProtocolError.make({
|
|
7307
|
+
message: "Parameter rejection does not match recorded Tool Call on resume",
|
|
7308
|
+
});
|
|
7309
|
+
}
|
|
7310
|
+
|
|
7311
|
+
const validation = yield* Effect.result(
|
|
7312
|
+
decodeToolCallParameters<Tools>(
|
|
7313
|
+
tools[call.name] as ToolUnion<Tools>,
|
|
7314
|
+
call.name,
|
|
7315
|
+
call.params,
|
|
7316
|
+
"resume",
|
|
7317
|
+
),
|
|
7318
|
+
);
|
|
7319
|
+
|
|
7320
|
+
if (Result.isSuccess(validation)) {
|
|
7321
|
+
return yield* ModelProtocolError.make({
|
|
7322
|
+
message: "Recorded parameter rejection contains valid arguments on resume",
|
|
7323
|
+
});
|
|
7324
|
+
}
|
|
7325
|
+
trace.toolParameterRejections.set(call.id, rejection);
|
|
7326
|
+
}
|
|
7327
|
+
|
|
7163
7328
|
for (const call of resume.calls) {
|
|
7164
7329
|
if (!hasTool(tools, call.name)) {
|
|
7165
7330
|
return failRunEventStream(
|
|
@@ -7174,7 +7339,9 @@ const makeResumeTurn = <
|
|
|
7174
7339
|
const tool = tools[call.name] as ToolUnion<Tools>;
|
|
7175
7340
|
const toolCallId = yield* decodeToolCallId(call.id);
|
|
7176
7341
|
|
|
7177
|
-
|
|
7342
|
+
if (!trace.toolParameterRejections.has(call.id)) {
|
|
7343
|
+
yield* decodeToolCallParameters<Tools>(tool, call.name, call.params, "resume");
|
|
7344
|
+
}
|
|
7178
7345
|
const parameters = yield* decodeEventJson(call.params, "Tool parameters");
|
|
7179
7346
|
const providerExecuted = call.providerExecuted === true;
|
|
7180
7347
|
|
|
@@ -7267,6 +7434,26 @@ const makeResumeTurn = <
|
|
|
7267
7434
|
providerCallIds,
|
|
7268
7435
|
);
|
|
7269
7436
|
|
|
7437
|
+
const rejection = trace.toolParameterRejections.get(settledCall.id);
|
|
7438
|
+
|
|
7439
|
+
if (
|
|
7440
|
+
rejection !== undefined &&
|
|
7441
|
+
(!settledCall.isFailure ||
|
|
7442
|
+
settledCall.toolSelection !== undefined ||
|
|
7443
|
+
(settledCall.budgetRejected !== true &&
|
|
7444
|
+
!sameJson(
|
|
7445
|
+
settledCall.result,
|
|
7446
|
+
yield* decodeEventJson(
|
|
7447
|
+
boundEncodedToolResult(rejection.error, agent.definition.policy.toolResultBounds),
|
|
7448
|
+
"Rejected Tool result",
|
|
7449
|
+
),
|
|
7450
|
+
)))
|
|
7451
|
+
) {
|
|
7452
|
+
return yield* ModelProtocolError.make({
|
|
7453
|
+
message: "Settled result contradicts parameter rejection on resume",
|
|
7454
|
+
});
|
|
7455
|
+
}
|
|
7456
|
+
|
|
7270
7457
|
const declared = declarationByCallId.get(settledCall.id);
|
|
7271
7458
|
|
|
7272
7459
|
if (declared === undefined) {
|