@ai-sdk/provider-utils 4.0.55 → 4.0.57

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
@@ -248,6 +248,15 @@ function isBrowserRuntime(globalThisAny = globalThis) {
248
248
  return globalThisAny.window != null;
249
249
  }
250
250
 
251
+ // src/is-same-origin.ts
252
+ function isSameOrigin(url, baseUrl) {
253
+ try {
254
+ return new URL(url).origin === new URL(baseUrl).origin;
255
+ } catch (e) {
256
+ return false;
257
+ }
258
+ }
259
+
251
260
  // src/validate-download-url.ts
252
261
  function validateDownloadUrl(url) {
253
262
  let parsed;
@@ -433,34 +442,24 @@ function createSafeLookup(lookup) {
433
442
  });
434
443
  }
435
444
  var safeNodeFetchPromise;
436
- var initialGlobalFetch = globalThis.fetch;
437
- var initialGlobalFetchIsNodeDefault = isNodeDefaultFetch(initialGlobalFetch);
438
445
  function isNodeRuntime() {
439
- var _a2, _b2;
446
+ var _a2, _b2, _c;
440
447
  const runtimeProcess = globalThis.process;
441
- return ((_a2 = runtimeProcess == null ? void 0 : runtimeProcess.release) == null ? void 0 : _a2.name) === "node" && ((_b2 = runtimeProcess.versions) == null ? void 0 : _b2.bun) == null;
448
+ 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;
442
449
  }
443
450
  async function getDefaultDownloadFetch() {
444
- if (!isNodeRuntime() || !initialGlobalFetchIsNodeDefault || globalThis.fetch !== initialGlobalFetch) {
451
+ if (!isNodeRuntime()) {
445
452
  return globalThis.fetch;
446
453
  }
447
454
  return safeNodeFetchPromise != null ? safeNodeFetchPromise : safeNodeFetchPromise = createSafeNodeFetch();
448
455
  }
449
- function isNodeDefaultFetch(fetch) {
450
- if (typeof fetch !== "function") {
451
- return false;
452
- }
453
- const source = Function.prototype.toString.call(fetch);
454
- return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
455
- }
456
456
  async function createSafeNodeFetch() {
457
- const [{ createRequire }, { lookup }] = await Promise.all([
457
+ const [module, { lookup }] = await Promise.all([
458
458
  loadNodeModule("node:module"),
459
459
  loadNodeModule("node:dns")
460
460
  ]);
461
- const { Agent, fetch } = createRequire(getCurrentModulePath())(
462
- "undici"
463
- );
461
+ const nodeRequire = module.createRequire(getCurrentModulePath());
462
+ const { Agent, fetch } = nodeRequire("undici");
464
463
  const dispatcher = new Agent({
465
464
  connect: {
466
465
  lookup: createSafeLookup(lookup)
@@ -502,20 +501,47 @@ function getCurrentModulePath() {
502
501
 
503
502
  // src/fetch-with-validated-redirects.ts
504
503
  var MAX_DOWNLOAD_REDIRECTS = 10;
504
+ async function getValidatedFetch(customFetch) {
505
+ return customFetch == null || customFetch === globalThis.fetch ? await getDefaultDownloadFetch() : customFetch;
506
+ }
507
+ async function fetchWithValidatedEndpoint({
508
+ url,
509
+ init,
510
+ fetch: customFetch,
511
+ trustedOrigin,
512
+ redirect = "error"
513
+ }) {
514
+ const urlText = url.toString();
515
+ const isTrusted = trustedOrigin !== void 0 && isSameOrigin(urlText, trustedOrigin);
516
+ if (!isTrusted) {
517
+ validateDownloadUrl(urlText);
518
+ }
519
+ const fetch = isTrusted && customFetch != null ? customFetch : isTrusted ? globalThis.fetch : await getValidatedFetch(customFetch);
520
+ return await fetch(url, {
521
+ ...init,
522
+ redirect
523
+ });
524
+ }
505
525
  async function fetchWithValidatedRedirects({
506
526
  url,
507
527
  headers,
508
528
  abortSignal,
509
- maxRedirects = MAX_DOWNLOAD_REDIRECTS
529
+ maxRedirects = MAX_DOWNLOAD_REDIRECTS,
530
+ fetch: customFetch,
531
+ trustedOrigin
510
532
  }) {
533
+ var _a2;
511
534
  const baseInit = { signal: abortSignal };
512
535
  if (headers !== void 0) {
513
536
  baseInit.headers = headers;
514
537
  }
515
538
  let currentUrl = url;
516
539
  for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
517
- validateDownloadUrl(currentUrl);
518
- const fetch = await getDefaultDownloadFetch();
540
+ const isTrustedHop = trustedOrigin !== void 0 && isSameOrigin(currentUrl, trustedOrigin);
541
+ if (!isTrustedHop) {
542
+ validateDownloadUrl(currentUrl);
543
+ }
544
+ const fetch = isTrustedHop && customFetch != null ? customFetch : isTrustedHop ? globalThis.fetch : await getValidatedFetch(customFetch);
519
545
  const response = await fetch(currentUrl, {
520
546
  ...baseInit,
521
547
  redirect: "manual"
@@ -529,7 +555,7 @@ async function fetchWithValidatedRedirects({
529
555
  }
530
556
  return await fetch(currentUrl, { ...baseInit, redirect: "follow" });
531
557
  }
532
- const location = response.headers.get("location");
558
+ const location = (_a2 = response.headers) == null ? void 0 : _a2.get("location");
533
559
  if (response.status >= 300 && response.status < 400 && location) {
534
560
  await cancelResponseBody(response);
535
561
  currentUrl = new URL(location, currentUrl).toString();
@@ -822,7 +848,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
822
848
  }
823
849
 
824
850
  // src/version.ts
825
- var VERSION = true ? "4.0.55" : "0.0.0-test";
851
+ var VERSION = true ? "4.0.57" : "0.0.0-test";
826
852
 
827
853
  // src/get-from-api.ts
828
854
  var getOriginalFetch = () => globalThis.fetch;
@@ -938,15 +964,6 @@ function isNonNullable(value) {
938
964
  return value != null;
939
965
  }
940
966
 
941
- // src/is-same-origin.ts
942
- function isSameOrigin(url, baseUrl) {
943
- try {
944
- return new URL(url).origin === new URL(baseUrl).origin;
945
- } catch (e) {
946
- return false;
947
- }
948
- }
949
-
950
967
  // src/is-url-supported.ts
951
968
  function isUrlSupported({
952
969
  mediaType,
@@ -3078,6 +3095,367 @@ var createStatusCodeErrorResponseHandler = () => async ({ response, url, request
3078
3095
  };
3079
3096
  };
3080
3097
 
3098
+ // src/streaming-tool-call-tracker.ts
3099
+ import {
3100
+ InvalidResponseDataError
3101
+ } from "@ai-sdk/provider";
3102
+
3103
+ // src/streaming-tool-call-argument-state.ts
3104
+ function startsWithStructuredValue(value) {
3105
+ if (typeof value !== "string") {
3106
+ return false;
3107
+ }
3108
+ const firstCharacter = value.trimStart()[0];
3109
+ return firstCharacter === "{" || firstCharacter === "[";
3110
+ }
3111
+ var StreamingToolCallArgumentState = class {
3112
+ constructor(initialValue = "") {
3113
+ this.structure = { kind: "undetermined" };
3114
+ this.append(initialValue);
3115
+ }
3116
+ get hasCompleteStructuredValue() {
3117
+ return this.structure.kind === "structured" && this.structure.complete === true;
3118
+ }
3119
+ append(delta) {
3120
+ let nextStructure = this.structure;
3121
+ for (const character of delta) {
3122
+ if (nextStructure.kind === "undetermined") {
3123
+ if (/\s/.test(character)) {
3124
+ continue;
3125
+ }
3126
+ if (character !== "{" && character !== "[") {
3127
+ nextStructure = { kind: "other" };
3128
+ continue;
3129
+ }
3130
+ nextStructure = {
3131
+ kind: "structured",
3132
+ stack: [character],
3133
+ inString: false,
3134
+ escaped: false,
3135
+ complete: false
3136
+ };
3137
+ continue;
3138
+ }
3139
+ if (nextStructure.kind !== "structured" || nextStructure.complete) {
3140
+ continue;
3141
+ }
3142
+ if (nextStructure.inString) {
3143
+ if (nextStructure.escaped) {
3144
+ nextStructure.escaped = false;
3145
+ } else if (character === "\\") {
3146
+ nextStructure.escaped = true;
3147
+ } else if (character === '"') {
3148
+ nextStructure.inString = false;
3149
+ }
3150
+ continue;
3151
+ }
3152
+ if (character === '"') {
3153
+ nextStructure.inString = true;
3154
+ } else if (character === "{" || character === "[") {
3155
+ nextStructure.stack.push(character);
3156
+ } else if (character === "}" || character === "]") {
3157
+ const expectedOpening = character === "}" ? "{" : "[";
3158
+ if (nextStructure.stack[nextStructure.stack.length - 1] !== expectedOpening) {
3159
+ nextStructure = { kind: "other" };
3160
+ continue;
3161
+ }
3162
+ nextStructure.stack.pop();
3163
+ if (nextStructure.stack.length === 0) {
3164
+ nextStructure.complete = true;
3165
+ }
3166
+ }
3167
+ }
3168
+ this.structure = nextStructure;
3169
+ }
3170
+ };
3171
+
3172
+ // src/streaming-tool-call-tracker.ts
3173
+ var StreamingToolCallTracker = class {
3174
+ constructor(controller, options = {}) {
3175
+ this.toolCalls = [];
3176
+ this.toolCallsById = /* @__PURE__ */ new Map();
3177
+ this.toolCallsByIndex = /* @__PURE__ */ new Map();
3178
+ this.usedToolCallIds = /* @__PURE__ */ new Set();
3179
+ this.nextGeneratedIdSuffixes = /* @__PURE__ */ new Map();
3180
+ var _a2, _b2;
3181
+ this.controller = controller;
3182
+ this._generateId = (_a2 = options.generateId) != null ? _a2 : generateId;
3183
+ this.typeValidation = (_b2 = options.typeValidation) != null ? _b2 : "none";
3184
+ this.extractMetadata = options.extractMetadata;
3185
+ this.buildToolCallProviderMetadata = options.buildToolCallProviderMetadata;
3186
+ }
3187
+ processDelta(toolCallDelta) {
3188
+ var _a2, _b2;
3189
+ const wireName = (_a2 = toolCallDelta.function) == null ? void 0 : _a2.name;
3190
+ const hasBlankName = typeof wireName === "string" && wireName.trim().length === 0;
3191
+ const wireId = this.getNonBlankString(toolCallDelta.id);
3192
+ const name2 = this.getNonBlankString(wireName);
3193
+ const { index } = toolCallDelta;
3194
+ const resolution = this.resolveToolCall({
3195
+ wireId,
3196
+ index,
3197
+ name: name2,
3198
+ hasExplicitCallStart: name2 != null && startsWithStructuredValue((_b2 = toolCallDelta.function) == null ? void 0 : _b2.arguments)
3199
+ });
3200
+ if (resolution.kind === "ambiguous") {
3201
+ return;
3202
+ }
3203
+ let toolCall;
3204
+ if (resolution.kind === "new") {
3205
+ if (hasBlankName) {
3206
+ return;
3207
+ }
3208
+ toolCall = this.processNewToolCall(toolCallDelta, {
3209
+ wireId,
3210
+ index,
3211
+ name: name2
3212
+ });
3213
+ } else {
3214
+ toolCall = resolution.toolCall;
3215
+ if (wireId != null) {
3216
+ this.associateWireId(toolCall, wireId);
3217
+ }
3218
+ this.processExistingToolCall(toolCall, toolCallDelta);
3219
+ }
3220
+ if (index != null) {
3221
+ this.associateIndex(toolCall, index);
3222
+ }
3223
+ }
3224
+ flush() {
3225
+ const toolCalls = this.toolCalls.every((toolCall) => toolCall.index != null) ? [...this.toolCalls].sort(
3226
+ (a, b) => a.index - b.index || a.sequence - b.sequence
3227
+ ) : this.toolCalls;
3228
+ for (const toolCall of toolCalls) {
3229
+ if (!toolCall.hasFinished) {
3230
+ this.finishToolCall(toolCall);
3231
+ }
3232
+ }
3233
+ }
3234
+ resolveToolCall({
3235
+ wireId,
3236
+ index,
3237
+ name: name2,
3238
+ hasExplicitCallStart
3239
+ }) {
3240
+ const indexedToolCalls = index != null ? this.toolCallsByIndex.get(index) : void 0;
3241
+ const matchingIndexedToolCalls = this.filterToolCallsByName(
3242
+ indexedToolCalls,
3243
+ name2
3244
+ );
3245
+ if (wireId != null) {
3246
+ const toolCallsWithId = this.toolCallsById.get(wireId);
3247
+ if (toolCallsWithId != null) {
3248
+ if (index != null) {
3249
+ const matchingToolCalls = matchingIndexedToolCalls.filter(
3250
+ (toolCall) => toolCallsWithId.has(toolCall)
3251
+ );
3252
+ const matchingToolCall = this.resolveMatchingToolCall(
3253
+ matchingToolCalls,
3254
+ hasExplicitCallStart
3255
+ );
3256
+ if (matchingToolCall.kind !== "new") {
3257
+ return matchingToolCall;
3258
+ }
3259
+ if (name2 != null) {
3260
+ return { kind: "new" };
3261
+ }
3262
+ if (indexedToolCalls != null) {
3263
+ return { kind: "ambiguous" };
3264
+ }
3265
+ return this.resolveMatchingToolCall([...toolCallsWithId], false);
3266
+ }
3267
+ if (name2 != null) {
3268
+ const matchingToolCalls = [...toolCallsWithId].filter(
3269
+ (toolCall) => toolCall.function.name === name2
3270
+ );
3271
+ return this.resolveMatchingToolCall(
3272
+ matchingToolCalls,
3273
+ hasExplicitCallStart
3274
+ );
3275
+ }
3276
+ return this.resolveMatchingToolCall([...toolCallsWithId], false);
3277
+ }
3278
+ if (matchingIndexedToolCalls.length > 0) {
3279
+ return hasExplicitCallStart ? { kind: "new" } : this.resolveMatchingToolCall(matchingIndexedToolCalls, false);
3280
+ }
3281
+ return { kind: "new" };
3282
+ }
3283
+ if (indexedToolCalls != null) {
3284
+ return this.resolveMatchingToolCall(
3285
+ matchingIndexedToolCalls,
3286
+ hasExplicitCallStart
3287
+ );
3288
+ }
3289
+ if (name2 != null) {
3290
+ return { kind: "new" };
3291
+ }
3292
+ const unfinishedToolCalls = this.toolCalls.filter(
3293
+ (toolCall) => !toolCall.hasFinished
3294
+ );
3295
+ if (unfinishedToolCalls.length === 1) {
3296
+ return { kind: "existing", toolCall: unfinishedToolCalls[0] };
3297
+ }
3298
+ return unfinishedToolCalls.length > 1 ? { kind: "ambiguous" } : { kind: "new" };
3299
+ }
3300
+ filterToolCallsByName(toolCalls, name2) {
3301
+ if (toolCalls == null) {
3302
+ return [];
3303
+ }
3304
+ return [...toolCalls].filter(
3305
+ (toolCall) => name2 == null || toolCall.function.name === name2
3306
+ );
3307
+ }
3308
+ resolveMatchingToolCall(toolCalls, hasExplicitCallStart) {
3309
+ if (toolCalls.length === 0) {
3310
+ return { kind: "new" };
3311
+ }
3312
+ if (!hasExplicitCallStart) {
3313
+ return toolCalls.length === 1 ? { kind: "existing", toolCall: toolCalls[0] } : { kind: "ambiguous" };
3314
+ }
3315
+ const continuableToolCalls = toolCalls.filter(
3316
+ (toolCall) => !toolCall.argumentState.hasCompleteStructuredValue
3317
+ );
3318
+ if (continuableToolCalls.length === 1) {
3319
+ return { kind: "existing", toolCall: continuableToolCalls[0] };
3320
+ }
3321
+ return continuableToolCalls.length > 1 ? { kind: "ambiguous" } : { kind: "new" };
3322
+ }
3323
+ processNewToolCall(toolCallDelta, {
3324
+ wireId,
3325
+ index,
3326
+ name: name2
3327
+ }) {
3328
+ var _a2, _b2, _c, _d, _e;
3329
+ if (this.typeValidation === "required") {
3330
+ if (toolCallDelta.type !== "function") {
3331
+ throw new InvalidResponseDataError({
3332
+ data: toolCallDelta,
3333
+ message: `Expected 'function' type.`
3334
+ });
3335
+ }
3336
+ } else if (this.typeValidation === "if-present") {
3337
+ if (toolCallDelta.type != null && toolCallDelta.type !== "function") {
3338
+ throw new InvalidResponseDataError({
3339
+ data: toolCallDelta,
3340
+ message: `Expected 'function' type.`
3341
+ });
3342
+ }
3343
+ }
3344
+ if (name2 == null) {
3345
+ throw new InvalidResponseDataError({
3346
+ data: toolCallDelta,
3347
+ message: `Expected 'function.name' to be a string.`
3348
+ });
3349
+ }
3350
+ const id = this.createToolCallId(wireId);
3351
+ this.controller.enqueue({
3352
+ type: "tool-input-start",
3353
+ id,
3354
+ toolName: name2
3355
+ });
3356
+ const toolCall = {
3357
+ id,
3358
+ index: index != null ? index : void 0,
3359
+ sequence: this.toolCalls.length,
3360
+ type: "function",
3361
+ function: {
3362
+ name: name2,
3363
+ arguments: (_b2 = (_a2 = toolCallDelta.function) == null ? void 0 : _a2.arguments) != null ? _b2 : ""
3364
+ },
3365
+ argumentState: new StreamingToolCallArgumentState(
3366
+ (_d = (_c = toolCallDelta.function) == null ? void 0 : _c.arguments) != null ? _d : ""
3367
+ ),
3368
+ hasFinished: false,
3369
+ metadata: (_e = this.extractMetadata) == null ? void 0 : _e.call(this, toolCallDelta)
3370
+ };
3371
+ this.toolCalls.push(toolCall);
3372
+ if (wireId != null) {
3373
+ this.associateWireId(toolCall, wireId);
3374
+ }
3375
+ if (toolCall.function.arguments.length > 0) {
3376
+ this.controller.enqueue({
3377
+ type: "tool-input-delta",
3378
+ id: toolCall.id,
3379
+ delta: toolCall.function.arguments
3380
+ });
3381
+ }
3382
+ return toolCall;
3383
+ }
3384
+ associateWireId(toolCall, wireId) {
3385
+ let toolCallsWithId = this.toolCallsById.get(wireId);
3386
+ if (toolCallsWithId == null) {
3387
+ toolCallsWithId = /* @__PURE__ */ new Set();
3388
+ this.toolCallsById.set(wireId, toolCallsWithId);
3389
+ }
3390
+ toolCallsWithId.add(toolCall);
3391
+ }
3392
+ associateIndex(toolCall, index) {
3393
+ let toolCallsWithIndex = this.toolCallsByIndex.get(index);
3394
+ if (toolCallsWithIndex == null) {
3395
+ toolCallsWithIndex = /* @__PURE__ */ new Set();
3396
+ this.toolCallsByIndex.set(index, toolCallsWithIndex);
3397
+ }
3398
+ toolCallsWithIndex.add(toolCall);
3399
+ }
3400
+ createToolCallId(wireId) {
3401
+ var _a2, _b2;
3402
+ if (wireId != null && !this.usedToolCallIds.has(wireId)) {
3403
+ this.usedToolCallIds.add(wireId);
3404
+ return wireId;
3405
+ }
3406
+ const generatedId = (_a2 = this.getNonBlankString(this._generateId())) != null ? _a2 : "tool-call";
3407
+ if (!this.usedToolCallIds.has(generatedId)) {
3408
+ this.usedToolCallIds.add(generatedId);
3409
+ return generatedId;
3410
+ }
3411
+ const initialSuffix = (_b2 = this.nextGeneratedIdSuffixes.get(generatedId)) != null ? _b2 : 1;
3412
+ const maximumSuffix = initialSuffix + this.usedToolCallIds.size;
3413
+ for (let suffix = initialSuffix; suffix <= maximumSuffix; suffix++) {
3414
+ const suffixedId = `${generatedId}-${suffix}`;
3415
+ if (!this.usedToolCallIds.has(suffixedId)) {
3416
+ this.usedToolCallIds.add(suffixedId);
3417
+ this.nextGeneratedIdSuffixes.set(generatedId, suffix + 1);
3418
+ return suffixedId;
3419
+ }
3420
+ }
3421
+ throw new Error("Failed to create a unique tool call ID.");
3422
+ }
3423
+ getNonBlankString(value) {
3424
+ return value != null && value.trim().length > 0 ? value : void 0;
3425
+ }
3426
+ processExistingToolCall(toolCall, toolCallDelta) {
3427
+ var _a2;
3428
+ if (!toolCall.hasFinished && ((_a2 = toolCallDelta.function) == null ? void 0 : _a2.arguments) != null) {
3429
+ toolCall.argumentState.append(toolCallDelta.function.arguments);
3430
+ toolCall.function.arguments += toolCallDelta.function.arguments;
3431
+ this.controller.enqueue({
3432
+ type: "tool-input-delta",
3433
+ id: toolCall.id,
3434
+ delta: toolCallDelta.function.arguments
3435
+ });
3436
+ }
3437
+ }
3438
+ finishToolCall(toolCall) {
3439
+ var _a2;
3440
+ this.controller.enqueue({
3441
+ type: "tool-input-end",
3442
+ id: toolCall.id
3443
+ });
3444
+ const providerMetadata = (_a2 = this.buildToolCallProviderMetadata) == null ? void 0 : _a2.call(
3445
+ this,
3446
+ toolCall.metadata
3447
+ );
3448
+ this.controller.enqueue({
3449
+ type: "tool-call",
3450
+ toolCallId: toolCall.id,
3451
+ toolName: toolCall.function.name,
3452
+ input: toolCall.function.arguments,
3453
+ ...providerMetadata ? { providerMetadata } : {}
3454
+ });
3455
+ toolCall.hasFinished = true;
3456
+ }
3457
+ };
3458
+
3081
3459
  // src/strip-file-extension.ts
3082
3460
  function stripFileExtension(filename) {
3083
3461
  const firstDotIndex = filename.indexOf(".");
@@ -3124,6 +3502,7 @@ export {
3124
3502
  EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL as EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL,
3125
3503
  EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER as EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER,
3126
3504
  EventSourceParserStream2 as EventSourceParserStream,
3505
+ StreamingToolCallTracker,
3127
3506
  VERSION,
3128
3507
  asSchema,
3129
3508
  cancelResponseBody,
@@ -3148,6 +3527,7 @@ export {
3148
3527
  dynamicTool,
3149
3528
  executeTool,
3150
3529
  extractResponseHeaders,
3530
+ fetchWithValidatedEndpoint,
3151
3531
  fetchWithValidatedRedirects,
3152
3532
  generateId,
3153
3533
  getErrorMessage,