@ai-sdk/workflow 1.0.67 → 1.0.68

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @ai-sdk/workflow
2
2
 
3
+ ## 1.0.68
4
+
5
+ ### Patch Changes
6
+
7
+ - e6064c5: Honor `WorkflowAgent` model-call retry settings without stacking workflow step retries.
8
+ - 83f9b12: Expose the original value from model stream error parts on resolved WorkflowAgent results without retrying the durable model step.
9
+ - ai@7.0.67
10
+
3
11
  ## 1.0.67
4
12
 
5
13
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -137,8 +137,7 @@ interface GenerationSettings {
137
137
  */
138
138
  seed?: number;
139
139
  /**
140
- * Maximum number of retries. Set to 0 to disable retries.
141
- * Note: In workflow context, retries are typically handled by the workflow step mechanism.
140
+ * Maximum number of retries for retryable model call failures. Set to 0 to disable retries.
142
141
  * @default 2
143
142
  */
144
143
  maxRetries?: number;
@@ -911,6 +910,14 @@ interface WorkflowAgentStreamResult<TTools extends ToolSet = ToolSet, OUTPUT = n
911
910
  * The finish reason from the last step.
912
911
  */
913
912
  finishReason: FinishReason;
913
+ /**
914
+ * The original value from a model stream error part.
915
+ *
916
+ * This property is present when the model emitted an error part, including
917
+ * when the supplied value is `undefined`. Check with `'error' in result` to
918
+ * distinguish that case from a result without a model stream error.
919
+ */
920
+ error?: unknown;
914
921
  /**
915
922
  * The total token usage across all steps.
916
923
  */
package/dist/index.js CHANGED
@@ -79,6 +79,7 @@ import {
79
79
  experimental_streamLanguageModelCall as streamModelCall,
80
80
  gateway
81
81
  } from "ai";
82
+ import { prepareRetries } from "ai/internal";
82
83
 
83
84
  // src/serializable-schema.ts
84
85
  import {
@@ -189,36 +190,47 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
189
190
  return void 0;
190
191
  }
191
192
  };
192
- const modelStream = await streamModelCall({
193
- model,
194
- // streamModelCall expects Prompt (ModelMessage[]) but we pass the
195
- // pre-converted LanguageModelV4Prompt. standardizePrompt inside
196
- // streamModelCall handles both formats.
197
- messages: conversationPrompt,
198
- allowSystemInMessages: true,
199
- tools,
200
- toolChoice: options == null ? void 0 : options.toolChoice,
201
- includeRawChunks: options == null ? void 0 : options.includeRawChunks,
202
- providerOptions: options == null ? void 0 : options.providerOptions,
203
- abortSignal,
204
- headers: options == null ? void 0 : options.headers,
205
- reasoning: options == null ? void 0 : options.reasoning,
206
- output,
207
- maxOutputTokens: options == null ? void 0 : options.maxOutputTokens,
208
- temperature: options == null ? void 0 : options.temperature,
209
- topP: options == null ? void 0 : options.topP,
210
- topK: options == null ? void 0 : options.topK,
211
- presencePenalty: options == null ? void 0 : options.presencePenalty,
212
- frequencyPenalty: options == null ? void 0 : options.frequencyPenalty,
213
- stopSequences: options == null ? void 0 : options.stopSequences,
214
- seed: options == null ? void 0 : options.seed,
215
- repairToolCall: options == null ? void 0 : options.repairToolCall
216
- }).then((result) => result.stream).catch((error) => {
217
- if ((abortSignal == null ? void 0 : abortSignal.aborted) && isAbortError(error)) {
218
- return void 0;
219
- }
220
- throw error;
193
+ const { retry } = prepareRetries({
194
+ maxRetries: options == null ? void 0 : options.maxRetries,
195
+ abortSignal
221
196
  });
197
+ const modelStream = await (async () => {
198
+ try {
199
+ const { stream } = await retry(
200
+ () => streamModelCall({
201
+ model,
202
+ // streamModelCall expects Prompt (ModelMessage[]) but we pass the
203
+ // pre-converted LanguageModelV4Prompt. standardizePrompt inside
204
+ // streamModelCall handles both formats.
205
+ messages: conversationPrompt,
206
+ allowSystemInMessages: true,
207
+ tools,
208
+ toolChoice: options == null ? void 0 : options.toolChoice,
209
+ includeRawChunks: options == null ? void 0 : options.includeRawChunks,
210
+ providerOptions: options == null ? void 0 : options.providerOptions,
211
+ abortSignal,
212
+ headers: options == null ? void 0 : options.headers,
213
+ reasoning: options == null ? void 0 : options.reasoning,
214
+ output,
215
+ maxOutputTokens: options == null ? void 0 : options.maxOutputTokens,
216
+ temperature: options == null ? void 0 : options.temperature,
217
+ topP: options == null ? void 0 : options.topP,
218
+ topK: options == null ? void 0 : options.topK,
219
+ presencePenalty: options == null ? void 0 : options.presencePenalty,
220
+ frequencyPenalty: options == null ? void 0 : options.frequencyPenalty,
221
+ stopSequences: options == null ? void 0 : options.stopSequences,
222
+ seed: options == null ? void 0 : options.seed,
223
+ repairToolCall: options == null ? void 0 : options.repairToolCall
224
+ })
225
+ );
226
+ return stream;
227
+ } catch (error) {
228
+ if ((abortSignal == null ? void 0 : abortSignal.aborted) && isAbortError(error)) {
229
+ return void 0;
230
+ }
231
+ throw error;
232
+ }
233
+ })();
222
234
  if (modelStream == null) {
223
235
  return { aborted: true };
224
236
  }
@@ -229,6 +241,8 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
229
241
  const reasoningParts = [];
230
242
  let responseMetadata;
231
243
  let warnings;
244
+ let terminalError;
245
+ let hasTerminalError = false;
232
246
  const writer = writable == null ? void 0 : writable.getWriter();
233
247
  try {
234
248
  for await (const part of modelStream) {
@@ -294,6 +308,10 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
294
308
  if (writer) {
295
309
  await writer.write(part);
296
310
  }
311
+ if (part.type === "error" && !hasTerminalError) {
312
+ terminalError = part.error;
313
+ hasTerminalError = true;
314
+ }
297
315
  }
298
316
  } catch (error) {
299
317
  if ((abortSignal == null ? void 0 : abortSignal.aborted) && isAbortError(error)) {
@@ -315,9 +333,11 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
315
333
  responseMetadata,
316
334
  warnings
317
335
  },
318
- providerExecutedToolResults
336
+ providerExecutedToolResults,
337
+ ...hasTerminalError ? { terminalError } : {}
319
338
  };
320
339
  }
340
+ doStreamStep.maxRetries = 0;
321
341
 
322
342
  // src/stream-text-iterator.ts
323
343
  var prepareStepGenerationSettingKeys = [
@@ -382,6 +402,8 @@ async function* streamTextIterator({
382
402
  let lastStep;
383
403
  let lastStepWasToolCalls = false;
384
404
  let wasAborted = false;
405
+ let terminalError;
406
+ let hasTerminalError = false;
385
407
  const telemetryDispatcher = createRestrictedTelemetryDispatcher({
386
408
  telemetry,
387
409
  includeRuntimeContext: telemetry == null ? void 0 : telemetry.includeRuntimeContext,
@@ -515,6 +537,10 @@ async function* streamTextIterator({
515
537
  wasAborted = true;
516
538
  break;
517
539
  }
540
+ if ("terminalError" in streamStepResult) {
541
+ terminalError = streamStepResult.terminalError;
542
+ hasTerminalError = true;
543
+ }
518
544
  const { toolCalls, finish, raw, providerExecutedToolResults } = streamStepResult;
519
545
  const step = buildStepResult(raw, toolCalls, finish, {
520
546
  stepNumber,
@@ -537,7 +563,9 @@ async function* streamTextIterator({
537
563
  lastStep = step;
538
564
  lastStepWasToolCalls = false;
539
565
  const finishReason = finish == null ? void 0 : finish.finishReason;
540
- if (finishReason === "tool-calls") {
566
+ if (hasTerminalError) {
567
+ done = true;
568
+ } else if (finishReason === "tool-calls") {
541
569
  lastStepWasToolCalls = true;
542
570
  const textContent = step.content.filter(
543
571
  (item) => item.type === "text"
@@ -634,6 +662,9 @@ async function* streamTextIterator({
634
662
  if (wasAborted) {
635
663
  return { aborted: true, messages: conversationPrompt };
636
664
  }
665
+ if (hasTerminalError) {
666
+ return { error: terminalError, messages: conversationPrompt };
667
+ }
637
668
  return conversationPrompt;
638
669
  }
639
670
  function getModelInfo(model) {
@@ -797,7 +828,7 @@ var WorkflowAgent = class {
797
828
  throw new Error("Not implemented");
798
829
  }
799
830
  async stream(options) {
800
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T;
831
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U;
801
832
  const { onFinish, onEnd = onFinish } = options;
802
833
  let effectiveModel = this.model;
803
834
  let effectiveInstructions = (_b = (_a = options.instructions) != null ? _a : options.system) != null ? _b : this.instructions;
@@ -1421,7 +1452,6 @@ var WorkflowAgent = class {
1421
1452
  stopConditions: effectiveStopWhenFromPrepare,
1422
1453
  onStepEnd: mergedOnStepEnd,
1423
1454
  onStepStart: mergedOnStepStart,
1424
- onError: options.onError,
1425
1455
  prepareStep: (_z = options.prepareStep) != null ? _z : this.prepareStep,
1426
1456
  generationSettings: mergedGenerationSettings,
1427
1457
  toolChoice: effectiveToolChoice,
@@ -1436,7 +1466,10 @@ var WorkflowAgent = class {
1436
1466
  });
1437
1467
  let finalMessages;
1438
1468
  let encounteredError;
1469
+ let hasEncounteredError = false;
1439
1470
  let wasAborted = false;
1471
+ let terminalError;
1472
+ let hasTerminalError = false;
1440
1473
  try {
1441
1474
  let result = await iterator.next();
1442
1475
  while (!result.done) {
@@ -1735,6 +1768,10 @@ var WorkflowAgent = class {
1735
1768
  if (result.done) {
1736
1769
  if (Array.isArray(result.value)) {
1737
1770
  finalMessages = result.value;
1771
+ } else if ("error" in result.value) {
1772
+ finalMessages = result.value.messages;
1773
+ terminalError = result.value.error;
1774
+ hasTerminalError = true;
1738
1775
  } else {
1739
1776
  finalMessages = result.value.messages;
1740
1777
  wasAborted = true;
@@ -1745,6 +1782,7 @@ var WorkflowAgent = class {
1745
1782
  }
1746
1783
  } catch (error) {
1747
1784
  encounteredError = error;
1785
+ hasEncounteredError = true;
1748
1786
  if (isAbortError2(error)) {
1749
1787
  wasAborted = true;
1750
1788
  if (options.onAbort) {
@@ -1755,8 +1793,14 @@ var WorkflowAgent = class {
1755
1793
  }
1756
1794
  await ((_L = telemetryDispatcher.onError) == null ? void 0 : _L.call(telemetryDispatcher, error));
1757
1795
  }
1796
+ if (hasTerminalError) {
1797
+ if (options.onError) {
1798
+ await options.onError({ error: terminalError });
1799
+ }
1800
+ await ((_M = telemetryDispatcher.onError) == null ? void 0 : _M.call(telemetryDispatcher, terminalError));
1801
+ }
1758
1802
  const messages = finalMessages != null ? finalMessages : prompt.messages;
1759
- const effectiveOutput = (_M = options.output) != null ? _M : this.output;
1803
+ const effectiveOutput = (_N = options.output) != null ? _N : this.output;
1760
1804
  let experimentalOutput = void 0;
1761
1805
  if (effectiveOutput && steps.length > 0) {
1762
1806
  const lastStep2 = steps[steps.length - 1];
@@ -1772,20 +1816,21 @@ var WorkflowAgent = class {
1772
1816
  }
1773
1817
  );
1774
1818
  } catch (parseError) {
1775
- if (!encounteredError) {
1819
+ if (!hasEncounteredError) {
1776
1820
  encounteredError = parseError;
1821
+ hasEncounteredError = true;
1777
1822
  }
1778
1823
  }
1779
1824
  }
1780
1825
  }
1781
1826
  const lastStep = steps[steps.length - 1];
1782
1827
  const totalUsage = aggregateUsage(steps);
1783
- const finishReason = (_N = lastStep == null ? void 0 : lastStep.finishReason) != null ? _N : "other";
1828
+ const finishReason = (_O = lastStep == null ? void 0 : lastStep.finishReason) != null ? _O : "other";
1784
1829
  if (mergedOnEnd && !wasAborted) {
1785
1830
  await mergedOnEnd({
1786
1831
  steps,
1787
1832
  messages,
1788
- text: (_O = lastStep == null ? void 0 : lastStep.text) != null ? _O : "",
1833
+ text: (_P = lastStep == null ? void 0 : lastStep.text) != null ? _P : "",
1789
1834
  finishReason,
1790
1835
  usage: totalUsage,
1791
1836
  totalUsage,
@@ -1797,17 +1842,17 @@ var WorkflowAgent = class {
1797
1842
  if (!wasAborted && steps.length > 0) {
1798
1843
  const telemetrySteps = steps.map(normalizeStepForTelemetry2);
1799
1844
  const lastTelemetryStep = telemetrySteps[telemetrySteps.length - 1];
1800
- await ((_P = telemetryDispatcher.onEnd) == null ? void 0 : _P.call(telemetryDispatcher, {
1845
+ await ((_Q = telemetryDispatcher.onEnd) == null ? void 0 : _Q.call(telemetryDispatcher, {
1801
1846
  ...lastTelemetryStep,
1802
1847
  steps: telemetrySteps,
1803
1848
  usage: totalUsage,
1804
1849
  totalUsage
1805
1850
  }));
1806
1851
  }
1807
- if (encounteredError) {
1852
+ if (hasEncounteredError) {
1808
1853
  if (options.writable) {
1809
- const sendFinish = (_Q = options.sendFinish) != null ? _Q : true;
1810
- const preventClose = (_R = options.preventClose) != null ? _R : false;
1854
+ const sendFinish = (_R = options.sendFinish) != null ? _R : true;
1855
+ const preventClose = (_S = options.preventClose) != null ? _S : false;
1811
1856
  if (sendFinish || !preventClose) {
1812
1857
  await closeStream(options.writable, preventClose, sendFinish);
1813
1858
  }
@@ -1815,8 +1860,8 @@ var WorkflowAgent = class {
1815
1860
  throw encounteredError;
1816
1861
  }
1817
1862
  if (options.writable) {
1818
- const sendFinish = (_S = options.sendFinish) != null ? _S : true;
1819
- const preventClose = (_T = options.preventClose) != null ? _T : false;
1863
+ const sendFinish = (_T = options.sendFinish) != null ? _T : true;
1864
+ const preventClose = (_U = options.preventClose) != null ? _U : false;
1820
1865
  if (sendFinish || !preventClose) {
1821
1866
  await closeStream(options.writable, preventClose, sendFinish);
1822
1867
  }
@@ -1828,7 +1873,8 @@ var WorkflowAgent = class {
1828
1873
  toolResults: lastStepToolResults,
1829
1874
  finishReason,
1830
1875
  totalUsage,
1831
- output: experimentalOutput
1876
+ output: experimentalOutput,
1877
+ ...hasTerminalError ? { error: terminalError } : {}
1832
1878
  };
1833
1879
  }
1834
1880
  };