ai 7.0.106 → 7.0.107

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,25 @@
1
1
  # ai
2
2
 
3
+ ## 7.0.107
4
+
5
+ ### Patch Changes
6
+
7
+ - 79681c4: fix(ai): preserve provider file and skill upload APIs in wrapProvider
8
+ - 98c7275: fix(ai): preserve query parameters in chat reconnect URLs
9
+ - a105059: fix(workflow): support deferred tool discovery in WorkflowAgent
10
+ - 31532f3: fix(ai): prevent preliminary tool outputs from completing chats
11
+ - e61cbd8: fix(ai): preserve raw speech audio format metadata
12
+ - 8ade040: fix(ai): pass tool-specific context to input callbacks
13
+ - 970a01e: fix(ai): enforce polling timeouts for in-flight video status requests
14
+ - 85539c5: fix(ai): preserve multiple Set-Cookie headers in Node stream responses
15
+ - 611d301: fix(ai): prevent duplicate content types in chat transport requests
16
+ - c415657: fix(ai): decode base64 text data URLs using their declared charset
17
+ - Updated dependencies [2973485]
18
+ - Updated dependencies [a4db5ea]
19
+ - Updated dependencies [2937ea2]
20
+ - @ai-sdk/provider-utils@5.0.45
21
+ - @ai-sdk/gateway@4.0.87
22
+
3
23
  ## 7.0.106
4
24
 
5
25
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1211,7 +1211,7 @@ import {
1211
1211
  } from "@ai-sdk/provider-utils";
1212
1212
 
1213
1213
  // src/version.ts
1214
- var VERSION = true ? "7.0.106" : "0.0.0-test";
1214
+ var VERSION = true ? "7.0.107" : "0.0.0-test";
1215
1215
 
1216
1216
  // src/util/download/download.ts
1217
1217
  var download = async ({
@@ -6265,22 +6265,29 @@ async function generateText({
6265
6265
  if (tool3 == null) {
6266
6266
  continue;
6267
6267
  }
6268
- if (tool3.onInputStart != null) {
6269
- await tool3.onInputStart({
6270
- toolCallId: toolCall.toolCallId,
6271
- messages: stepMessages,
6272
- abortSignal: mergedAbortSignal,
6273
- context: runtimeContext
6274
- });
6275
- }
6276
- if ((tool3 == null ? void 0 : tool3.onInputAvailable) != null) {
6277
- await tool3.onInputAvailable({
6278
- input: toolCall.input,
6279
- toolCallId: toolCall.toolCallId,
6280
- messages: stepMessages,
6281
- abortSignal: mergedAbortSignal,
6282
- context: runtimeContext
6268
+ if (tool3.onInputStart != null || tool3.onInputAvailable != null) {
6269
+ const context = await validateToolContext({
6270
+ toolName: toolCall.toolName,
6271
+ context: getOwn(toolsContext, toolCall.toolName),
6272
+ contextSchema: tool3.contextSchema
6283
6273
  });
6274
+ if (tool3.onInputStart != null) {
6275
+ await tool3.onInputStart({
6276
+ toolCallId: toolCall.toolCallId,
6277
+ messages: stepMessages,
6278
+ abortSignal: mergedAbortSignal,
6279
+ context
6280
+ });
6281
+ }
6282
+ if (tool3.onInputAvailable != null) {
6283
+ await tool3.onInputAvailable({
6284
+ input: toolCall.input,
6285
+ toolCallId: toolCall.toolCallId,
6286
+ messages: stepMessages,
6287
+ abortSignal: mergedAbortSignal,
6288
+ context
6289
+ });
6290
+ }
6284
6291
  }
6285
6292
  const toolApprovalStatus = await resolveToolApproval({
6286
6293
  tools: stepExecutionTools,
@@ -6783,10 +6790,13 @@ function writeToServerResponse({
6783
6790
  stream
6784
6791
  }) {
6785
6792
  const statusCode = status != null ? status : 200;
6793
+ if (headers != null) {
6794
+ response.setHeaders(headers);
6795
+ }
6786
6796
  if (statusText !== void 0) {
6787
- response.writeHead(statusCode, statusText, headers);
6797
+ response.writeHead(statusCode, statusText);
6788
6798
  } else {
6789
- response.writeHead(statusCode, headers);
6799
+ response.writeHead(statusCode);
6790
6800
  }
6791
6801
  const reader = stream.getReader();
6792
6802
  const read = async () => {
@@ -6826,11 +6836,9 @@ function pipeTextStreamToResponse({
6826
6836
  response,
6827
6837
  status,
6828
6838
  statusText,
6829
- headers: Object.fromEntries(
6830
- prepareHeaders(headers, {
6831
- "content-type": "text/plain; charset=utf-8"
6832
- }).entries()
6833
- ),
6839
+ headers: prepareHeaders(headers, {
6840
+ "content-type": "text/plain; charset=utf-8"
6841
+ }),
6834
6842
  stream: stream.pipeThrough(new TextEncoderStream())
6835
6843
  });
6836
6844
  }
@@ -6916,9 +6924,7 @@ function pipeUIMessageStreamToResponse({
6916
6924
  response,
6917
6925
  status,
6918
6926
  statusText,
6919
- headers: Object.fromEntries(
6920
- prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS).entries()
6921
- ),
6927
+ headers: prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS),
6922
6928
  stream: sseStream.pipeThrough(new TextEncoderStream())
6923
6929
  });
6924
6930
  }
@@ -8796,33 +8802,60 @@ function invokeToolCallbacksFromStream({
8796
8802
  tools,
8797
8803
  stepInputMessages,
8798
8804
  abortSignal,
8799
- runtimeContext
8805
+ toolsContext
8800
8806
  }) {
8801
8807
  if (tools == null) return stream;
8802
- const ongoingToolCallToolNames = createIdMap();
8808
+ let ongoingToolCalls = createIdMap();
8809
+ const getValidatedContext = ({
8810
+ toolCallId,
8811
+ toolName
8812
+ }) => {
8813
+ const ongoingToolCall = ongoingToolCalls[toolCallId];
8814
+ if ((ongoingToolCall == null ? void 0 : ongoingToolCall.validatedContext) != null) {
8815
+ return ongoingToolCall.validatedContext;
8816
+ }
8817
+ const tool3 = getOwn(tools, toolName);
8818
+ const validatedContext = validateToolContext({
8819
+ toolName,
8820
+ context: getOwn(toolsContext, toolName),
8821
+ contextSchema: tool3 == null ? void 0 : tool3.contextSchema
8822
+ });
8823
+ if (ongoingToolCall != null) {
8824
+ ongoingToolCall.validatedContext = validatedContext;
8825
+ }
8826
+ return validatedContext;
8827
+ };
8803
8828
  return stream.pipeThrough(
8804
8829
  new TransformStream({
8805
8830
  async transform(chunk, controller) {
8831
+ var _a25, _b25;
8806
8832
  controller.enqueue(chunk);
8807
8833
  if (isStreamRetryAttemptBoundaryPart(chunk)) {
8834
+ ongoingToolCalls = createIdMap();
8808
8835
  return;
8809
8836
  }
8810
8837
  switch (chunk.type) {
8811
8838
  case "tool-input-start": {
8812
- ongoingToolCallToolNames[chunk.id] = chunk.toolName;
8839
+ ongoingToolCalls[chunk.id] = {
8840
+ toolName: chunk.toolName,
8841
+ validatedContext: void 0
8842
+ };
8813
8843
  const tool3 = getOwn(tools, chunk.toolName);
8814
8844
  if ((tool3 == null ? void 0 : tool3.onInputStart) != null) {
8815
8845
  await tool3.onInputStart({
8816
8846
  toolCallId: chunk.id,
8817
8847
  messages: stepInputMessages,
8818
8848
  abortSignal,
8819
- context: runtimeContext
8849
+ context: await getValidatedContext({
8850
+ toolCallId: chunk.id,
8851
+ toolName: chunk.toolName
8852
+ })
8820
8853
  });
8821
8854
  }
8822
8855
  break;
8823
8856
  }
8824
8857
  case "tool-input-delta": {
8825
- const toolName = ongoingToolCallToolNames[chunk.id];
8858
+ const toolName = (_a25 = ongoingToolCalls[chunk.id]) == null ? void 0 : _a25.toolName;
8826
8859
  const tool3 = getOwn(tools, toolName);
8827
8860
  if ((tool3 == null ? void 0 : tool3.onInputDelta) != null) {
8828
8861
  await tool3.onInputDelta({
@@ -8830,23 +8863,32 @@ function invokeToolCallbacksFromStream({
8830
8863
  toolCallId: chunk.id,
8831
8864
  messages: stepInputMessages,
8832
8865
  abortSignal,
8833
- context: runtimeContext
8866
+ context: await getValidatedContext({
8867
+ toolCallId: chunk.id,
8868
+ toolName
8869
+ })
8834
8870
  });
8835
8871
  }
8836
8872
  break;
8837
8873
  }
8838
8874
  case "tool-call": {
8839
- const toolName = ongoingToolCallToolNames[chunk.toolCallId];
8875
+ const toolName = (_b25 = ongoingToolCalls[chunk.toolCallId]) == null ? void 0 : _b25.toolName;
8840
8876
  const tool3 = getOwn(tools, toolName);
8841
- delete ongoingToolCallToolNames[chunk.toolCallId];
8842
8877
  if (!chunk.invalid && (tool3 == null ? void 0 : tool3.onInputAvailable) != null) {
8878
+ const validatedContext = getValidatedContext({
8879
+ toolCallId: chunk.toolCallId,
8880
+ toolName
8881
+ });
8882
+ delete ongoingToolCalls[chunk.toolCallId];
8843
8883
  await tool3.onInputAvailable({
8844
8884
  input: chunk.input,
8845
8885
  toolCallId: chunk.toolCallId,
8846
8886
  messages: stepInputMessages,
8847
8887
  abortSignal,
8848
- context: runtimeContext
8888
+ context: await validatedContext
8849
8889
  });
8890
+ } else {
8891
+ delete ongoingToolCalls[chunk.toolCallId];
8850
8892
  }
8851
8893
  }
8852
8894
  }
@@ -10881,7 +10923,7 @@ var DefaultStreamTextResult = class {
10881
10923
  tools: stepExecutionTools,
10882
10924
  stepInputMessages: stepMessages,
10883
10925
  abortSignal,
10884
- runtimeContext
10926
+ toolsContext
10885
10927
  });
10886
10928
  const runInTracingChannelSpanInStep = telemetryDispatcher.runInTracingChannelSpan == null ? void 0 : (options) => runInStepTracingChannelContext(
10887
10929
  () => telemetryDispatcher.runInTracingChannelSpan(options)
@@ -15331,8 +15373,13 @@ function createDownload(options) {
15331
15373
  // src/util/data-url.ts
15332
15374
  var { atob: atob2 } = globalThis;
15333
15375
  function getTextFromDataUrl(dataUrl) {
15376
+ var _a25;
15334
15377
  const [header, base64Content] = dataUrl.split(",");
15335
15378
  const mediaType = header.split(";")[0].split(":")[1];
15379
+ const charsetMatch = /(?:^|;)\s*charset\s*=\s*(?:"([^"]+)"|([^;\s]+))/i.exec(
15380
+ header
15381
+ );
15382
+ const charset = (_a25 = charsetMatch == null ? void 0 : charsetMatch[1]) != null ? _a25 : charsetMatch == null ? void 0 : charsetMatch[2];
15336
15383
  if (mediaType == null || base64Content == null) {
15337
15384
  throw new InvalidArgumentError({
15338
15385
  parameter: "dataUrl",
@@ -15341,7 +15388,13 @@ function getTextFromDataUrl(dataUrl) {
15341
15388
  });
15342
15389
  }
15343
15390
  try {
15344
- return atob2(base64Content);
15391
+ const byteString = atob2(base64Content);
15392
+ if (charset == null) {
15393
+ return byteString;
15394
+ }
15395
+ return new TextDecoder(charset).decode(
15396
+ Uint8Array.from(byteString, (byte) => byte.codePointAt(0))
15397
+ );
15345
15398
  } catch (e) {
15346
15399
  throw new InvalidArgumentError({
15347
15400
  parameter: "dataUrl",
@@ -16010,7 +16063,7 @@ async function generateSpeech({
16010
16063
  abortSignal,
16011
16064
  headers
16012
16065
  }) {
16013
- var _a25;
16066
+ var _a25, _b25;
16014
16067
  const resolvedModel = resolveSpeechModel(model);
16015
16068
  if (!resolvedModel) {
16016
16069
  throw new Error("Model could not be resolved");
@@ -16044,19 +16097,41 @@ async function generateSpeech({
16044
16097
  provider: resolvedModel.provider,
16045
16098
  model: resolvedModel.modelId
16046
16099
  });
16100
+ const detectedMediaType = detectMediaType4({
16101
+ data: result.audio,
16102
+ topLevelType: "audio"
16103
+ });
16047
16104
  return new DefaultSpeechResult({
16048
16105
  audio: new DefaultGeneratedAudioFile({
16049
16106
  data: result.audio,
16050
- mediaType: (_a25 = detectMediaType4({
16051
- data: result.audio,
16052
- topLevelType: "audio"
16053
- })) != null ? _a25 : "audio/mp3"
16107
+ mediaType: (_b25 = (_a25 = detectedMediaType != null ? detectedMediaType : getResponseAudioMediaType(result.response.headers)) != null ? _a25 : getOutputFormatMediaType(outputFormat)) != null ? _b25 : "audio/mp3"
16054
16108
  }),
16055
16109
  warnings: result.warnings,
16056
16110
  responses: [result.response],
16057
16111
  providerMetadata: result.providerMetadata
16058
16112
  });
16059
16113
  }
16114
+ function getResponseAudioMediaType(headers) {
16115
+ var _a25;
16116
+ const mediaType = (_a25 = Object.entries(headers != null ? headers : {}).find(
16117
+ ([name25]) => name25.toLowerCase() === "content-type"
16118
+ )) == null ? void 0 : _a25[1];
16119
+ if (mediaType == null) {
16120
+ return void 0;
16121
+ }
16122
+ const normalizedMediaType = mediaType.split(";", 1)[0].trim().toLowerCase();
16123
+ if (normalizedMediaType.length === 0) {
16124
+ return void 0;
16125
+ }
16126
+ return normalizedMediaType.startsWith("audio/") ? normalizedMediaType : void 0;
16127
+ }
16128
+ function getOutputFormatMediaType(outputFormat) {
16129
+ if (outputFormat == null) {
16130
+ return void 0;
16131
+ }
16132
+ const normalizedOutputFormat = outputFormat.trim().toLowerCase();
16133
+ return normalizedOutputFormat === "pcm" || normalizedOutputFormat === "audio/pcm" ? "audio/pcm" : void 0;
16134
+ }
16060
16135
  var DefaultSpeechResult = class {
16061
16136
  constructor(options) {
16062
16137
  var _a25;
@@ -16364,7 +16439,7 @@ async function experimental_generateVideo({
16364
16439
  headers != null ? headers : {},
16365
16440
  `ai/${VERSION}`
16366
16441
  );
16367
- const { retry } = prepareRetries({
16442
+ const { maxRetries, retry } = prepareRetries({
16368
16443
  maxRetries: maxRetriesArg,
16369
16444
  abortSignal
16370
16445
  });
@@ -16424,6 +16499,7 @@ async function experimental_generateVideo({
16424
16499
  callOptions,
16425
16500
  poll,
16426
16501
  webhook,
16502
+ maxRetries,
16427
16503
  retry
16428
16504
  });
16429
16505
  }
@@ -16512,6 +16588,7 @@ async function executeStartStatusFlow({
16512
16588
  callOptions,
16513
16589
  poll: pollConfig,
16514
16590
  webhook: webhookFactory,
16591
+ maxRetries,
16515
16592
  retry
16516
16593
  }) {
16517
16594
  var _a25, _b25, _c, _d;
@@ -16553,6 +16630,9 @@ async function executeStartStatusFlow({
16553
16630
  const timeoutMs = (_c = pollConfig == null ? void 0 : pollConfig.timeoutMs) != null ? _c : 6e5;
16554
16631
  const delay = (_d = pollConfig == null ? void 0 : pollConfig.delay) != null ? _d : defaultDelay;
16555
16632
  const startTime = Date.now();
16633
+ const pollingTimeoutError = new Error(
16634
+ `Video generation timed out after ${timeoutMs}ms.`
16635
+ );
16556
16636
  if (webhookReceived != null) {
16557
16637
  await waitForWebhook({
16558
16638
  received: webhookReceived,
@@ -16565,22 +16645,65 @@ async function executeStartStatusFlow({
16565
16645
  if (webhookReceived == null) {
16566
16646
  const elapsedMs = Date.now() - startTime;
16567
16647
  if (elapsedMs >= timeoutMs) {
16568
- throw new Error(`Video generation timed out after ${timeoutMs}ms.`);
16648
+ throw pollingTimeoutError;
16569
16649
  }
16570
16650
  await delay(Math.min(intervalMs, timeoutMs - elapsedMs), {
16571
16651
  abortSignal: callOptions.abortSignal
16572
16652
  });
16573
16653
  if (Date.now() - startTime >= timeoutMs) {
16574
- throw new Error(`Video generation timed out after ${timeoutMs}ms.`);
16654
+ throw pollingTimeoutError;
16655
+ }
16656
+ }
16657
+ let statusResult;
16658
+ if (webhookReceived != null) {
16659
+ statusResult = await retry(
16660
+ () => model.doStatus({
16661
+ operation: startResult.operation,
16662
+ abortSignal: callOptions.abortSignal,
16663
+ headers: callOptions.headers
16664
+ })
16665
+ );
16666
+ } else {
16667
+ const statusTimeoutController = new AbortController();
16668
+ const statusAbortSignal = mergeAbortSignals(
16669
+ callOptions.abortSignal,
16670
+ statusTimeoutController.signal
16671
+ );
16672
+ const statusTimeoutId = setTimeout(
16673
+ () => statusTimeoutController.abort(pollingTimeoutError),
16674
+ timeoutMs - (Date.now() - startTime)
16675
+ );
16676
+ const statusTimeoutPromise = new Promise((_, reject) => {
16677
+ statusTimeoutController.signal.addEventListener(
16678
+ "abort",
16679
+ () => reject(pollingTimeoutError),
16680
+ { once: true }
16681
+ );
16682
+ });
16683
+ const { retry: statusRetry } = prepareRetries({
16684
+ maxRetries,
16685
+ abortSignal: statusAbortSignal
16686
+ });
16687
+ try {
16688
+ statusResult = await Promise.race([
16689
+ statusRetry(
16690
+ () => model.doStatus({
16691
+ operation: startResult.operation,
16692
+ abortSignal: statusAbortSignal,
16693
+ headers: callOptions.headers
16694
+ })
16695
+ ),
16696
+ statusTimeoutPromise
16697
+ ]);
16698
+ } catch (error) {
16699
+ if (statusTimeoutController.signal.aborted) {
16700
+ throw pollingTimeoutError;
16701
+ }
16702
+ throw error;
16703
+ } finally {
16704
+ clearTimeout(statusTimeoutId);
16575
16705
  }
16576
16706
  }
16577
- const statusResult = await retry(
16578
- () => model.doStatus({
16579
- operation: startResult.operation,
16580
- abortSignal: callOptions.abortSignal,
16581
- headers: callOptions.headers
16582
- })
16583
- );
16584
16707
  if (statusResult.status === "error") {
16585
16708
  throw new Error(statusResult.error);
16586
16709
  }
@@ -17551,7 +17674,9 @@ function wrapProvider({
17551
17674
  },
17552
17675
  transcriptionModel: providerV4.transcriptionModel,
17553
17676
  speechModel: providerV4.speechModel,
17554
- rerankingModel: providerV4.rerankingModel
17677
+ rerankingModel: providerV4.rerankingModel,
17678
+ ...providerV4.files != null ? { files: providerV4.files } : {},
17679
+ ...providerV4.skills != null ? { skills: providerV4.skills } : {}
17555
17680
  };
17556
17681
  }
17557
17682
 
@@ -21532,6 +21657,10 @@ import {
21532
21657
  resolve as resolve2
21533
21658
  } from "@ai-sdk/provider-utils";
21534
21659
  import { EmptyResponseBodyError as EmptyResponseBodyError3 } from "@ai-sdk/provider";
21660
+ function appendPathToUrl(url, path) {
21661
+ const queryOrFragmentStart = url.search(/[?#]/);
21662
+ return queryOrFragmentStart === -1 ? `${url}${path}` : `${url.slice(0, queryOrFragmentStart)}${path}${url.slice(queryOrFragmentStart)}`;
21663
+ }
21535
21664
  var HttpChatTransport = class {
21536
21665
  constructor({
21537
21666
  api = "/api/chat",
@@ -21588,7 +21717,7 @@ var HttpChatTransport = class {
21588
21717
  const response = await fetch2(api, {
21589
21718
  method: "POST",
21590
21719
  headers: {
21591
- "Content-Type": "application/json",
21720
+ "content-type": "application/json",
21592
21721
  ...headers
21593
21722
  },
21594
21723
  body: JSON.stringify(body),
@@ -21626,7 +21755,7 @@ var HttpChatTransport = class {
21626
21755
  credentials: resolvedCredentials,
21627
21756
  requestMetadata: options.metadata
21628
21757
  }));
21629
- const api = (_b25 = preparedRequest == null ? void 0 : preparedRequest.api) != null ? _b25 : `${this.api}/${options.chatId}/stream`;
21758
+ const api = (_b25 = preparedRequest == null ? void 0 : preparedRequest.api) != null ? _b25 : appendPathToUrl(this.api, `/${options.chatId}/stream`);
21630
21759
  const headers = (preparedRequest == null ? void 0 : preparedRequest.headers) !== void 0 ? normalizeHeaders(preparedRequest.headers) : baseHeaders;
21631
21760
  const credentials = (_c = preparedRequest == null ? void 0 : preparedRequest.credentials) != null ? _c : resolvedCredentials;
21632
21761
  const fetch2 = (_d = this.fetch) != null ? _d : globalThis.fetch;
@@ -22212,7 +22341,7 @@ function lastAssistantMessageIsCompleteWithApprovalResponses({
22212
22341
  // has at least one tool approval response
22213
22342
  lastStepToolInvocations.filter((part) => part.state === "approval-responded").length > 0 && // all tool approvals must have a response
22214
22343
  lastStepToolInvocations.every(
22215
- (part) => part.state === "output-available" || part.state === "output-error" || part.state === "output-denied" || part.state === "approval-responded"
22344
+ (part) => part.state === "output-available" && part.preliminary !== true || part.state === "output-error" || part.state === "output-denied" || part.state === "approval-responded"
22216
22345
  )
22217
22346
  );
22218
22347
  }
@@ -22233,7 +22362,7 @@ function lastAssistantMessageIsCompleteWithToolCalls({
22233
22362
  }, -1);
22234
22363
  const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolUIPart).filter((part) => !part.providerExecuted);
22235
22364
  return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every(
22236
- (part) => part.state === "output-available" || part.state === "output-error"
22365
+ (part) => part.state === "output-available" && part.preliminary !== true || part.state === "output-error"
22237
22366
  );
22238
22367
  }
22239
22368