@ai-sdk/provider-utils 5.0.39 → 5.0.40
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 +10 -0
- package/dist/index.d.ts +20 -1
- package/dist/index.js +34 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/detect-media-type.ts +6 -2
- package/src/fetch-with-validated-redirects.ts +63 -3
- package/src/index.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/provider-utils",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.40",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@ai-sdk/provider": "4.0.
|
|
35
|
+
"@ai-sdk/provider": "4.0.14",
|
|
36
36
|
"@standard-schema/spec": "^1.1.0",
|
|
37
37
|
"@workflow/serde": "4.1.0",
|
|
38
38
|
"eventsource-parser": "^3.0.8",
|
package/src/detect-media-type.ts
CHANGED
|
@@ -3,7 +3,11 @@ import { convertBase64ToUint8Array } from './uint8-utils';
|
|
|
3
3
|
const imageMediaTypeSignatures = [
|
|
4
4
|
{
|
|
5
5
|
mediaType: 'image/gif' as const,
|
|
6
|
-
bytesPrefix: [0x47, 0x49, 0x46], //
|
|
6
|
+
bytesPrefix: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], // GIF87a
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
mediaType: 'image/gif' as const,
|
|
10
|
+
bytesPrefix: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], // GIF89a
|
|
7
11
|
},
|
|
8
12
|
{
|
|
9
13
|
mediaType: 'image/png' as const,
|
|
@@ -32,7 +36,7 @@ const imageMediaTypeSignatures = [
|
|
|
32
36
|
},
|
|
33
37
|
{
|
|
34
38
|
mediaType: 'image/bmp' as const,
|
|
35
|
-
bytesPrefix: [0x42, 0x4d],
|
|
39
|
+
bytesPrefix: [0x42, 0x4d, null, null, null, null, 0x00, 0x00, 0x00, 0x00],
|
|
36
40
|
},
|
|
37
41
|
{
|
|
38
42
|
mediaType: 'image/tiff' as const,
|
|
@@ -14,6 +14,63 @@ const MAX_DOWNLOAD_REDIRECTS = 10;
|
|
|
14
14
|
// even when a server attaches a Location header.
|
|
15
15
|
const REDIRECT_STATUS_CODES = new Set([301, 302, 303, 307, 308]);
|
|
16
16
|
|
|
17
|
+
async function getValidatedFetch(
|
|
18
|
+
customFetch: FetchFunction | undefined,
|
|
19
|
+
): Promise<FetchFunction> {
|
|
20
|
+
// Callers commonly pass globalThis.fetch through several abstraction
|
|
21
|
+
// layers. Preserve the DNS-pinned Node.js default in that case rather than
|
|
22
|
+
// accidentally treating it as an intentionally custom fetch.
|
|
23
|
+
return customFetch == null || customFetch === globalThis.fetch
|
|
24
|
+
? await getDefaultDownloadFetch()
|
|
25
|
+
: customFetch;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Fetches one validated URL without following redirects.
|
|
30
|
+
*
|
|
31
|
+
* On Node.js, the default fetch validates and pins DNS results at connect time.
|
|
32
|
+
* An injected fetch is responsible for equivalent connect-time validation.
|
|
33
|
+
* Redirects are rejected by default. Callers using `redirect: 'manual'` must
|
|
34
|
+
* validate the Location target before issuing another request.
|
|
35
|
+
*/
|
|
36
|
+
export async function fetchWithValidatedEndpoint({
|
|
37
|
+
url,
|
|
38
|
+
init,
|
|
39
|
+
fetch: customFetch,
|
|
40
|
+
trustedOrigin,
|
|
41
|
+
redirect = 'error',
|
|
42
|
+
}: {
|
|
43
|
+
url: string | URL;
|
|
44
|
+
init?: RequestInit;
|
|
45
|
+
fetch?: FetchFunction;
|
|
46
|
+
/**
|
|
47
|
+
* A developer-configured origin that may legitimately resolve to a private
|
|
48
|
+
* address. This must never be derived from untrusted response data.
|
|
49
|
+
*/
|
|
50
|
+
trustedOrigin?: string;
|
|
51
|
+
redirect?: 'error' | 'manual';
|
|
52
|
+
}): Promise<Response> {
|
|
53
|
+
const urlText = url.toString();
|
|
54
|
+
const isTrusted =
|
|
55
|
+
trustedOrigin !== undefined && isSameOrigin(urlText, trustedOrigin);
|
|
56
|
+
|
|
57
|
+
if (!isTrusted) {
|
|
58
|
+
validateDownloadUrl(urlText);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const fetch =
|
|
62
|
+
isTrusted && customFetch != null
|
|
63
|
+
? customFetch
|
|
64
|
+
: isTrusted
|
|
65
|
+
? globalThis.fetch
|
|
66
|
+
: await getValidatedFetch(customFetch);
|
|
67
|
+
|
|
68
|
+
return await fetch(url, {
|
|
69
|
+
...init,
|
|
70
|
+
redirect,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
17
74
|
/**
|
|
18
75
|
* Fetches a URL while enforcing the download guard on every hop.
|
|
19
76
|
*
|
|
@@ -106,8 +163,11 @@ export async function fetchWithValidatedRedirects({
|
|
|
106
163
|
}
|
|
107
164
|
|
|
108
165
|
const fetch =
|
|
109
|
-
customFetch
|
|
110
|
-
|
|
166
|
+
isTrustedHop && customFetch != null
|
|
167
|
+
? customFetch
|
|
168
|
+
: isTrustedHop
|
|
169
|
+
? globalThis.fetch
|
|
170
|
+
: await getValidatedFetch(customFetch);
|
|
111
171
|
|
|
112
172
|
const response = await fetch(currentUrl, perHopInit('manual'));
|
|
113
173
|
|
|
@@ -121,7 +181,7 @@ export async function fetchWithValidatedRedirects({
|
|
|
121
181
|
return await fetch(currentUrl, perHopInit('follow'));
|
|
122
182
|
}
|
|
123
183
|
|
|
124
|
-
const location = response.headers
|
|
184
|
+
const location = response.headers?.get('location');
|
|
125
185
|
if (REDIRECT_STATUS_CODES.has(response.status) && location) {
|
|
126
186
|
// Release the redirect response's connection before moving to the next
|
|
127
187
|
// hop. Whether that hop is followed or rejected by the guard, an
|
package/src/index.ts
CHANGED
|
@@ -31,7 +31,10 @@ export {
|
|
|
31
31
|
export { downloadBlob } from './download-blob';
|
|
32
32
|
export { DownloadError } from './download-error';
|
|
33
33
|
export { EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL as EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL } from './embedding-model-capabilities';
|
|
34
|
-
export {
|
|
34
|
+
export {
|
|
35
|
+
fetchWithValidatedEndpoint,
|
|
36
|
+
fetchWithValidatedRedirects,
|
|
37
|
+
} from './fetch-with-validated-redirects';
|
|
35
38
|
export { extractLines } from './extract-lines';
|
|
36
39
|
export * from './extract-response-headers';
|
|
37
40
|
export * from './fetch-function';
|