@ai-sdk/provider-utils 3.0.24 → 3.0.26

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
@@ -154,6 +154,191 @@ var DownloadError = class extends (_b = AISDKError, _a = symbol, _b) {
154
154
  }
155
155
  };
156
156
 
157
+ // src/is-browser-runtime.ts
158
+ function isBrowserRuntime(globalThisAny = globalThis) {
159
+ return globalThisAny.window != null;
160
+ }
161
+
162
+ // src/validate-download-url.ts
163
+ function validateDownloadUrl(url) {
164
+ let parsed;
165
+ try {
166
+ parsed = new URL(url);
167
+ } catch (e) {
168
+ throw new DownloadError({
169
+ url,
170
+ message: `Invalid URL: ${url}`
171
+ });
172
+ }
173
+ if (parsed.protocol === "data:") {
174
+ return;
175
+ }
176
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
177
+ throw new DownloadError({
178
+ url,
179
+ message: `URL scheme must be http, https, or data, got ${parsed.protocol}`
180
+ });
181
+ }
182
+ const hostname = parsed.hostname.toLowerCase().replace(/\.+$/, "");
183
+ if (!hostname) {
184
+ throw new DownloadError({
185
+ url,
186
+ message: `URL must have a hostname`
187
+ });
188
+ }
189
+ if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost")) {
190
+ throw new DownloadError({
191
+ url,
192
+ message: `URL with hostname ${hostname} is not allowed`
193
+ });
194
+ }
195
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
196
+ const ipv6 = hostname.slice(1, -1);
197
+ if (isPrivateIPv6(ipv6)) {
198
+ throw new DownloadError({
199
+ url,
200
+ message: `URL with IPv6 address ${hostname} is not allowed`
201
+ });
202
+ }
203
+ return;
204
+ }
205
+ if (isIPv4(hostname)) {
206
+ if (isPrivateIPv4(hostname)) {
207
+ throw new DownloadError({
208
+ url,
209
+ message: `URL with IP address ${hostname} is not allowed`
210
+ });
211
+ }
212
+ return;
213
+ }
214
+ }
215
+ function isIPv4(hostname) {
216
+ const parts = hostname.split(".");
217
+ if (parts.length !== 4) return false;
218
+ return parts.every((part) => {
219
+ const num = Number(part);
220
+ return Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part;
221
+ });
222
+ }
223
+ function isPrivateIPv4(ip) {
224
+ const parts = ip.split(".").map(Number);
225
+ const [a, b, c] = parts;
226
+ if (a === 0) return true;
227
+ if (a === 10) return true;
228
+ if (a === 100 && b >= 64 && b <= 127) return true;
229
+ if (a === 127) return true;
230
+ if (a === 169 && b === 254) return true;
231
+ if (a === 172 && b >= 16 && b <= 31) return true;
232
+ if (a === 192 && b === 0 && c === 0) return true;
233
+ if (a === 192 && b === 168) return true;
234
+ if (a === 198 && (b === 18 || b === 19)) return true;
235
+ if (a >= 240) return true;
236
+ return false;
237
+ }
238
+ function parseIPv6(ip) {
239
+ let address = ip.toLowerCase();
240
+ const zoneIndex = address.indexOf("%");
241
+ if (zoneIndex !== -1) {
242
+ address = address.slice(0, zoneIndex);
243
+ }
244
+ const halves = address.split("::");
245
+ if (halves.length > 2) return null;
246
+ const toGroups = (segment) => {
247
+ if (segment === "") return [];
248
+ const groups = [];
249
+ const parts = segment.split(":");
250
+ for (let i = 0; i < parts.length; i++) {
251
+ const part = parts[i];
252
+ if (part.includes(".")) {
253
+ if (i !== parts.length - 1 || !isIPv4(part)) return null;
254
+ const [a, b, c, d] = part.split(".").map(Number);
255
+ groups.push(a << 8 | b, c << 8 | d);
256
+ continue;
257
+ }
258
+ if (!/^[0-9a-f]{1,4}$/.test(part)) return null;
259
+ groups.push(parseInt(part, 16));
260
+ }
261
+ return groups;
262
+ };
263
+ const head = toGroups(halves[0]);
264
+ if (head === null) return null;
265
+ if (halves.length === 2) {
266
+ const tail = toGroups(halves[1]);
267
+ if (tail === null) return null;
268
+ const fill = 8 - head.length - tail.length;
269
+ if (fill < 0) return null;
270
+ return [...head, ...new Array(fill).fill(0), ...tail];
271
+ }
272
+ return head.length === 8 ? head : null;
273
+ }
274
+ function isPrivateIPv6(ip) {
275
+ const groups = parseIPv6(ip);
276
+ if (groups === null) return true;
277
+ const topZero = (count) => groups.slice(0, count).every((group) => group === 0);
278
+ if (topZero(7) && (groups[7] === 0 || groups[7] === 1)) return true;
279
+ if ((groups[0] & 65024) === 64512) return true;
280
+ if ((groups[0] & 65472) === 65152) return true;
281
+ if ((groups[0] & 65472) === 65216) return true;
282
+ if ((groups[0] & 65280) === 65280) return true;
283
+ const embedsIPv4 = (
284
+ // ::/96 — IPv4-compatible (deprecated)
285
+ topZero(6) || // ::ffff:0:0/96 — IPv4-mapped (ffff in group 5)
286
+ topZero(5) && groups[5] === 65535 || // ::ffff:0:0/96 — IPv4-translated form (ffff in group 4, group 5 zero)
287
+ topZero(4) && groups[4] === 65535 && groups[5] === 0 || // 64:ff9b::/96 — NAT64 well-known prefix
288
+ groups[0] === 100 && groups[1] === 65435 && groups[2] === 0 && groups[3] === 0 && groups[4] === 0 && groups[5] === 0 || // 64:ff9b:1::/48 — NAT64 local-use prefix
289
+ groups[0] === 100 && groups[1] === 65435 && groups[2] === 1
290
+ );
291
+ if (embedsIPv4) {
292
+ const a = groups[6] >> 8 & 255;
293
+ const b = groups[6] & 255;
294
+ const c = groups[7] >> 8 & 255;
295
+ const d = groups[7] & 255;
296
+ return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
297
+ }
298
+ return false;
299
+ }
300
+
301
+ // src/fetch-with-validated-redirects.ts
302
+ var MAX_DOWNLOAD_REDIRECTS = 10;
303
+ async function fetchWithValidatedRedirects({
304
+ url,
305
+ headers,
306
+ abortSignal,
307
+ maxRedirects = MAX_DOWNLOAD_REDIRECTS
308
+ }) {
309
+ const baseInit = { signal: abortSignal };
310
+ if (headers !== void 0) {
311
+ baseInit.headers = headers;
312
+ }
313
+ let currentUrl = url;
314
+ for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
315
+ validateDownloadUrl(currentUrl);
316
+ const response = await fetch(currentUrl, {
317
+ ...baseInit,
318
+ redirect: "manual"
319
+ });
320
+ if (response.type === "opaqueredirect") {
321
+ if (!isBrowserRuntime()) {
322
+ throw new DownloadError({
323
+ url,
324
+ message: `Redirect from ${currentUrl} could not be validated and was blocked`
325
+ });
326
+ }
327
+ return await fetch(currentUrl, { ...baseInit, redirect: "follow" });
328
+ }
329
+ const location = response.headers.get("location");
330
+ if (response.status >= 300 && response.status < 400 && location) {
331
+ currentUrl = new URL(location, currentUrl).toString();
332
+ continue;
333
+ }
334
+ return response;
335
+ }
336
+ throw new DownloadError({
337
+ url,
338
+ message: `Too many redirects (max ${maxRedirects})`
339
+ });
340
+ }
341
+
157
342
  // src/read-response-with-size-limit.ts
158
343
  var DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024;
159
344
  async function readResponseWithSizeLimit({
@@ -343,7 +528,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
343
528
  }
344
529
 
345
530
  // src/version.ts
346
- var VERSION = true ? "3.0.24" : "0.0.0-test";
531
+ var VERSION = true ? "3.0.26" : "0.0.0-test";
347
532
 
348
533
  // src/get-from-api.ts
349
534
  var getOriginalFetch = () => globalThis.fetch;
@@ -353,10 +538,10 @@ var getFromApi = async ({
353
538
  successfulResponseHandler,
354
539
  failedResponseHandler,
355
540
  abortSignal,
356
- fetch = getOriginalFetch()
541
+ fetch: fetch2 = getOriginalFetch()
357
542
  }) => {
358
543
  try {
359
- const response = await fetch(url, {
544
+ const response = await fetch2(url, {
360
545
  method: "GET",
361
546
  headers: withUserAgentSuffix(
362
547
  headers,
@@ -454,6 +639,15 @@ function injectJsonInstructionIntoMessages({
454
639
  ];
455
640
  }
456
641
 
642
+ // src/is-same-origin.ts
643
+ function isSameOrigin(url, baseUrl) {
644
+ try {
645
+ return new URL(url).origin === new URL(baseUrl).origin;
646
+ } catch (e) {
647
+ return false;
648
+ }
649
+ }
650
+
457
651
  // src/is-url-supported.ts
458
652
  function isUrlSupported({
459
653
  mediaType,
@@ -798,7 +992,7 @@ var postJsonToApi = async ({
798
992
  failedResponseHandler,
799
993
  successfulResponseHandler,
800
994
  abortSignal,
801
- fetch
995
+ fetch: fetch2
802
996
  }) => postToApi({
803
997
  url,
804
998
  headers: {
@@ -812,7 +1006,7 @@ var postJsonToApi = async ({
812
1006
  failedResponseHandler,
813
1007
  successfulResponseHandler,
814
1008
  abortSignal,
815
- fetch
1009
+ fetch: fetch2
816
1010
  });
817
1011
  var postFormDataToApi = async ({
818
1012
  url,
@@ -821,7 +1015,7 @@ var postFormDataToApi = async ({
821
1015
  failedResponseHandler,
822
1016
  successfulResponseHandler,
823
1017
  abortSignal,
824
- fetch
1018
+ fetch: fetch2
825
1019
  }) => postToApi({
826
1020
  url,
827
1021
  headers,
@@ -832,7 +1026,7 @@ var postFormDataToApi = async ({
832
1026
  failedResponseHandler,
833
1027
  successfulResponseHandler,
834
1028
  abortSignal,
835
- fetch
1029
+ fetch: fetch2
836
1030
  });
837
1031
  var postToApi = async ({
838
1032
  url,
@@ -841,10 +1035,10 @@ var postToApi = async ({
841
1035
  successfulResponseHandler,
842
1036
  failedResponseHandler,
843
1037
  abortSignal,
844
- fetch = getOriginalFetch2()
1038
+ fetch: fetch2 = getOriginalFetch2()
845
1039
  }) => {
846
1040
  try {
847
- const response = await fetch(url, {
1041
+ const response = await fetch2(url, {
848
1042
  method: "POST",
849
1043
  headers: withUserAgentSuffix(
850
1044
  headers,
@@ -1149,6 +1343,35 @@ var createStatusCodeErrorResponseHandler = () => async ({ response, url, request
1149
1343
  };
1150
1344
  };
1151
1345
 
1346
+ // src/schema.ts
1347
+ var schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
1348
+ function lazySchema(createSchema) {
1349
+ let schema;
1350
+ return () => {
1351
+ if (schema == null) {
1352
+ schema = createSchema();
1353
+ }
1354
+ return schema;
1355
+ };
1356
+ }
1357
+ function jsonSchema(jsonSchema2, {
1358
+ validate
1359
+ } = {}) {
1360
+ return {
1361
+ [schemaSymbol]: true,
1362
+ _type: void 0,
1363
+ // should never be used directly
1364
+ [validatorSymbol]: true,
1365
+ get jsonSchema() {
1366
+ if (typeof jsonSchema2 === "function") {
1367
+ jsonSchema2 = jsonSchema2();
1368
+ }
1369
+ return jsonSchema2;
1370
+ },
1371
+ validate
1372
+ };
1373
+ }
1374
+
1152
1375
  // src/zod-schema.ts
1153
1376
  import * as z4 from "zod/v4";
1154
1377
 
@@ -1179,15 +1402,6 @@ function addAdditionalPropertiesToJsonSchema(jsonSchema2) {
1179
1402
  return jsonSchema2;
1180
1403
  }
1181
1404
 
1182
- // src/zod-to-json-schema/get-relative-path.ts
1183
- var getRelativePath = (pathA, pathB) => {
1184
- let i = 0;
1185
- for (; i < pathA.length && i < pathB.length; i++) {
1186
- if (pathA[i] !== pathB[i]) break;
1187
- }
1188
- return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
1189
- };
1190
-
1191
1405
  // src/zod-to-json-schema/options.ts
1192
1406
  var ignoreOverride = /* @__PURE__ */ Symbol(
1193
1407
  "Let zodToJsonSchema decide on which parser to use"
@@ -2221,6 +2435,15 @@ var selectParser = (def, typeName, refs) => {
2221
2435
  }
2222
2436
  };
2223
2437
 
2438
+ // src/zod-to-json-schema/get-relative-path.ts
2439
+ var getRelativePath = (pathA, pathB) => {
2440
+ let i = 0;
2441
+ for (; i < pathA.length && i < pathB.length; i++) {
2442
+ if (pathA[i] !== pathB[i]) break;
2443
+ }
2444
+ return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
2445
+ };
2446
+
2224
2447
  // src/zod-to-json-schema/parse-def.ts
2225
2448
  function parseDef(def, refs, forceResolution = false) {
2226
2449
  var _a2;
@@ -2410,34 +2633,7 @@ function zodSchema(zodSchema2, options) {
2410
2633
  }
2411
2634
  }
2412
2635
 
2413
- // src/schema.ts
2414
- var schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2415
- function lazySchema(createSchema) {
2416
- let schema;
2417
- return () => {
2418
- if (schema == null) {
2419
- schema = createSchema();
2420
- }
2421
- return schema;
2422
- };
2423
- }
2424
- function jsonSchema(jsonSchema2, {
2425
- validate
2426
- } = {}) {
2427
- return {
2428
- [schemaSymbol]: true,
2429
- _type: void 0,
2430
- // should never be used directly
2431
- [validatorSymbol]: true,
2432
- get jsonSchema() {
2433
- if (typeof jsonSchema2 === "function") {
2434
- jsonSchema2 = jsonSchema2();
2435
- }
2436
- return jsonSchema2;
2437
- },
2438
- validate
2439
- };
2440
- }
2636
+ // src/as-schema.ts
2441
2637
  function isSchema(value) {
2442
2638
  return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
2443
2639
  }
@@ -2466,105 +2662,6 @@ function convertToBase64(value) {
2466
2662
  return value instanceof Uint8Array ? convertUint8ArrayToBase64(value) : value;
2467
2663
  }
2468
2664
 
2469
- // src/validate-download-url.ts
2470
- function validateDownloadUrl(url) {
2471
- let parsed;
2472
- try {
2473
- parsed = new URL(url);
2474
- } catch (e) {
2475
- throw new DownloadError({
2476
- url,
2477
- message: `Invalid URL: ${url}`
2478
- });
2479
- }
2480
- if (parsed.protocol === "data:") {
2481
- return;
2482
- }
2483
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
2484
- throw new DownloadError({
2485
- url,
2486
- message: `URL scheme must be http, https, or data, got ${parsed.protocol}`
2487
- });
2488
- }
2489
- const hostname = parsed.hostname;
2490
- if (!hostname) {
2491
- throw new DownloadError({
2492
- url,
2493
- message: `URL must have a hostname`
2494
- });
2495
- }
2496
- if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost")) {
2497
- throw new DownloadError({
2498
- url,
2499
- message: `URL with hostname ${hostname} is not allowed`
2500
- });
2501
- }
2502
- if (hostname.startsWith("[") && hostname.endsWith("]")) {
2503
- const ipv6 = hostname.slice(1, -1);
2504
- if (isPrivateIPv6(ipv6)) {
2505
- throw new DownloadError({
2506
- url,
2507
- message: `URL with IPv6 address ${hostname} is not allowed`
2508
- });
2509
- }
2510
- return;
2511
- }
2512
- if (isIPv4(hostname)) {
2513
- if (isPrivateIPv4(hostname)) {
2514
- throw new DownloadError({
2515
- url,
2516
- message: `URL with IP address ${hostname} is not allowed`
2517
- });
2518
- }
2519
- return;
2520
- }
2521
- }
2522
- function isIPv4(hostname) {
2523
- const parts = hostname.split(".");
2524
- if (parts.length !== 4) return false;
2525
- return parts.every((part) => {
2526
- const num = Number(part);
2527
- return Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part;
2528
- });
2529
- }
2530
- function isPrivateIPv4(ip) {
2531
- const parts = ip.split(".").map(Number);
2532
- const [a, b] = parts;
2533
- if (a === 0) return true;
2534
- if (a === 10) return true;
2535
- if (a === 127) return true;
2536
- if (a === 169 && b === 254) return true;
2537
- if (a === 172 && b >= 16 && b <= 31) return true;
2538
- if (a === 192 && b === 168) return true;
2539
- return false;
2540
- }
2541
- function isPrivateIPv6(ip) {
2542
- const normalized = ip.toLowerCase();
2543
- if (normalized === "::1") return true;
2544
- if (normalized === "::") return true;
2545
- if (normalized.startsWith("::ffff:")) {
2546
- const mappedPart = normalized.slice(7);
2547
- if (isIPv4(mappedPart)) {
2548
- return isPrivateIPv4(mappedPart);
2549
- }
2550
- const hexParts = mappedPart.split(":");
2551
- if (hexParts.length === 2) {
2552
- const high = parseInt(hexParts[0], 16);
2553
- const low = parseInt(hexParts[1], 16);
2554
- if (!isNaN(high) && !isNaN(low)) {
2555
- const a = high >> 8 & 255;
2556
- const b = high & 255;
2557
- const c = low >> 8 & 255;
2558
- const d = low & 255;
2559
- return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
2560
- }
2561
- }
2562
- }
2563
- if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
2564
- if (normalized.startsWith("fe80")) return true;
2565
- return false;
2566
- }
2567
-
2568
2665
  // src/without-trailing-slash.ts
2569
2666
  function withoutTrailingSlash(url) {
2570
2667
  return url == null ? void 0 : url.replace(/\/$/, "");
@@ -2625,13 +2722,16 @@ export {
2625
2722
  dynamicTool,
2626
2723
  executeTool,
2627
2724
  extractResponseHeaders,
2725
+ fetchWithValidatedRedirects,
2628
2726
  generateId,
2629
2727
  getErrorMessage,
2630
2728
  getFromApi,
2631
2729
  getRuntimeEnvironmentUserAgent,
2632
2730
  injectJsonInstructionIntoMessages,
2633
2731
  isAbortError,
2732
+ isBrowserRuntime,
2634
2733
  isParsableJson,
2734
+ isSameOrigin,
2635
2735
  isUrlSupported,
2636
2736
  isValidator,
2637
2737
  jsonSchema,