@ai-sdk/workflow 2.0.20 → 2.0.21

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/index.js CHANGED
@@ -4,7 +4,6 @@ import "./chunk-UAWBPTDW.js";
4
4
  import {
5
5
  getErrorMessage,
6
6
  isAbortError as isAbortError2,
7
- validateTypes,
8
7
  withUserAgentSuffix
9
8
  } from "@ai-sdk/provider-utils";
10
9
  import {
@@ -73,8 +72,28 @@ async function createLanguageModelToolResultOutput({
73
72
  });
74
73
  }
75
74
 
75
+ // src/resolve-tool-context.ts
76
+ import { validateTypes } from "@ai-sdk/provider-utils";
77
+ async function resolveToolContext({
78
+ toolName,
79
+ tool: tool2,
80
+ toolsContext
81
+ }) {
82
+ const contextSchema = tool2.contextSchema;
83
+ const entry = toolsContext == null ? void 0 : toolsContext[toolName];
84
+ if (contextSchema == null) {
85
+ return entry;
86
+ }
87
+ return await validateTypes({
88
+ value: entry,
89
+ schema: contextSchema,
90
+ context: { field: "tool context", entityName: toolName }
91
+ });
92
+ }
93
+
76
94
  // src/stream-text-iterator.ts
77
95
  import {
96
+ DefaultGeneratedFile,
78
97
  experimental_filterActiveTools as filterActiveTools
79
98
  } from "ai";
80
99
  import { createRestrictedTelemetryDispatcher } from "ai/internal";
@@ -92,7 +111,7 @@ import {
92
111
  asSchema,
93
112
  jsonSchema
94
113
  } from "@ai-sdk/provider-utils";
95
- import { tool } from "ai";
114
+ import { dynamicTool, tool } from "ai";
96
115
  import Ajv from "ajv";
97
116
  function serializeToolSet(tools, {
98
117
  toolsContext = {},
@@ -102,6 +121,8 @@ function serializeToolSet(tools, {
102
121
  Object.entries(tools).map(([name, t]) => {
103
122
  var _a;
104
123
  const def = {
124
+ title: t.title,
125
+ metadata: t.metadata,
105
126
  description: resolveToolDescription({
106
127
  tool: t,
107
128
  toolName: name,
@@ -109,12 +130,26 @@ function serializeToolSet(tools, {
109
130
  experimental_sandbox: sandbox
110
131
  }),
111
132
  inputSchema: asSchema(t.inputSchema).jsonSchema,
133
+ strict: t.strict,
112
134
  inputExamples: t.inputExamples,
113
135
  providerOptions: t.providerOptions
114
136
  };
137
+ if (t.type === "dynamic") {
138
+ def.type = "dynamic";
139
+ }
140
+ if (t.onInputStart != null) {
141
+ def.hasOnInputStart = true;
142
+ }
143
+ if (t.onInputDelta != null) {
144
+ def.hasOnInputDelta = true;
145
+ }
146
+ if (t.onInputAvailable != null) {
147
+ def.hasOnInputAvailable = true;
148
+ }
115
149
  if (t.type === "provider") {
116
150
  def.type = "provider";
117
151
  def.isProviderExecuted = (_a = t.isProviderExecuted) != null ? _a : false;
152
+ def.supportsDeferredResults = t.supportsDeferredResults;
118
153
  def.id = t.id;
119
154
  def.args = t.args;
120
155
  }
@@ -137,39 +172,74 @@ function resolveSerializableTools(tools) {
137
172
  const ajv = new Ajv();
138
173
  return Object.fromEntries(
139
174
  Object.entries(tools).map(([name, t]) => {
140
- var _a, _b;
175
+ var _a;
141
176
  if (t.type === "provider") {
177
+ const providerTool = {
178
+ type: "provider",
179
+ title: t.title,
180
+ metadata: t.metadata,
181
+ id: t.id,
182
+ args: (_a = t.args) != null ? _a : {},
183
+ inputSchema: jsonSchema(t.inputSchema),
184
+ providerOptions: t.providerOptions
185
+ };
142
186
  return [
143
187
  name,
144
- tool({
145
- type: "provider",
146
- id: t.id,
147
- args: (_a = t.args) != null ? _a : {},
148
- isProviderExecuted: (_b = t.isProviderExecuted) != null ? _b : false,
149
- inputSchema: jsonSchema(t.inputSchema),
150
- providerOptions: t.providerOptions
188
+ t.isProviderExecuted ? tool({
189
+ ...providerTool,
190
+ isProviderExecuted: true,
191
+ supportsDeferredResults: t.supportsDeferredResults
192
+ }) : tool({
193
+ ...providerTool,
194
+ isProviderExecuted: false
151
195
  })
152
196
  ];
153
197
  }
154
- const validateFn = ajv.compile(t.inputSchema);
155
- return [
156
- name,
157
- tool({
158
- description: t.description,
159
- inputExamples: t.inputExamples,
160
- providerOptions: t.providerOptions,
161
- inputSchema: jsonSchema(t.inputSchema, {
162
- validate: (value) => {
163
- if (validateFn(value)) {
164
- return { success: true, value };
198
+ if (t.type === "dynamic") {
199
+ const validateFn2 = ajv.compile(t.inputSchema);
200
+ return [
201
+ name,
202
+ dynamicTool({
203
+ description: t.description,
204
+ inputExamples: t.inputExamples,
205
+ providerOptions: t.providerOptions,
206
+ inputSchema: jsonSchema(t.inputSchema, {
207
+ validate: (value) => {
208
+ if (validateFn2(value)) {
209
+ return { success: true, value };
210
+ }
211
+ return {
212
+ success: false,
213
+ error: new Error(ajv.errorsText(validateFn2.errors))
214
+ };
165
215
  }
166
- return {
167
- success: false,
168
- error: new Error(ajv.errorsText(validateFn.errors))
169
- };
170
- }
216
+ })
171
217
  })
218
+ ];
219
+ }
220
+ const validateFn = ajv.compile(t.inputSchema);
221
+ const functionTool = {
222
+ title: t.title,
223
+ metadata: t.metadata,
224
+ description: t.description,
225
+ strict: t.strict,
226
+ inputExamples: t.inputExamples,
227
+ providerOptions: t.providerOptions,
228
+ inputSchema: jsonSchema(t.inputSchema, {
229
+ validate: (value) => {
230
+ if (validateFn(value)) {
231
+ return { success: true, value };
232
+ }
233
+ return {
234
+ success: false,
235
+ error: new Error(ajv.errorsText(validateFn.errors))
236
+ };
237
+ }
172
238
  })
239
+ };
240
+ return [
241
+ name,
242
+ t.type === "dynamic" ? tool({ ...functionTool, type: "dynamic" }) : tool(functionTool)
173
243
  ];
174
244
  })
175
245
  );
@@ -178,13 +248,14 @@ function resolveSerializableTools(tools) {
178
248
  // src/do-stream-step.ts
179
249
  async function doStreamStep(conversationPrompt, modelInit, writable, serializedTools, options) {
180
250
  "use step";
181
- var _a;
251
+ var _a, _b, _c, _d, _e, _f;
182
252
  const timeout = (options == null ? void 0 : options.timeoutAt) == null ? void 0 : options.timeoutAt - Date.now();
183
253
  if (((_a = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a.aborted) || timeout != null && timeout <= 0) {
184
254
  return { aborted: true };
185
255
  }
186
256
  const abortSignal = timeout == null ? options == null ? void 0 : options.abortSignal : (options == null ? void 0 : options.abortSignal) == null ? AbortSignal.timeout(timeout) : AbortSignal.any([options.abortSignal, AbortSignal.timeout(timeout)]);
187
257
  const model = typeof modelInit === "string" ? gateway.languageModel(modelInit) : modelInit;
258
+ const toolInputLifecycleEvents = [];
188
259
  const tools = serializedTools ? resolveSerializableTools(serializedTools) : void 0;
189
260
  const output = (options == null ? void 0 : options.responseFormat) == null ? void 0 : {
190
261
  name: "workflow",
@@ -248,25 +319,85 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
248
319
  const toolCalls = [];
249
320
  const providerExecutedToolResults = /* @__PURE__ */ new Map();
250
321
  let finish;
251
- let text = "";
322
+ const content = [];
323
+ const textPartIndexes = /* @__PURE__ */ new Map();
252
324
  const reasoningParts = [];
253
325
  let responseMetadata;
254
326
  let warnings;
255
327
  let terminalError;
256
328
  let hasTerminalError = false;
329
+ const ongoingToolCallToolNames = /* @__PURE__ */ new Map();
257
330
  const writer = writable == null ? void 0 : writable.getWriter();
258
331
  try {
259
332
  await (writer == null ? void 0 : writer.write({ type: "reset-step" }));
260
333
  for await (const part of modelStream) {
261
334
  switch (part.type) {
335
+ case "tool-input-start":
336
+ ongoingToolCallToolNames.set(part.id, part.toolName);
337
+ if (((_b = serializedTools == null ? void 0 : serializedTools[part.toolName]) == null ? void 0 : _b.hasOnInputStart) || ((_c = serializedTools == null ? void 0 : serializedTools[part.toolName]) == null ? void 0 : _c.hasOnInputDelta) || ((_d = serializedTools == null ? void 0 : serializedTools[part.toolName]) == null ? void 0 : _d.hasOnInputAvailable)) {
338
+ toolInputLifecycleEvents.push(["start", part.id, part.toolName]);
339
+ }
340
+ break;
341
+ case "tool-input-delta": {
342
+ const toolName = ongoingToolCallToolNames.get(part.id);
343
+ if (toolName != null && ((_e = serializedTools == null ? void 0 : serializedTools[toolName]) == null ? void 0 : _e.hasOnInputDelta)) {
344
+ toolInputLifecycleEvents.push(["delta", part.id, part.delta]);
345
+ }
346
+ break;
347
+ }
348
+ case "text-start":
349
+ upsertTextContentPart({
350
+ content,
351
+ textPartIndexes,
352
+ id: part.id,
353
+ providerMetadata: part.providerMetadata
354
+ });
355
+ break;
262
356
  case "text-delta":
263
- text += part.text;
357
+ upsertTextContentPart({
358
+ content,
359
+ textPartIndexes,
360
+ id: part.id,
361
+ textDelta: part.text,
362
+ providerMetadata: part.providerMetadata
363
+ });
364
+ break;
365
+ case "text-end":
366
+ upsertTextContentPart({
367
+ content,
368
+ textPartIndexes,
369
+ id: part.id,
370
+ providerMetadata: part.providerMetadata
371
+ });
372
+ textPartIndexes.delete(part.id);
264
373
  break;
265
374
  case "reasoning-delta":
266
375
  reasoningParts.push({ text: part.text });
267
376
  break;
377
+ case "file":
378
+ content.push({
379
+ type: "file",
380
+ data: part.file.base64,
381
+ mediaType: part.file.mediaType,
382
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
383
+ });
384
+ break;
385
+ case "source":
386
+ content.push(part);
387
+ break;
268
388
  case "tool-call": {
269
389
  const toolCallPart = part;
390
+ const toolCallIndex = toolCalls.length;
391
+ const lifecycleToolName = ongoingToolCallToolNames.get(
392
+ toolCallPart.toolCallId
393
+ );
394
+ ongoingToolCallToolNames.delete(toolCallPart.toolCallId);
395
+ if (lifecycleToolName != null && ((_f = serializedTools == null ? void 0 : serializedTools[lifecycleToolName]) == null ? void 0 : _f.hasOnInputAvailable)) {
396
+ toolInputLifecycleEvents.push([
397
+ "available",
398
+ toolCallPart.toolCallId
399
+ ]);
400
+ }
270
401
  toolCalls.push({
271
402
  type: "tool-call",
272
403
  toolCallId: toolCallPart.toolCallId,
@@ -274,10 +405,13 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
274
405
  input: toolCallPart.input,
275
406
  providerExecuted: toolCallPart.providerExecuted,
276
407
  providerMetadata: toolCallPart.providerMetadata,
408
+ title: toolCallPart.title,
409
+ toolMetadata: toolCallPart.toolMetadata,
277
410
  dynamic: toolCallPart.dynamic,
278
411
  invalid: toolCallPart.invalid,
279
412
  error: toolCallPart.error
280
413
  });
414
+ content.push({ type: "tool-call", toolCallIndex });
281
415
  break;
282
416
  }
283
417
  case "tool-result":
@@ -349,16 +483,44 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
349
483
  toolCalls,
350
484
  finish,
351
485
  raw: {
352
- text,
486
+ content,
353
487
  reasoning: reasoningParts,
354
488
  responseMetadata,
355
489
  warnings
356
490
  },
357
491
  providerExecutedToolResults,
492
+ toolInputLifecycleEvents,
358
493
  ...hasTerminalError ? { terminalError } : {}
359
494
  };
360
495
  }
361
496
  doStreamStep.maxRetries = 0;
497
+ function upsertTextContentPart({
498
+ content,
499
+ textPartIndexes,
500
+ id,
501
+ textDelta,
502
+ providerMetadata
503
+ }) {
504
+ let partIndex = textPartIndexes.get(id);
505
+ if (partIndex == null) {
506
+ partIndex = content.push({
507
+ type: "text",
508
+ text: "",
509
+ ...providerMetadata != null ? { providerMetadata } : {}
510
+ }) - 1;
511
+ textPartIndexes.set(id, partIndex);
512
+ }
513
+ const part = content[partIndex];
514
+ if (part.type !== "text") {
515
+ throw new Error(`Expected text content at index ${partIndex}.`);
516
+ }
517
+ if (textDelta != null) {
518
+ part.text += textDelta;
519
+ }
520
+ if (providerMetadata != null) {
521
+ part.providerMetadata = providerMetadata;
522
+ }
523
+ }
362
524
 
363
525
  // src/stream-text-iterator.ts
364
526
  var prepareStepGenerationSettingKeys = [
@@ -540,6 +702,7 @@ async function* streamTextIterator({
540
702
  providerOptions: currentGenerationSettings.providerOptions,
541
703
  headers: currentGenerationSettings.headers
542
704
  }));
705
+ const stepInputMessages = conversationPrompt;
543
706
  const streamStepResult = await doStreamStep(
544
707
  conversationPrompt,
545
708
  currentModel,
@@ -562,7 +725,22 @@ async function* streamTextIterator({
562
725
  terminalError = streamStepResult.terminalError;
563
726
  hasTerminalError = true;
564
727
  }
565
- const { toolCalls, finish, raw, providerExecutedToolResults } = streamStepResult;
728
+ const {
729
+ toolCalls,
730
+ finish,
731
+ raw,
732
+ providerExecutedToolResults,
733
+ toolInputLifecycleEvents
734
+ } = streamStepResult;
735
+ await invokeToolInputLifecycleCallbacks({
736
+ events: toolInputLifecycleEvents != null ? toolInputLifecycleEvents : [],
737
+ toolCalls,
738
+ tools: effectiveTools,
739
+ messages: stepInputMessages,
740
+ abortSignal: currentGenerationSettings.abortSignal,
741
+ toolsContext: currentToolsContext,
742
+ experimental_sandbox: stepSandbox
743
+ });
566
744
  const step = buildStepResult(raw, toolCalls, finish, {
567
745
  stepNumber,
568
746
  runtimeContext: currentRuntimeContext,
@@ -588,27 +766,17 @@ async function* streamTextIterator({
588
766
  done = true;
589
767
  } else if (finishReason === "tool-calls") {
590
768
  lastStepWasToolCalls = true;
591
- const textContent = step.content.filter(
592
- (item) => item.type === "text"
769
+ const assistantContent = getAssistantMessageContent(step);
770
+ const includedToolCallIds = new Set(
771
+ assistantContent.flatMap(
772
+ (part) => part.type === "tool-call" ? [part.toolCallId] : []
773
+ )
593
774
  );
594
775
  conversationPrompt.push({
595
776
  role: "assistant",
596
777
  content: [
597
- ...textContent,
598
- ...toolCalls.map((toolCall) => {
599
- const sanitizedMetadata = sanitizeProviderMetadataForToolCall(
600
- toolCall.providerMetadata
601
- );
602
- return {
603
- type: "tool-call",
604
- toolCallId: toolCall.toolCallId,
605
- toolName: toolCall.toolName,
606
- input: toolCall.input,
607
- ...sanitizedMetadata != null ? {
608
- providerOptions: sanitizedMetadata
609
- } : {}
610
- };
611
- })
778
+ ...assistantContent,
779
+ ...toolCalls.filter((toolCall) => !includedToolCallIds.has(toolCall.toolCallId)).map(toAssistantToolCallContent)
612
780
  ]
613
781
  });
614
782
  const toolResults = yield {
@@ -631,13 +799,11 @@ async function* streamTextIterator({
631
799
  }
632
800
  }
633
801
  } else if (finishReason === "stop") {
634
- const textContent = step.content.filter(
635
- (item) => item.type === "text"
636
- );
637
- if (textContent.length > 0) {
802
+ const assistantContent = getAssistantMessageContent(step);
803
+ if (assistantContent.length > 0) {
638
804
  conversationPrompt.push({
639
805
  role: "assistant",
640
- content: textContent
806
+ content: assistantContent
641
807
  });
642
808
  }
643
809
  done = true;
@@ -688,6 +854,74 @@ async function* streamTextIterator({
688
854
  }
689
855
  return conversationPrompt;
690
856
  }
857
+ async function invokeToolInputLifecycleCallbacks({
858
+ events,
859
+ toolCalls,
860
+ tools,
861
+ messages,
862
+ abortSignal,
863
+ toolsContext,
864
+ experimental_sandbox
865
+ }) {
866
+ var _a, _b, _c;
867
+ const toolNamesByCallId = /* @__PURE__ */ new Map();
868
+ const toolCallsById = new Map(
869
+ toolCalls.map((toolCall) => [toolCall.toolCallId, toolCall])
870
+ );
871
+ const resolvedContexts = /* @__PURE__ */ new Map();
872
+ for (const event of events) {
873
+ const [type, toolCallId, value] = event;
874
+ if (type === "start") {
875
+ toolNamesByCallId.set(toolCallId, value);
876
+ }
877
+ const toolName = type === "start" ? value : toolNamesByCallId.get(toolCallId);
878
+ if (toolName == null) {
879
+ continue;
880
+ }
881
+ const tool2 = tools[toolName];
882
+ if (tool2 == null) {
883
+ continue;
884
+ }
885
+ let resolvedContext = resolvedContexts.get(toolName);
886
+ if (resolvedContext == null) {
887
+ resolvedContext = resolveToolContext({
888
+ toolName,
889
+ tool: tool2,
890
+ toolsContext
891
+ });
892
+ resolvedContexts.set(toolName, resolvedContext);
893
+ }
894
+ const options = {
895
+ toolCallId,
896
+ messages,
897
+ abortSignal,
898
+ context: await resolvedContext,
899
+ experimental_sandbox
900
+ };
901
+ switch (type) {
902
+ case "start":
903
+ await ((_a = tool2.onInputStart) == null ? void 0 : _a.call(tool2, options));
904
+ break;
905
+ case "delta":
906
+ await ((_b = tool2.onInputDelta) == null ? void 0 : _b.call(tool2, {
907
+ ...options,
908
+ inputTextDelta: value
909
+ }));
910
+ break;
911
+ case "available": {
912
+ const toolCall = toolCallsById.get(toolCallId);
913
+ if (toolCall == null) {
914
+ break;
915
+ }
916
+ await ((_c = tool2.onInputAvailable) == null ? void 0 : _c.call(tool2, {
917
+ ...options,
918
+ input: toolCall.input
919
+ }));
920
+ break;
921
+ }
922
+ }
923
+ }
924
+ }
691
925
  function getModelInfo(model) {
692
926
  var _a;
693
927
  return typeof model === "string" ? { provider: (_a = model.split("/")[0]) != null ? _a : "gateway", modelId: model } : { provider: model.provider, modelId: model.modelId };
@@ -701,15 +935,76 @@ function normalizeStepForTelemetry(step) {
701
935
  }
702
936
  function buildStepResult(raw, toolCalls, finish, opts) {
703
937
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
704
- const { text, reasoning: reasoningParts, responseMetadata, warnings } = raw;
938
+ const {
939
+ content: rawContent,
940
+ reasoning: reasoningParts,
941
+ responseMetadata,
942
+ warnings
943
+ } = raw;
705
944
  const reasoningText = reasoningParts.map((r) => r.text).join("") || void 0;
706
- const validToolCalls = toolCalls.filter((tc) => !tc.invalid).map((tc) => ({
707
- type: "tool-call",
708
- toolCallId: tc.toolCallId,
709
- toolName: tc.toolName,
710
- input: tc.input,
711
- ...tc.dynamic ? { dynamic: true } : {}
712
- }));
945
+ const validToolCallsByIndex = new Map(
946
+ toolCalls.flatMap(
947
+ (tc, index) => tc.invalid ? [] : [
948
+ [
949
+ index,
950
+ {
951
+ type: "tool-call",
952
+ toolCallId: tc.toolCallId,
953
+ toolName: tc.toolName,
954
+ input: tc.input,
955
+ ...tc.providerExecuted != null ? { providerExecuted: tc.providerExecuted } : {},
956
+ ...tc.title != null ? { title: tc.title } : {},
957
+ ...tc.toolMetadata != null ? { toolMetadata: tc.toolMetadata } : {},
958
+ ...tc.dynamic ? { dynamic: true } : {},
959
+ ...tc.providerExecuted ? { providerExecuted: true } : {},
960
+ ...tc.providerMetadata != null ? { providerMetadata: tc.providerMetadata } : {}
961
+ }
962
+ ]
963
+ ]
964
+ )
965
+ );
966
+ const validToolCalls = [...validToolCallsByIndex.values()];
967
+ const content = [];
968
+ const files = [];
969
+ const sources = [];
970
+ let text = "";
971
+ for (const part of rawContent) {
972
+ switch (part.type) {
973
+ case "text":
974
+ text += part.text;
975
+ content.push({
976
+ type: "text",
977
+ text: part.text,
978
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
979
+ });
980
+ break;
981
+ case "file": {
982
+ const file = new DefaultGeneratedFile({
983
+ data: part.data,
984
+ mediaType: part.mediaType,
985
+ providerMetadata: part.providerMetadata
986
+ });
987
+ files.push(file);
988
+ content.push({
989
+ type: "file",
990
+ file,
991
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
992
+ });
993
+ break;
994
+ }
995
+ case "source":
996
+ sources.push(part);
997
+ content.push(part);
998
+ break;
999
+ case "tool-call": {
1000
+ const toolCall = validToolCallsByIndex.get(part.toolCallIndex);
1001
+ if (toolCall != null) {
1002
+ content.push(toolCall);
1003
+ }
1004
+ break;
1005
+ }
1006
+ }
1007
+ }
713
1008
  return {
714
1009
  callId: "workflow-agent",
715
1010
  stepNumber: opts.stepNumber,
@@ -721,20 +1016,17 @@ function buildStepResult(raw, toolCalls, finish, opts) {
721
1016
  metadata: void 0,
722
1017
  runtimeContext: (_d = opts.runtimeContext) != null ? _d : {},
723
1018
  toolsContext: (_e = opts.toolsContext) != null ? _e : {},
724
- content: [
725
- ...text ? [{ type: "text", text }] : [],
726
- ...validToolCalls
727
- ],
1019
+ content,
728
1020
  text,
729
1021
  reasoning: reasoningParts.map((r) => ({
730
1022
  type: "reasoning",
731
1023
  text: r.text
732
1024
  })),
733
1025
  reasoningText,
734
- files: [],
735
- sources: [],
1026
+ files,
1027
+ sources,
736
1028
  toolCalls: validToolCalls,
737
- staticToolCalls: [],
1029
+ staticToolCalls: validToolCalls.filter((tc) => tc.dynamic !== true),
738
1030
  dynamicToolCalls: validToolCalls.filter((tc) => tc.dynamic),
739
1031
  toolResults: [],
740
1032
  staticToolResults: [],
@@ -780,6 +1072,47 @@ function buildStepResult(raw, toolCalls, finish, opts) {
780
1072
  providerMetadata: (_k = finish == null ? void 0 : finish.providerMetadata) != null ? _k : {}
781
1073
  };
782
1074
  }
1075
+ function getAssistantMessageContent(step) {
1076
+ const content = [];
1077
+ for (const part of step.content) {
1078
+ switch (part.type) {
1079
+ case "text":
1080
+ if (part.text.length > 0) {
1081
+ content.push({ type: "text", text: part.text });
1082
+ }
1083
+ break;
1084
+ case "file":
1085
+ content.push({
1086
+ type: "file",
1087
+ data: { type: "data", data: part.file.base64 },
1088
+ mediaType: part.file.mediaType,
1089
+ ...part.providerMetadata != null ? {
1090
+ providerOptions: part.providerMetadata
1091
+ } : {}
1092
+ });
1093
+ break;
1094
+ case "tool-call":
1095
+ content.push(toAssistantToolCallContent(part));
1096
+ break;
1097
+ }
1098
+ }
1099
+ return content;
1100
+ }
1101
+ function toAssistantToolCallContent(toolCall) {
1102
+ const sanitizedMetadata = sanitizeProviderMetadataForToolCall(
1103
+ toolCall.providerMetadata
1104
+ );
1105
+ return {
1106
+ type: "tool-call",
1107
+ toolCallId: toolCall.toolCallId,
1108
+ toolName: toolCall.toolName,
1109
+ input: toolCall.input,
1110
+ ...toolCall.providerExecuted != null ? { providerExecuted: toolCall.providerExecuted } : {},
1111
+ ...sanitizedMetadata != null ? {
1112
+ providerOptions: sanitizedMetadata
1113
+ } : {}
1114
+ };
1115
+ }
783
1116
  function sanitizeProviderMetadataForToolCall(metadata) {
784
1117
  if (metadata == null) return void 0;
785
1118
  const meta = metadata;
@@ -802,6 +1135,45 @@ function sanitizeProviderMetadataForToolCall(metadata) {
802
1135
  }
803
1136
 
804
1137
  // src/workflow-agent.ts
1138
+ function addToolResultsToStep(step, executedResults) {
1139
+ if (step == null || executedResults.length === 0) {
1140
+ return;
1141
+ }
1142
+ const toolOutputs = executedResults.map((result) => {
1143
+ const toolCall = step.toolCalls.find(
1144
+ (toolCall2) => toolCall2.toolCallId === result.modelResult.toolCallId
1145
+ );
1146
+ const common = {
1147
+ toolCallId: result.modelResult.toolCallId,
1148
+ toolName: result.modelResult.toolName,
1149
+ input: toolCall == null ? void 0 : toolCall.input,
1150
+ ...(toolCall == null ? void 0 : toolCall.dynamic) === true ? { dynamic: true } : {},
1151
+ ...(toolCall == null ? void 0 : toolCall.providerExecuted) === true ? { providerExecuted: true } : {}
1152
+ };
1153
+ return result.isError ? {
1154
+ type: "tool-error",
1155
+ ...common,
1156
+ error: result.rawOutput
1157
+ } : {
1158
+ type: "tool-result",
1159
+ ...common,
1160
+ output: result.rawOutput
1161
+ };
1162
+ });
1163
+ step.content.push(...toolOutputs);
1164
+ const toolResults = toolOutputs.filter(
1165
+ (result) => result.type === "tool-result"
1166
+ );
1167
+ step.toolResults.push(
1168
+ ...toolResults
1169
+ );
1170
+ step.staticToolResults.push(
1171
+ ...toolResults.filter((result) => result.dynamic !== true)
1172
+ );
1173
+ step.dynamicToolResults.push(
1174
+ ...toolResults.filter((result) => result.dynamic === true)
1175
+ );
1176
+ }
805
1177
  var WorkflowAgent = class {
806
1178
  constructor(options) {
807
1179
  var _a, _b, _c, _d, _e, _f, _g;
@@ -1507,26 +1879,32 @@ var WorkflowAgent = class {
1507
1879
  )
1508
1880
  )
1509
1881
  );
1510
- const providerResults = await Promise.all(
1511
- providerToolCalls.map(
1512
- (toolCall) => resolveProviderToolResult(
1882
+ const providerResultEntries = await Promise.all(
1883
+ providerToolCalls.map(async (toolCall) => ({
1884
+ toolCall,
1885
+ result: await resolveProviderToolResult(
1513
1886
  toolCall,
1514
1887
  providerExecutedToolResults,
1515
1888
  effectiveTools,
1516
1889
  download
1517
1890
  )
1518
- )
1891
+ }))
1519
1892
  );
1520
1893
  await Promise.all(
1521
- providerToolCalls.map(
1522
- (toolCall, index) => recordProviderExecutedToolTelemetry(
1523
- toolCall,
1524
- providerResults[index],
1525
- iterMessages,
1526
- currentStepNumber
1527
- )
1894
+ providerResultEntries.flatMap(
1895
+ ({ toolCall, result: result2 }) => result2 == null ? [] : [
1896
+ recordProviderExecutedToolTelemetry(
1897
+ toolCall,
1898
+ result2,
1899
+ iterMessages,
1900
+ currentStepNumber
1901
+ )
1902
+ ]
1528
1903
  )
1529
1904
  );
1905
+ const providerResults = providerResultEntries.flatMap(
1906
+ ({ result: result2 }) => result2 == null ? [] : [result2]
1907
+ );
1530
1908
  const continuationInvalidResults = invalidToolCalls.map(
1531
1909
  createInvalidToolResult
1532
1910
  );
@@ -1554,6 +1932,7 @@ var WorkflowAgent = class {
1554
1932
  output: r.rawOutput
1555
1933
  };
1556
1934
  });
1935
+ addToolResultsToStep(step, executedResults);
1557
1936
  if (resolvedResults.length > 0) {
1558
1937
  iterMessages.push({
1559
1938
  role: "tool",
@@ -1661,26 +2040,32 @@ var WorkflowAgent = class {
1661
2040
  )
1662
2041
  )
1663
2042
  );
1664
- const providerToolResults = await Promise.all(
1665
- providerToolCalls.map(
1666
- (toolCall) => resolveProviderToolResult(
2043
+ const providerToolResultEntries = await Promise.all(
2044
+ providerToolCalls.map(async (toolCall) => ({
2045
+ toolCall,
2046
+ result: await resolveProviderToolResult(
1667
2047
  toolCall,
1668
2048
  providerExecutedToolResults,
1669
2049
  effectiveTools,
1670
2050
  download
1671
2051
  )
1672
- )
2052
+ }))
1673
2053
  );
1674
2054
  await Promise.all(
1675
- providerToolCalls.map(
1676
- (toolCall, index) => recordProviderExecutedToolTelemetry(
1677
- toolCall,
1678
- providerToolResults[index],
1679
- iterMessages,
1680
- currentStepNumber
1681
- )
2055
+ providerToolResultEntries.flatMap(
2056
+ ({ toolCall, result: result2 }) => result2 == null ? [] : [
2057
+ recordProviderExecutedToolTelemetry(
2058
+ toolCall,
2059
+ result2,
2060
+ iterMessages,
2061
+ currentStepNumber
2062
+ )
2063
+ ]
1682
2064
  )
1683
2065
  );
2066
+ const providerToolResults = providerToolResultEntries.flatMap(
2067
+ ({ result: result2 }) => result2 == null ? [] : [result2]
2068
+ );
1684
2069
  const continuationInvalidToolResults = invalidToolCalls.map(
1685
2070
  createInvalidToolResult
1686
2071
  );
@@ -1742,6 +2127,7 @@ var WorkflowAgent = class {
1742
2127
  output: r.rawOutput
1743
2128
  };
1744
2129
  });
2130
+ addToolResultsToStep(step, executedToolResults);
1745
2131
  result = await iterator.next(continuationToolResults);
1746
2132
  } else {
1747
2133
  lastStepToolCalls = [];
@@ -2036,22 +2422,6 @@ async function writeApprovalToolResults(writable, approvedResults, deniedResults
2036
2422
  writer.releaseLock();
2037
2423
  }
2038
2424
  }
2039
- async function resolveToolContext({
2040
- toolName,
2041
- tool: tool2,
2042
- toolsContext
2043
- }) {
2044
- const contextSchema = tool2.contextSchema;
2045
- const entry = toolsContext == null ? void 0 : toolsContext[toolName];
2046
- if (contextSchema == null) {
2047
- return entry;
2048
- }
2049
- return await validateTypes({
2050
- value: entry,
2051
- schema: contextSchema,
2052
- context: { field: "tool context", entityName: toolName }
2053
- });
2054
- }
2055
2425
  function aggregateUsage(steps) {
2056
2426
  var _a, _b, _c, _d;
2057
2427
  let inputTokens = 0;
@@ -2069,6 +2439,10 @@ function aggregateUsage(steps) {
2069
2439
  async function resolveProviderToolResult(toolCall, providerExecutedToolResults, tools, download) {
2070
2440
  const streamResult = providerExecutedToolResults == null ? void 0 : providerExecutedToolResults.get(toolCall.toolCallId);
2071
2441
  if (!streamResult) {
2442
+ const tool2 = tools == null ? void 0 : tools[toolCall.toolName];
2443
+ if ((tool2 == null ? void 0 : tool2.type) === "provider" && tool2.isProviderExecuted && tool2.supportsDeferredResults) {
2444
+ return void 0;
2445
+ }
2072
2446
  console.warn(
2073
2447
  `[WorkflowAgent] Provider-executed tool "${toolCall.toolName}" (${toolCall.toolCallId}) did not receive a result from the stream. This may indicate a provider issue.`
2074
2448
  );