@ai-sdk/provider-utils 5.0.0-beta.30 → 5.0.0-beta.49

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.js CHANGED
@@ -489,6 +489,15 @@ function isFullMediaType(mediaType) {
489
489
  return subtype.length > 0 && subtype !== "*";
490
490
  }
491
491
 
492
+ // src/cancel-response-body.ts
493
+ async function cancelResponseBody(response) {
494
+ var _a2;
495
+ try {
496
+ await ((_a2 = response.body) == null ? void 0 : _a2.cancel());
497
+ } catch (e) {
498
+ }
499
+ }
500
+
492
501
  // src/download-error.ts
493
502
  import { AISDKError } from "@ai-sdk/provider";
494
503
  var name = "AI_DownloadError";
@@ -514,59 +523,9 @@ var DownloadError = class extends (_b = AISDKError, _a = symbol, _b) {
514
523
  }
515
524
  };
516
525
 
517
- // src/read-response-with-size-limit.ts
518
- var DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024;
519
- async function readResponseWithSizeLimit({
520
- response,
521
- url,
522
- maxBytes = DEFAULT_MAX_DOWNLOAD_SIZE
523
- }) {
524
- const contentLength = response.headers.get("content-length");
525
- if (contentLength != null) {
526
- const length = parseInt(contentLength, 10);
527
- if (!isNaN(length) && length > maxBytes) {
528
- throw new DownloadError({
529
- url,
530
- message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes (Content-Length: ${length}).`
531
- });
532
- }
533
- }
534
- const body = response.body;
535
- if (body == null) {
536
- return new Uint8Array(0);
537
- }
538
- const reader = body.getReader();
539
- const chunks = [];
540
- let totalBytes = 0;
541
- try {
542
- while (true) {
543
- const { done, value } = await reader.read();
544
- if (done) {
545
- break;
546
- }
547
- totalBytes += value.length;
548
- if (totalBytes > maxBytes) {
549
- throw new DownloadError({
550
- url,
551
- message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes.`
552
- });
553
- }
554
- chunks.push(value);
555
- }
556
- } finally {
557
- try {
558
- await reader.cancel();
559
- } finally {
560
- reader.releaseLock();
561
- }
562
- }
563
- const result = new Uint8Array(totalBytes);
564
- let offset = 0;
565
- for (const chunk of chunks) {
566
- result.set(chunk, offset);
567
- offset += chunk.length;
568
- }
569
- return result;
526
+ // src/is-browser-runtime.ts
527
+ function isBrowserRuntime(globalThisAny = globalThis) {
528
+ return globalThisAny.window != null;
570
529
  }
571
530
 
572
531
  // src/validate-download-url.ts
@@ -589,7 +548,7 @@ function validateDownloadUrl(url) {
589
548
  message: `URL scheme must be http, https, or data, got ${parsed.protocol}`
590
549
  });
591
550
  }
592
- const hostname = parsed.hostname;
551
+ const hostname = parsed.hostname.toLowerCase().replace(/\.+$/, "");
593
552
  if (!hostname) {
594
553
  throw new DownloadError({
595
554
  url,
@@ -632,54 +591,190 @@ function isIPv4(hostname) {
632
591
  }
633
592
  function isPrivateIPv4(ip) {
634
593
  const parts = ip.split(".").map(Number);
635
- const [a, b] = parts;
594
+ const [a, b, c] = parts;
636
595
  if (a === 0) return true;
637
596
  if (a === 10) return true;
597
+ if (a === 100 && b >= 64 && b <= 127) return true;
638
598
  if (a === 127) return true;
639
599
  if (a === 169 && b === 254) return true;
640
600
  if (a === 172 && b >= 16 && b <= 31) return true;
601
+ if (a === 192 && b === 0 && c === 0) return true;
641
602
  if (a === 192 && b === 168) return true;
603
+ if (a === 198 && (b === 18 || b === 19)) return true;
604
+ if (a >= 240) return true;
642
605
  return false;
643
606
  }
644
- function isPrivateIPv6(ip) {
645
- const normalized = ip.toLowerCase();
646
- if (normalized === "::1") return true;
647
- if (normalized === "::") return true;
648
- if (normalized.startsWith("::ffff:")) {
649
- const mappedPart = normalized.slice(7);
650
- if (isIPv4(mappedPart)) {
651
- return isPrivateIPv4(mappedPart);
652
- }
653
- const hexParts = mappedPart.split(":");
654
- if (hexParts.length === 2) {
655
- const high = parseInt(hexParts[0], 16);
656
- const low = parseInt(hexParts[1], 16);
657
- if (!isNaN(high) && !isNaN(low)) {
658
- const a = high >> 8 & 255;
659
- const b = high & 255;
660
- const c = low >> 8 & 255;
661
- const d = low & 255;
662
- return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
607
+ function parseIPv6(ip) {
608
+ let address = ip.toLowerCase();
609
+ const zoneIndex = address.indexOf("%");
610
+ if (zoneIndex !== -1) {
611
+ address = address.slice(0, zoneIndex);
612
+ }
613
+ const halves = address.split("::");
614
+ if (halves.length > 2) return null;
615
+ const toGroups = (segment) => {
616
+ if (segment === "") return [];
617
+ const groups = [];
618
+ const parts = segment.split(":");
619
+ for (let i = 0; i < parts.length; i++) {
620
+ const part = parts[i];
621
+ if (part.includes(".")) {
622
+ if (i !== parts.length - 1 || !isIPv4(part)) return null;
623
+ const [a, b, c, d] = part.split(".").map(Number);
624
+ groups.push(a << 8 | b, c << 8 | d);
625
+ continue;
663
626
  }
627
+ if (!/^[0-9a-f]{1,4}$/.test(part)) return null;
628
+ groups.push(parseInt(part, 16));
664
629
  }
630
+ return groups;
631
+ };
632
+ const head = toGroups(halves[0]);
633
+ if (head === null) return null;
634
+ if (halves.length === 2) {
635
+ const tail = toGroups(halves[1]);
636
+ if (tail === null) return null;
637
+ const fill = 8 - head.length - tail.length;
638
+ if (fill < 0) return null;
639
+ return [...head, ...new Array(fill).fill(0), ...tail];
640
+ }
641
+ return head.length === 8 ? head : null;
642
+ }
643
+ function isPrivateIPv6(ip) {
644
+ const groups = parseIPv6(ip);
645
+ if (groups === null) return true;
646
+ const topZero = (count) => groups.slice(0, count).every((group) => group === 0);
647
+ if (topZero(7) && (groups[7] === 0 || groups[7] === 1)) return true;
648
+ if ((groups[0] & 65024) === 64512) return true;
649
+ if ((groups[0] & 65472) === 65152) return true;
650
+ if ((groups[0] & 65472) === 65216) return true;
651
+ if ((groups[0] & 65280) === 65280) return true;
652
+ const embedsIPv4 = (
653
+ // ::/96 — IPv4-compatible (deprecated)
654
+ topZero(6) || // ::ffff:0:0/96 — IPv4-mapped (ffff in group 5)
655
+ topZero(5) && groups[5] === 65535 || // ::ffff:0:0/96 — IPv4-translated form (ffff in group 4, group 5 zero)
656
+ topZero(4) && groups[4] === 65535 && groups[5] === 0 || // 64:ff9b::/96 — NAT64 well-known prefix
657
+ 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
658
+ groups[0] === 100 && groups[1] === 65435 && groups[2] === 1
659
+ );
660
+ if (embedsIPv4) {
661
+ const a = groups[6] >> 8 & 255;
662
+ const b = groups[6] & 255;
663
+ const c = groups[7] >> 8 & 255;
664
+ const d = groups[7] & 255;
665
+ return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
665
666
  }
666
- if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
667
- if (normalized.startsWith("fe80")) return true;
668
667
  return false;
669
668
  }
670
669
 
670
+ // src/fetch-with-validated-redirects.ts
671
+ var MAX_DOWNLOAD_REDIRECTS = 10;
672
+ async function fetchWithValidatedRedirects({
673
+ url,
674
+ headers,
675
+ abortSignal,
676
+ maxRedirects = MAX_DOWNLOAD_REDIRECTS
677
+ }) {
678
+ const baseInit = { signal: abortSignal };
679
+ if (headers !== void 0) {
680
+ baseInit.headers = headers;
681
+ }
682
+ let currentUrl = url;
683
+ for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
684
+ validateDownloadUrl(currentUrl);
685
+ const response = await fetch(currentUrl, {
686
+ ...baseInit,
687
+ redirect: "manual"
688
+ });
689
+ if (response.type === "opaqueredirect") {
690
+ if (!isBrowserRuntime()) {
691
+ throw new DownloadError({
692
+ url,
693
+ message: `Redirect from ${currentUrl} could not be validated and was blocked`
694
+ });
695
+ }
696
+ return await fetch(currentUrl, { ...baseInit, redirect: "follow" });
697
+ }
698
+ const location = response.headers.get("location");
699
+ if (response.status >= 300 && response.status < 400 && location) {
700
+ await cancelResponseBody(response);
701
+ currentUrl = new URL(location, currentUrl).toString();
702
+ continue;
703
+ }
704
+ return response;
705
+ }
706
+ throw new DownloadError({
707
+ url,
708
+ message: `Too many redirects (max ${maxRedirects})`
709
+ });
710
+ }
711
+
712
+ // src/read-response-with-size-limit.ts
713
+ var DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024;
714
+ async function readResponseWithSizeLimit({
715
+ response,
716
+ url,
717
+ maxBytes = DEFAULT_MAX_DOWNLOAD_SIZE
718
+ }) {
719
+ const contentLength = response.headers.get("content-length");
720
+ if (contentLength != null) {
721
+ const length = parseInt(contentLength, 10);
722
+ if (!isNaN(length) && length > maxBytes) {
723
+ await cancelResponseBody(response);
724
+ throw new DownloadError({
725
+ url,
726
+ message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes (Content-Length: ${length}).`
727
+ });
728
+ }
729
+ }
730
+ const body = response.body;
731
+ if (body == null) {
732
+ return new Uint8Array(0);
733
+ }
734
+ const reader = body.getReader();
735
+ const chunks = [];
736
+ let totalBytes = 0;
737
+ try {
738
+ while (true) {
739
+ const { done, value } = await reader.read();
740
+ if (done) {
741
+ break;
742
+ }
743
+ totalBytes += value.length;
744
+ if (totalBytes > maxBytes) {
745
+ throw new DownloadError({
746
+ url,
747
+ message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes.`
748
+ });
749
+ }
750
+ chunks.push(value);
751
+ }
752
+ } finally {
753
+ try {
754
+ await reader.cancel();
755
+ } finally {
756
+ reader.releaseLock();
757
+ }
758
+ }
759
+ const result = new Uint8Array(totalBytes);
760
+ let offset = 0;
761
+ for (const chunk of chunks) {
762
+ result.set(chunk, offset);
763
+ offset += chunk.length;
764
+ }
765
+ return result;
766
+ }
767
+
671
768
  // src/download-blob.ts
672
769
  async function downloadBlob(url, options) {
673
770
  var _a2, _b2;
674
- validateDownloadUrl(url);
675
771
  try {
676
- const response = await fetch(url, {
677
- signal: options == null ? void 0 : options.abortSignal
772
+ const response = await fetchWithValidatedRedirects({
773
+ url,
774
+ abortSignal: options == null ? void 0 : options.abortSignal
678
775
  });
679
- if (response.redirected) {
680
- validateDownloadUrl(response.url);
681
- }
682
776
  if (!response.ok) {
777
+ await cancelResponseBody(response);
683
778
  throw new DownloadError({
684
779
  url,
685
780
  statusCode: response.status,
@@ -701,6 +796,20 @@ async function downloadBlob(url, options) {
701
796
  }
702
797
  }
703
798
 
799
+ // src/extract-lines.ts
800
+ function extractLines({
801
+ text,
802
+ startLine,
803
+ endLine
804
+ }) {
805
+ if (startLine == null && endLine == null) return text;
806
+ const lineEnding = text.includes("\r\n") ? "\r\n" : text.includes("\n") ? "\n" : text.includes("\r") ? "\r" : "\n";
807
+ const lines = text.split(lineEnding);
808
+ const start = Math.max(1, startLine != null ? startLine : 1) - 1;
809
+ const end = Math.min(lines.length, endLine != null ? endLine : lines.length);
810
+ return lines.slice(start, end).join(lineEnding);
811
+ }
812
+
704
813
  // src/extract-response-headers.ts
705
814
  function extractResponseHeaders(response) {
706
815
  return Object.fromEntries([...response.headers]);
@@ -862,7 +971,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
862
971
  }
863
972
 
864
973
  // src/version.ts
865
- var VERSION = true ? "5.0.0-beta.30" : "0.0.0-test";
974
+ var VERSION = true ? "5.0.0-beta.49" : "0.0.0-test";
866
975
 
867
976
  // src/get-from-api.ts
868
977
  var getOriginalFetch = () => globalThis.fetch;
@@ -979,6 +1088,15 @@ function isBuffer(value) {
979
1088
  return (_b2 = (_a2 = globalThis.Buffer) == null ? void 0 : _a2.isBuffer(value)) != null ? _b2 : false;
980
1089
  }
981
1090
 
1091
+ // src/is-same-origin.ts
1092
+ function isSameOrigin(url, baseUrl) {
1093
+ try {
1094
+ return new URL(url).origin === new URL(baseUrl).origin;
1095
+ } catch (e) {
1096
+ return false;
1097
+ }
1098
+ }
1099
+
982
1100
  // src/is-non-nullable.ts
983
1101
  function isNonNullable(value) {
984
1102
  return value != null;
@@ -2134,16 +2252,18 @@ var parsePipelineDef = (def, refs) => {
2134
2252
  } else if (refs.pipeStrategy === "output") {
2135
2253
  return parseDef(def.out._def, refs);
2136
2254
  }
2137
- const a = parseDef(def.in._def, {
2255
+ const inputSchema = parseDef(def.in._def, {
2138
2256
  ...refs,
2139
2257
  currentPath: [...refs.currentPath, "allOf", "0"]
2140
2258
  });
2141
- const b = parseDef(def.out._def, {
2259
+ const outputSchema = parseDef(def.out._def, {
2142
2260
  ...refs,
2143
- currentPath: [...refs.currentPath, "allOf", a ? "1" : "0"]
2261
+ currentPath: [...refs.currentPath, "allOf", inputSchema ? "1" : "0"]
2144
2262
  });
2145
2263
  return {
2146
- allOf: [a, b].filter((x) => x !== void 0)
2264
+ allOf: [inputSchema, outputSchema].filter(
2265
+ (schema) => schema !== void 0
2266
+ )
2147
2267
  };
2148
2268
  };
2149
2269
 
@@ -2481,7 +2601,11 @@ function isSchema(value) {
2481
2601
  return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value;
2482
2602
  }
2483
2603
  function asSchema(schema) {
2484
- return schema == null ? jsonSchema({ properties: {}, additionalProperties: false }) : isSchema(schema) ? schema : "~standard" in schema ? schema["~standard"].vendor === "zod" ? zodSchema(schema) : standardSchema(schema) : schema();
2604
+ return schema == null ? jsonSchema({
2605
+ type: "object",
2606
+ properties: {},
2607
+ additionalProperties: false
2608
+ }) : isSchema(schema) ? schema : "~standard" in schema ? schema["~standard"].vendor === "zod" ? zodSchema(schema) : standardSchema(schema) : schema();
2485
2609
  }
2486
2610
  function standardSchema(standardSchema2) {
2487
2611
  return jsonSchema(
@@ -3277,6 +3401,11 @@ function withoutTrailingSlash(url) {
3277
3401
  return url == null ? void 0 : url.replace(/\/$/, "");
3278
3402
  }
3279
3403
 
3404
+ // src/types/executable-tool.ts
3405
+ function isExecutableTool(tool2) {
3406
+ return tool2 != null && typeof tool2.execute === "function";
3407
+ }
3408
+
3280
3409
  // src/is-async-iterable.ts
3281
3410
  function isAsyncIterable(obj) {
3282
3411
  return obj != null && typeof obj[Symbol.asyncIterator] === "function";
@@ -3301,11 +3430,6 @@ async function* executeTool({
3301
3430
  }
3302
3431
  }
3303
3432
 
3304
- // src/types/executable-tool.ts
3305
- function isExecutableTool(tool2) {
3306
- return tool2 != null && typeof tool2.execute === "function";
3307
- }
3308
-
3309
3433
  // src/index.ts
3310
3434
  import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from "@workflow/serde";
3311
3435
  import {
@@ -3322,6 +3446,7 @@ export {
3322
3446
  WORKFLOW_SERIALIZE,
3323
3447
  asArray,
3324
3448
  asSchema,
3449
+ cancelResponseBody,
3325
3450
  combineHeaders,
3326
3451
  convertAsyncIteratorToReadableStream,
3327
3452
  convertBase64ToUint8Array,
@@ -3345,7 +3470,9 @@ export {
3345
3470
  downloadBlob,
3346
3471
  dynamicTool,
3347
3472
  executeTool,
3473
+ extractLines,
3348
3474
  extractResponseHeaders,
3475
+ fetchWithValidatedRedirects,
3349
3476
  filterNullable,
3350
3477
  generateId,
3351
3478
  getErrorMessage,
@@ -3354,6 +3481,7 @@ export {
3354
3481
  getTopLevelMediaType,
3355
3482
  injectJsonInstructionIntoMessages,
3356
3483
  isAbortError,
3484
+ isBrowserRuntime,
3357
3485
  isBuffer,
3358
3486
  isCustomReasoning,
3359
3487
  isExecutableTool,
@@ -3361,6 +3489,7 @@ export {
3361
3489
  isNonNullable,
3362
3490
  isParsableJson,
3363
3491
  isProviderReference,
3492
+ isSameOrigin,
3364
3493
  isUrlSupported,
3365
3494
  jsonSchema,
3366
3495
  lazySchema,