@ai-sdk/provider-utils 3.0.39 → 3.0.41

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.mjs CHANGED
@@ -173,6 +173,15 @@ function isBrowserRuntime(globalThisAny = globalThis) {
173
173
  return globalThisAny.window != null;
174
174
  }
175
175
 
176
+ // src/is-same-origin.ts
177
+ function isSameOrigin(url, baseUrl) {
178
+ try {
179
+ return new URL(url).origin === new URL(baseUrl).origin;
180
+ } catch (e) {
181
+ return false;
182
+ }
183
+ }
184
+
176
185
  // src/validate-download-url.ts
177
186
  function validateDownloadUrl(url) {
178
187
  let parsed;
@@ -358,34 +367,24 @@ function createSafeLookup(lookup) {
358
367
  });
359
368
  }
360
369
  var safeNodeFetchPromise;
361
- var initialGlobalFetch = globalThis.fetch;
362
- var initialGlobalFetchIsNodeDefault = isNodeDefaultFetch(initialGlobalFetch);
363
370
  function isNodeRuntime() {
364
- var _a2, _b2;
371
+ var _a2, _b2, _c;
365
372
  const runtimeProcess = globalThis.process;
366
- return ((_a2 = runtimeProcess == null ? void 0 : runtimeProcess.release) == null ? void 0 : _a2.name) === "node" && ((_b2 = runtimeProcess.versions) == null ? void 0 : _b2.bun) == null;
373
+ return ((_a2 = runtimeProcess == null ? void 0 : runtimeProcess.release) == null ? void 0 : _a2.name) === "node" && ((_b2 = runtimeProcess.versions) == null ? void 0 : _b2.bun) == null && ((_c = runtimeProcess.versions) == null ? void 0 : _c.deno) == null && runtimeProcess.title !== "workerd" && globalThis.EdgeRuntime == null;
367
374
  }
368
375
  async function getDefaultDownloadFetch() {
369
- if (!isNodeRuntime() || !initialGlobalFetchIsNodeDefault || globalThis.fetch !== initialGlobalFetch) {
376
+ if (!isNodeRuntime()) {
370
377
  return globalThis.fetch;
371
378
  }
372
379
  return safeNodeFetchPromise != null ? safeNodeFetchPromise : safeNodeFetchPromise = createSafeNodeFetch();
373
380
  }
374
- function isNodeDefaultFetch(fetch) {
375
- if (typeof fetch !== "function") {
376
- return false;
377
- }
378
- const source = Function.prototype.toString.call(fetch);
379
- return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
380
- }
381
381
  async function createSafeNodeFetch() {
382
- const [{ createRequire }, { lookup }] = await Promise.all([
382
+ const [module, { lookup }] = await Promise.all([
383
383
  loadNodeModule("node:module"),
384
384
  loadNodeModule("node:dns")
385
385
  ]);
386
- const { Agent, fetch } = createRequire(getCurrentModulePath())(
387
- "undici"
388
- );
386
+ const nodeRequire = module.createRequire(getCurrentModulePath());
387
+ const { Agent, fetch } = nodeRequire("undici");
389
388
  const dispatcher = new Agent({
390
389
  connect: {
391
390
  lookup: createSafeLookup(lookup)
@@ -427,20 +426,47 @@ function getCurrentModulePath() {
427
426
 
428
427
  // src/fetch-with-validated-redirects.ts
429
428
  var MAX_DOWNLOAD_REDIRECTS = 10;
429
+ async function getValidatedFetch(customFetch) {
430
+ return customFetch == null || customFetch === globalThis.fetch ? await getDefaultDownloadFetch() : customFetch;
431
+ }
432
+ async function fetchWithValidatedEndpoint({
433
+ url,
434
+ init,
435
+ fetch: customFetch,
436
+ trustedOrigin,
437
+ redirect = "error"
438
+ }) {
439
+ const urlText = url.toString();
440
+ const isTrusted = trustedOrigin !== void 0 && isSameOrigin(urlText, trustedOrigin);
441
+ if (!isTrusted) {
442
+ validateDownloadUrl(urlText);
443
+ }
444
+ const fetch = isTrusted && customFetch != null ? customFetch : isTrusted ? globalThis.fetch : await getValidatedFetch(customFetch);
445
+ return await fetch(url, {
446
+ ...init,
447
+ redirect
448
+ });
449
+ }
430
450
  async function fetchWithValidatedRedirects({
431
451
  url,
432
452
  headers,
433
453
  abortSignal,
434
- maxRedirects = MAX_DOWNLOAD_REDIRECTS
454
+ maxRedirects = MAX_DOWNLOAD_REDIRECTS,
455
+ fetch: customFetch,
456
+ trustedOrigin
435
457
  }) {
458
+ var _a2;
436
459
  const baseInit = { signal: abortSignal };
437
460
  if (headers !== void 0) {
438
461
  baseInit.headers = headers;
439
462
  }
440
463
  let currentUrl = url;
441
464
  for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
442
- validateDownloadUrl(currentUrl);
443
- const fetch = await getDefaultDownloadFetch();
465
+ const isTrustedHop = trustedOrigin !== void 0 && isSameOrigin(currentUrl, trustedOrigin);
466
+ if (!isTrustedHop) {
467
+ validateDownloadUrl(currentUrl);
468
+ }
469
+ const fetch = isTrustedHop && customFetch != null ? customFetch : isTrustedHop ? globalThis.fetch : await getValidatedFetch(customFetch);
444
470
  const response = await fetch(currentUrl, {
445
471
  ...baseInit,
446
472
  redirect: "manual"
@@ -454,7 +480,7 @@ async function fetchWithValidatedRedirects({
454
480
  }
455
481
  return await fetch(currentUrl, { ...baseInit, redirect: "follow" });
456
482
  }
457
- const location = response.headers.get("location");
483
+ const location = (_a2 = response.headers) == null ? void 0 : _a2.get("location");
458
484
  if (response.status >= 300 && response.status < 400 && location) {
459
485
  await cancelResponseBody(response);
460
486
  currentUrl = new URL(location, currentUrl).toString();
@@ -708,7 +734,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
708
734
  }
709
735
 
710
736
  // src/version.ts
711
- var VERSION = true ? "3.0.39" : "0.0.0-test";
737
+ var VERSION = true ? "3.0.41" : "0.0.0-test";
712
738
 
713
739
  // src/get-from-api.ts
714
740
  var getOriginalFetch = () => globalThis.fetch;
@@ -819,15 +845,6 @@ function injectJsonInstructionIntoMessages({
819
845
  ];
820
846
  }
821
847
 
822
- // src/is-same-origin.ts
823
- function isSameOrigin(url, baseUrl) {
824
- try {
825
- return new URL(url).origin === new URL(baseUrl).origin;
826
- } catch (e) {
827
- return false;
828
- }
829
- }
830
-
831
848
  // src/is-url-supported.ts
832
849
  function isUrlSupported({
833
850
  mediaType,
@@ -2899,6 +2916,367 @@ function asSchema(schema) {
2899
2916
  }) : isSchema(schema) ? schema : typeof schema === "function" ? schema() : zodSchema(schema);
2900
2917
  }
2901
2918
 
2919
+ // src/streaming-tool-call-tracker.ts
2920
+ import {
2921
+ InvalidResponseDataError
2922
+ } from "@ai-sdk/provider";
2923
+
2924
+ // src/streaming-tool-call-argument-state.ts
2925
+ function startsWithStructuredValue(value) {
2926
+ if (typeof value !== "string") {
2927
+ return false;
2928
+ }
2929
+ const firstCharacter = value.trimStart()[0];
2930
+ return firstCharacter === "{" || firstCharacter === "[";
2931
+ }
2932
+ var StreamingToolCallArgumentState = class {
2933
+ constructor(initialValue = "") {
2934
+ this.structure = { kind: "undetermined" };
2935
+ this.append(initialValue);
2936
+ }
2937
+ get hasCompleteStructuredValue() {
2938
+ return this.structure.kind === "structured" && this.structure.complete === true;
2939
+ }
2940
+ append(delta) {
2941
+ let nextStructure = this.structure;
2942
+ for (const character of delta) {
2943
+ if (nextStructure.kind === "undetermined") {
2944
+ if (/\s/.test(character)) {
2945
+ continue;
2946
+ }
2947
+ if (character !== "{" && character !== "[") {
2948
+ nextStructure = { kind: "other" };
2949
+ continue;
2950
+ }
2951
+ nextStructure = {
2952
+ kind: "structured",
2953
+ stack: [character],
2954
+ inString: false,
2955
+ escaped: false,
2956
+ complete: false
2957
+ };
2958
+ continue;
2959
+ }
2960
+ if (nextStructure.kind !== "structured" || nextStructure.complete) {
2961
+ continue;
2962
+ }
2963
+ if (nextStructure.inString) {
2964
+ if (nextStructure.escaped) {
2965
+ nextStructure.escaped = false;
2966
+ } else if (character === "\\") {
2967
+ nextStructure.escaped = true;
2968
+ } else if (character === '"') {
2969
+ nextStructure.inString = false;
2970
+ }
2971
+ continue;
2972
+ }
2973
+ if (character === '"') {
2974
+ nextStructure.inString = true;
2975
+ } else if (character === "{" || character === "[") {
2976
+ nextStructure.stack.push(character);
2977
+ } else if (character === "}" || character === "]") {
2978
+ const expectedOpening = character === "}" ? "{" : "[";
2979
+ if (nextStructure.stack[nextStructure.stack.length - 1] !== expectedOpening) {
2980
+ nextStructure = { kind: "other" };
2981
+ continue;
2982
+ }
2983
+ nextStructure.stack.pop();
2984
+ if (nextStructure.stack.length === 0) {
2985
+ nextStructure.complete = true;
2986
+ }
2987
+ }
2988
+ }
2989
+ this.structure = nextStructure;
2990
+ }
2991
+ };
2992
+
2993
+ // src/streaming-tool-call-tracker.ts
2994
+ var StreamingToolCallTracker = class {
2995
+ constructor(controller, options = {}) {
2996
+ this.toolCalls = [];
2997
+ this.toolCallsById = /* @__PURE__ */ new Map();
2998
+ this.toolCallsByIndex = /* @__PURE__ */ new Map();
2999
+ this.usedToolCallIds = /* @__PURE__ */ new Set();
3000
+ this.nextGeneratedIdSuffixes = /* @__PURE__ */ new Map();
3001
+ var _a2, _b2;
3002
+ this.controller = controller;
3003
+ this._generateId = (_a2 = options.generateId) != null ? _a2 : generateId;
3004
+ this.typeValidation = (_b2 = options.typeValidation) != null ? _b2 : "none";
3005
+ this.extractMetadata = options.extractMetadata;
3006
+ this.buildToolCallProviderMetadata = options.buildToolCallProviderMetadata;
3007
+ }
3008
+ processDelta(toolCallDelta) {
3009
+ var _a2, _b2;
3010
+ const wireName = (_a2 = toolCallDelta.function) == null ? void 0 : _a2.name;
3011
+ const hasBlankName = typeof wireName === "string" && wireName.trim().length === 0;
3012
+ const wireId = this.getNonBlankString(toolCallDelta.id);
3013
+ const name2 = this.getNonBlankString(wireName);
3014
+ const { index } = toolCallDelta;
3015
+ const resolution = this.resolveToolCall({
3016
+ wireId,
3017
+ index,
3018
+ name: name2,
3019
+ hasExplicitCallStart: name2 != null && startsWithStructuredValue((_b2 = toolCallDelta.function) == null ? void 0 : _b2.arguments)
3020
+ });
3021
+ if (resolution.kind === "ambiguous") {
3022
+ return;
3023
+ }
3024
+ let toolCall;
3025
+ if (resolution.kind === "new") {
3026
+ if (hasBlankName) {
3027
+ return;
3028
+ }
3029
+ toolCall = this.processNewToolCall(toolCallDelta, {
3030
+ wireId,
3031
+ index,
3032
+ name: name2
3033
+ });
3034
+ } else {
3035
+ toolCall = resolution.toolCall;
3036
+ if (wireId != null) {
3037
+ this.associateWireId(toolCall, wireId);
3038
+ }
3039
+ this.processExistingToolCall(toolCall, toolCallDelta);
3040
+ }
3041
+ if (index != null) {
3042
+ this.associateIndex(toolCall, index);
3043
+ }
3044
+ }
3045
+ flush() {
3046
+ const toolCalls = this.toolCalls.every((toolCall) => toolCall.index != null) ? [...this.toolCalls].sort(
3047
+ (a, b) => a.index - b.index || a.sequence - b.sequence
3048
+ ) : this.toolCalls;
3049
+ for (const toolCall of toolCalls) {
3050
+ if (!toolCall.hasFinished) {
3051
+ this.finishToolCall(toolCall);
3052
+ }
3053
+ }
3054
+ }
3055
+ resolveToolCall({
3056
+ wireId,
3057
+ index,
3058
+ name: name2,
3059
+ hasExplicitCallStart
3060
+ }) {
3061
+ const indexedToolCalls = index != null ? this.toolCallsByIndex.get(index) : void 0;
3062
+ const matchingIndexedToolCalls = this.filterToolCallsByName(
3063
+ indexedToolCalls,
3064
+ name2
3065
+ );
3066
+ if (wireId != null) {
3067
+ const toolCallsWithId = this.toolCallsById.get(wireId);
3068
+ if (toolCallsWithId != null) {
3069
+ if (index != null) {
3070
+ const matchingToolCalls = matchingIndexedToolCalls.filter(
3071
+ (toolCall) => toolCallsWithId.has(toolCall)
3072
+ );
3073
+ const matchingToolCall = this.resolveMatchingToolCall(
3074
+ matchingToolCalls,
3075
+ hasExplicitCallStart
3076
+ );
3077
+ if (matchingToolCall.kind !== "new") {
3078
+ return matchingToolCall;
3079
+ }
3080
+ if (name2 != null) {
3081
+ return { kind: "new" };
3082
+ }
3083
+ if (indexedToolCalls != null) {
3084
+ return { kind: "ambiguous" };
3085
+ }
3086
+ return this.resolveMatchingToolCall([...toolCallsWithId], false);
3087
+ }
3088
+ if (name2 != null) {
3089
+ const matchingToolCalls = [...toolCallsWithId].filter(
3090
+ (toolCall) => toolCall.function.name === name2
3091
+ );
3092
+ return this.resolveMatchingToolCall(
3093
+ matchingToolCalls,
3094
+ hasExplicitCallStart
3095
+ );
3096
+ }
3097
+ return this.resolveMatchingToolCall([...toolCallsWithId], false);
3098
+ }
3099
+ if (matchingIndexedToolCalls.length > 0) {
3100
+ return hasExplicitCallStart ? { kind: "new" } : this.resolveMatchingToolCall(matchingIndexedToolCalls, false);
3101
+ }
3102
+ return { kind: "new" };
3103
+ }
3104
+ if (indexedToolCalls != null) {
3105
+ return this.resolveMatchingToolCall(
3106
+ matchingIndexedToolCalls,
3107
+ hasExplicitCallStart
3108
+ );
3109
+ }
3110
+ if (name2 != null) {
3111
+ return { kind: "new" };
3112
+ }
3113
+ const unfinishedToolCalls = this.toolCalls.filter(
3114
+ (toolCall) => !toolCall.hasFinished
3115
+ );
3116
+ if (unfinishedToolCalls.length === 1) {
3117
+ return { kind: "existing", toolCall: unfinishedToolCalls[0] };
3118
+ }
3119
+ return unfinishedToolCalls.length > 1 ? { kind: "ambiguous" } : { kind: "new" };
3120
+ }
3121
+ filterToolCallsByName(toolCalls, name2) {
3122
+ if (toolCalls == null) {
3123
+ return [];
3124
+ }
3125
+ return [...toolCalls].filter(
3126
+ (toolCall) => name2 == null || toolCall.function.name === name2
3127
+ );
3128
+ }
3129
+ resolveMatchingToolCall(toolCalls, hasExplicitCallStart) {
3130
+ if (toolCalls.length === 0) {
3131
+ return { kind: "new" };
3132
+ }
3133
+ if (!hasExplicitCallStart) {
3134
+ return toolCalls.length === 1 ? { kind: "existing", toolCall: toolCalls[0] } : { kind: "ambiguous" };
3135
+ }
3136
+ const continuableToolCalls = toolCalls.filter(
3137
+ (toolCall) => !toolCall.argumentState.hasCompleteStructuredValue
3138
+ );
3139
+ if (continuableToolCalls.length === 1) {
3140
+ return { kind: "existing", toolCall: continuableToolCalls[0] };
3141
+ }
3142
+ return continuableToolCalls.length > 1 ? { kind: "ambiguous" } : { kind: "new" };
3143
+ }
3144
+ processNewToolCall(toolCallDelta, {
3145
+ wireId,
3146
+ index,
3147
+ name: name2
3148
+ }) {
3149
+ var _a2, _b2, _c, _d, _e;
3150
+ if (this.typeValidation === "required") {
3151
+ if (toolCallDelta.type !== "function") {
3152
+ throw new InvalidResponseDataError({
3153
+ data: toolCallDelta,
3154
+ message: `Expected 'function' type.`
3155
+ });
3156
+ }
3157
+ } else if (this.typeValidation === "if-present") {
3158
+ if (toolCallDelta.type != null && toolCallDelta.type !== "function") {
3159
+ throw new InvalidResponseDataError({
3160
+ data: toolCallDelta,
3161
+ message: `Expected 'function' type.`
3162
+ });
3163
+ }
3164
+ }
3165
+ if (name2 == null) {
3166
+ throw new InvalidResponseDataError({
3167
+ data: toolCallDelta,
3168
+ message: `Expected 'function.name' to be a string.`
3169
+ });
3170
+ }
3171
+ const id = this.createToolCallId(wireId);
3172
+ this.controller.enqueue({
3173
+ type: "tool-input-start",
3174
+ id,
3175
+ toolName: name2
3176
+ });
3177
+ const toolCall = {
3178
+ id,
3179
+ index: index != null ? index : void 0,
3180
+ sequence: this.toolCalls.length,
3181
+ type: "function",
3182
+ function: {
3183
+ name: name2,
3184
+ arguments: (_b2 = (_a2 = toolCallDelta.function) == null ? void 0 : _a2.arguments) != null ? _b2 : ""
3185
+ },
3186
+ argumentState: new StreamingToolCallArgumentState(
3187
+ (_d = (_c = toolCallDelta.function) == null ? void 0 : _c.arguments) != null ? _d : ""
3188
+ ),
3189
+ hasFinished: false,
3190
+ metadata: (_e = this.extractMetadata) == null ? void 0 : _e.call(this, toolCallDelta)
3191
+ };
3192
+ this.toolCalls.push(toolCall);
3193
+ if (wireId != null) {
3194
+ this.associateWireId(toolCall, wireId);
3195
+ }
3196
+ if (toolCall.function.arguments.length > 0) {
3197
+ this.controller.enqueue({
3198
+ type: "tool-input-delta",
3199
+ id: toolCall.id,
3200
+ delta: toolCall.function.arguments
3201
+ });
3202
+ }
3203
+ return toolCall;
3204
+ }
3205
+ associateWireId(toolCall, wireId) {
3206
+ let toolCallsWithId = this.toolCallsById.get(wireId);
3207
+ if (toolCallsWithId == null) {
3208
+ toolCallsWithId = /* @__PURE__ */ new Set();
3209
+ this.toolCallsById.set(wireId, toolCallsWithId);
3210
+ }
3211
+ toolCallsWithId.add(toolCall);
3212
+ }
3213
+ associateIndex(toolCall, index) {
3214
+ let toolCallsWithIndex = this.toolCallsByIndex.get(index);
3215
+ if (toolCallsWithIndex == null) {
3216
+ toolCallsWithIndex = /* @__PURE__ */ new Set();
3217
+ this.toolCallsByIndex.set(index, toolCallsWithIndex);
3218
+ }
3219
+ toolCallsWithIndex.add(toolCall);
3220
+ }
3221
+ createToolCallId(wireId) {
3222
+ var _a2, _b2;
3223
+ if (wireId != null && !this.usedToolCallIds.has(wireId)) {
3224
+ this.usedToolCallIds.add(wireId);
3225
+ return wireId;
3226
+ }
3227
+ const generatedId = (_a2 = this.getNonBlankString(this._generateId())) != null ? _a2 : "tool-call";
3228
+ if (!this.usedToolCallIds.has(generatedId)) {
3229
+ this.usedToolCallIds.add(generatedId);
3230
+ return generatedId;
3231
+ }
3232
+ const initialSuffix = (_b2 = this.nextGeneratedIdSuffixes.get(generatedId)) != null ? _b2 : 1;
3233
+ const maximumSuffix = initialSuffix + this.usedToolCallIds.size;
3234
+ for (let suffix = initialSuffix; suffix <= maximumSuffix; suffix++) {
3235
+ const suffixedId = `${generatedId}-${suffix}`;
3236
+ if (!this.usedToolCallIds.has(suffixedId)) {
3237
+ this.usedToolCallIds.add(suffixedId);
3238
+ this.nextGeneratedIdSuffixes.set(generatedId, suffix + 1);
3239
+ return suffixedId;
3240
+ }
3241
+ }
3242
+ throw new Error("Failed to create a unique tool call ID.");
3243
+ }
3244
+ getNonBlankString(value) {
3245
+ return value != null && value.trim().length > 0 ? value : void 0;
3246
+ }
3247
+ processExistingToolCall(toolCall, toolCallDelta) {
3248
+ var _a2;
3249
+ if (!toolCall.hasFinished && ((_a2 = toolCallDelta.function) == null ? void 0 : _a2.arguments) != null) {
3250
+ toolCall.argumentState.append(toolCallDelta.function.arguments);
3251
+ toolCall.function.arguments += toolCallDelta.function.arguments;
3252
+ this.controller.enqueue({
3253
+ type: "tool-input-delta",
3254
+ id: toolCall.id,
3255
+ delta: toolCallDelta.function.arguments
3256
+ });
3257
+ }
3258
+ }
3259
+ finishToolCall(toolCall) {
3260
+ var _a2;
3261
+ this.controller.enqueue({
3262
+ type: "tool-input-end",
3263
+ id: toolCall.id
3264
+ });
3265
+ const providerMetadata = (_a2 = this.buildToolCallProviderMetadata) == null ? void 0 : _a2.call(
3266
+ this,
3267
+ toolCall.metadata
3268
+ );
3269
+ this.controller.enqueue({
3270
+ type: "tool-call",
3271
+ toolCallId: toolCall.id,
3272
+ toolName: toolCall.function.name,
3273
+ input: toolCall.function.arguments,
3274
+ ...providerMetadata ? { providerMetadata } : {}
3275
+ });
3276
+ toolCall.hasFinished = true;
3277
+ }
3278
+ };
3279
+
2902
3280
  // src/uint8-utils.ts
2903
3281
  var { btoa, atob } = globalThis;
2904
3282
  function convertBase64ToUint8Array(base64String) {
@@ -2958,6 +3336,7 @@ export {
2958
3336
  DownloadError,
2959
3337
  EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL as EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL,
2960
3338
  EventSourceParserStream2 as EventSourceParserStream,
3339
+ StreamingToolCallTracker,
2961
3340
  VERSION,
2962
3341
  asSchema,
2963
3342
  asValidator,
@@ -2980,6 +3359,7 @@ export {
2980
3359
  dynamicTool,
2981
3360
  executeTool,
2982
3361
  extractResponseHeaders,
3362
+ fetchWithValidatedEndpoint,
2983
3363
  fetchWithValidatedRedirects,
2984
3364
  generateId,
2985
3365
  getErrorMessage,