@ai-sdk/provider-utils 5.0.6 → 5.0.9
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 +31 -0
- package/dist/index.d.ts +246 -40
- package/dist/index.js +399 -98
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/connect-to-websocket.ts +116 -0
- package/src/fetch-with-validated-redirects.ts +87 -22
- package/src/get-from-api.ts +64 -9
- package/src/index.ts +15 -0
- package/src/sanitize-request-headers.ts +53 -0
- package/src/transcription-stream-envelope.ts +341 -0
- package/src/validate-base-url.ts +12 -0
- package/src/validate-download-url.ts +14 -2
- package/src/websocket.ts +36 -0
package/dist/index.js
CHANGED
|
@@ -14,6 +14,155 @@ function combineHeaders(...headers) {
|
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
// src/remove-undefined-entries.ts
|
|
18
|
+
function removeUndefinedEntries(record) {
|
|
19
|
+
return Object.fromEntries(
|
|
20
|
+
Object.entries(record).filter(([_key, value]) => value != null)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/delay.ts
|
|
25
|
+
async function delay(delayInMs, options) {
|
|
26
|
+
if (delayInMs == null) {
|
|
27
|
+
return Promise.resolve();
|
|
28
|
+
}
|
|
29
|
+
const signal = options == null ? void 0 : options.abortSignal;
|
|
30
|
+
return new Promise((resolve2, reject) => {
|
|
31
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
32
|
+
reject(createAbortError());
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const timeoutId = setTimeout(() => {
|
|
36
|
+
cleanup();
|
|
37
|
+
resolve2();
|
|
38
|
+
}, delayInMs);
|
|
39
|
+
const cleanup = () => {
|
|
40
|
+
clearTimeout(timeoutId);
|
|
41
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
42
|
+
};
|
|
43
|
+
const onAbort = () => {
|
|
44
|
+
cleanup();
|
|
45
|
+
reject(createAbortError());
|
|
46
|
+
};
|
|
47
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function createAbortError() {
|
|
51
|
+
return new DOMException("Delay was aborted", "AbortError");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/websocket.ts
|
|
55
|
+
function getWebSocketConstructor(webSocket) {
|
|
56
|
+
const WebSocketConstructor = webSocket != null ? webSocket : globalThis.WebSocket;
|
|
57
|
+
if (WebSocketConstructor == null) {
|
|
58
|
+
throw new Error("No WebSocket implementation available.");
|
|
59
|
+
}
|
|
60
|
+
return WebSocketConstructor;
|
|
61
|
+
}
|
|
62
|
+
function toWebSocketUrl(url) {
|
|
63
|
+
const wsUrl = new URL(url);
|
|
64
|
+
if (wsUrl.protocol === "http:") {
|
|
65
|
+
wsUrl.protocol = "ws:";
|
|
66
|
+
} else if (wsUrl.protocol === "https:") {
|
|
67
|
+
wsUrl.protocol = "wss:";
|
|
68
|
+
}
|
|
69
|
+
return wsUrl;
|
|
70
|
+
}
|
|
71
|
+
var textDecoder = new TextDecoder();
|
|
72
|
+
async function readWebSocketMessageText(data) {
|
|
73
|
+
if (typeof data === "string") return data;
|
|
74
|
+
if (data instanceof ArrayBuffer) return textDecoder.decode(data);
|
|
75
|
+
if (ArrayBuffer.isView(data)) {
|
|
76
|
+
return textDecoder.decode(data);
|
|
77
|
+
}
|
|
78
|
+
if (typeof Blob !== "undefined" && data instanceof Blob) {
|
|
79
|
+
return data.text();
|
|
80
|
+
}
|
|
81
|
+
return String(data);
|
|
82
|
+
}
|
|
83
|
+
var WEBSOCKET_OPEN_STATE = 1;
|
|
84
|
+
async function waitForWebSocketBufferDrain(socket, {
|
|
85
|
+
highWaterMark = 1024 * 1024,
|
|
86
|
+
pollIntervalMs = 20,
|
|
87
|
+
abortSignal
|
|
88
|
+
} = {}) {
|
|
89
|
+
var _a2;
|
|
90
|
+
while (socket.readyState === WEBSOCKET_OPEN_STATE && ((_a2 = socket.bufferedAmount) != null ? _a2 : 0) > highWaterMark) {
|
|
91
|
+
if ((abortSignal == null ? void 0 : abortSignal.aborted) === true) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
await delay(pollIntervalMs);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/connect-to-websocket.ts
|
|
99
|
+
function connectToWebSocket({
|
|
100
|
+
url,
|
|
101
|
+
protocols,
|
|
102
|
+
headers,
|
|
103
|
+
webSocket,
|
|
104
|
+
abortSignal,
|
|
105
|
+
onOpen,
|
|
106
|
+
onMessageText,
|
|
107
|
+
onProcessingError,
|
|
108
|
+
onSocketError,
|
|
109
|
+
onClose,
|
|
110
|
+
onAbort
|
|
111
|
+
}) {
|
|
112
|
+
var _a2;
|
|
113
|
+
let socket;
|
|
114
|
+
let abortListener;
|
|
115
|
+
const close = (code) => {
|
|
116
|
+
if (abortListener != null) {
|
|
117
|
+
abortSignal == null ? void 0 : abortSignal.removeEventListener("abort", abortListener);
|
|
118
|
+
abortListener = void 0;
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
socket == null ? void 0 : socket.close(code);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
if (abortSignal == null ? void 0 : abortSignal.aborted) {
|
|
126
|
+
onAbort == null ? void 0 : onAbort((_a2 = abortSignal.reason) != null ? _a2 : new Error("Aborted"));
|
|
127
|
+
return { socket: void 0, close };
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const WebSocketConstructor = getWebSocketConstructor(webSocket);
|
|
131
|
+
socket = new WebSocketConstructor(url, protocols, {
|
|
132
|
+
headers: removeUndefinedEntries(headers != null ? headers : {})
|
|
133
|
+
});
|
|
134
|
+
} catch (error) {
|
|
135
|
+
onProcessingError(error);
|
|
136
|
+
return { socket: void 0, close };
|
|
137
|
+
}
|
|
138
|
+
if (abortSignal != null && onAbort != null) {
|
|
139
|
+
abortListener = () => {
|
|
140
|
+
var _a3;
|
|
141
|
+
return onAbort((_a3 = abortSignal.reason) != null ? _a3 : new Error("Aborted"));
|
|
142
|
+
};
|
|
143
|
+
abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
144
|
+
}
|
|
145
|
+
const openedSocket = socket;
|
|
146
|
+
socket.onopen = () => {
|
|
147
|
+
try {
|
|
148
|
+
onOpen == null ? void 0 : onOpen(openedSocket);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
onProcessingError(error);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
let tail = Promise.resolve();
|
|
154
|
+
socket.onmessage = (event) => {
|
|
155
|
+
tail = tail.then(() => readWebSocketMessageText(event.data)).then((text) => onMessageText(text)).catch(onProcessingError);
|
|
156
|
+
};
|
|
157
|
+
socket.onerror = () => {
|
|
158
|
+
tail = tail.then(() => onSocketError == null ? void 0 : onSocketError()).catch(onProcessingError);
|
|
159
|
+
};
|
|
160
|
+
socket.onclose = () => {
|
|
161
|
+
tail = tail.then(() => onClose == null ? void 0 : onClose()).catch(onProcessingError);
|
|
162
|
+
};
|
|
163
|
+
return { socket, close };
|
|
164
|
+
}
|
|
165
|
+
|
|
17
166
|
// src/convert-async-iterator-to-readable-stream.ts
|
|
18
167
|
function convertAsyncIteratorToReadableStream(iterator) {
|
|
19
168
|
let cancelled = false;
|
|
@@ -140,36 +289,6 @@ function createToolNameMapping({
|
|
|
140
289
|
};
|
|
141
290
|
}
|
|
142
291
|
|
|
143
|
-
// src/delay.ts
|
|
144
|
-
async function delay(delayInMs, options) {
|
|
145
|
-
if (delayInMs == null) {
|
|
146
|
-
return Promise.resolve();
|
|
147
|
-
}
|
|
148
|
-
const signal = options == null ? void 0 : options.abortSignal;
|
|
149
|
-
return new Promise((resolve2, reject) => {
|
|
150
|
-
if (signal == null ? void 0 : signal.aborted) {
|
|
151
|
-
reject(createAbortError());
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const timeoutId = setTimeout(() => {
|
|
155
|
-
cleanup();
|
|
156
|
-
resolve2();
|
|
157
|
-
}, delayInMs);
|
|
158
|
-
const cleanup = () => {
|
|
159
|
-
clearTimeout(timeoutId);
|
|
160
|
-
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
161
|
-
};
|
|
162
|
-
const onAbort = () => {
|
|
163
|
-
cleanup();
|
|
164
|
-
reject(createAbortError());
|
|
165
|
-
};
|
|
166
|
-
signal == null ? void 0 : signal.addEventListener("abort", onAbort);
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
function createAbortError() {
|
|
170
|
-
return new DOMException("Delay was aborted", "AbortError");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
292
|
// src/delayed-promise.ts
|
|
174
293
|
var DelayedPromise = class {
|
|
175
294
|
constructor() {
|
|
@@ -528,6 +647,51 @@ function isBrowserRuntime(globalThisAny = globalThis) {
|
|
|
528
647
|
return globalThisAny.window != null;
|
|
529
648
|
}
|
|
530
649
|
|
|
650
|
+
// src/is-same-origin.ts
|
|
651
|
+
function isSameOrigin(url, baseUrl) {
|
|
652
|
+
try {
|
|
653
|
+
return new URL(url).origin === new URL(baseUrl).origin;
|
|
654
|
+
} catch (e) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// src/sanitize-request-headers.ts
|
|
660
|
+
var BLOCKED_REQUEST_HEADERS = [
|
|
661
|
+
// Hop-by-hop / transport (RFC 7230 §6.1)
|
|
662
|
+
"connection",
|
|
663
|
+
"keep-alive",
|
|
664
|
+
"te",
|
|
665
|
+
"trailer",
|
|
666
|
+
"transfer-encoding",
|
|
667
|
+
"upgrade",
|
|
668
|
+
// Host / virtual-host routing
|
|
669
|
+
"host",
|
|
670
|
+
// Proxy / origin spoofing
|
|
671
|
+
"forwarded",
|
|
672
|
+
"proxy-authorization",
|
|
673
|
+
"via",
|
|
674
|
+
"x-forwarded-for",
|
|
675
|
+
"x-forwarded-host",
|
|
676
|
+
"x-forwarded-proto",
|
|
677
|
+
"x-real-ip",
|
|
678
|
+
// Cloud metadata (GCP, AWS IMDSv1/v2, Azure, Alibaba, DigitalOcean)
|
|
679
|
+
"metadata",
|
|
680
|
+
"metadata-flavor",
|
|
681
|
+
"x-aws-ec2-metadata-token",
|
|
682
|
+
"x-metadata-token",
|
|
683
|
+
// Session / cookie
|
|
684
|
+
"cookie",
|
|
685
|
+
"set-cookie"
|
|
686
|
+
];
|
|
687
|
+
function sanitizeRequestHeaders(input) {
|
|
688
|
+
const headers = new Headers(input);
|
|
689
|
+
for (const name2 of BLOCKED_REQUEST_HEADERS) {
|
|
690
|
+
headers.delete(name2);
|
|
691
|
+
}
|
|
692
|
+
return headers;
|
|
693
|
+
}
|
|
694
|
+
|
|
531
695
|
// src/validate-download-url.ts
|
|
532
696
|
function validateDownloadUrl(url) {
|
|
533
697
|
let parsed;
|
|
@@ -599,9 +763,12 @@ function isPrivateIPv4(ip) {
|
|
|
599
763
|
if (a === 169 && b === 254) return true;
|
|
600
764
|
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
601
765
|
if (a === 192 && b === 0 && c === 0) return true;
|
|
766
|
+
if (a === 192 && b === 0 && c === 2) return true;
|
|
602
767
|
if (a === 192 && b === 168) return true;
|
|
603
768
|
if (a === 198 && (b === 18 || b === 19)) return true;
|
|
604
|
-
if (a
|
|
769
|
+
if (a === 198 && b === 51 && c === 100) return true;
|
|
770
|
+
if (a === 203 && b === 0 && c === 113) return true;
|
|
771
|
+
if (a >= 224) return true;
|
|
605
772
|
return false;
|
|
606
773
|
}
|
|
607
774
|
function parseIPv6(ip) {
|
|
@@ -649,6 +816,8 @@ function isPrivateIPv6(ip) {
|
|
|
649
816
|
if ((groups[0] & 65472) === 65152) return true;
|
|
650
817
|
if ((groups[0] & 65472) === 65216) return true;
|
|
651
818
|
if ((groups[0] & 65280) === 65280) return true;
|
|
819
|
+
if (groups[0] === 8193 && groups[1] === 3512) return true;
|
|
820
|
+
if (groups[0] === 16383 && (groups[1] & 61440) === 0) return true;
|
|
652
821
|
const embedsIPv4 = (
|
|
653
822
|
// ::/96 — IPv4-compatible (deprecated)
|
|
654
823
|
topZero(6) || // ::ffff:0:0/96 — IPv4-mapped (ffff in group 5)
|
|
@@ -669,23 +838,29 @@ function isPrivateIPv6(ip) {
|
|
|
669
838
|
|
|
670
839
|
// src/fetch-with-validated-redirects.ts
|
|
671
840
|
var MAX_DOWNLOAD_REDIRECTS = 10;
|
|
841
|
+
var REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
672
842
|
async function fetchWithValidatedRedirects({
|
|
673
843
|
url,
|
|
674
844
|
headers,
|
|
675
845
|
abortSignal,
|
|
676
|
-
maxRedirects = MAX_DOWNLOAD_REDIRECTS
|
|
846
|
+
maxRedirects = MAX_DOWNLOAD_REDIRECTS,
|
|
847
|
+
fetch = globalThis.fetch,
|
|
848
|
+
trustedOrigin
|
|
677
849
|
}) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
850
|
+
let currentHeaders = headers === void 0 ? void 0 : sanitizeRequestHeaders(headers);
|
|
851
|
+
const perHopInit = (redirect) => {
|
|
852
|
+
const init = { signal: abortSignal, redirect };
|
|
853
|
+
if (currentHeaders !== void 0) {
|
|
854
|
+
init.headers = new Headers(currentHeaders);
|
|
855
|
+
}
|
|
856
|
+
return init;
|
|
857
|
+
};
|
|
682
858
|
let currentUrl = url;
|
|
683
859
|
for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
});
|
|
860
|
+
if (trustedOrigin === void 0 || !isSameOrigin(currentUrl, trustedOrigin)) {
|
|
861
|
+
validateDownloadUrl(currentUrl);
|
|
862
|
+
}
|
|
863
|
+
const response = await fetch(currentUrl, perHopInit("manual"));
|
|
689
864
|
if (response.type === "opaqueredirect") {
|
|
690
865
|
if (!isBrowserRuntime()) {
|
|
691
866
|
throw new DownloadError({
|
|
@@ -693,12 +868,19 @@ async function fetchWithValidatedRedirects({
|
|
|
693
868
|
message: `Redirect from ${currentUrl} could not be validated and was blocked`
|
|
694
869
|
});
|
|
695
870
|
}
|
|
696
|
-
return await fetch(currentUrl,
|
|
871
|
+
return await fetch(currentUrl, perHopInit("follow"));
|
|
697
872
|
}
|
|
698
873
|
const location = response.headers.get("location");
|
|
699
|
-
if (
|
|
874
|
+
if (REDIRECT_STATUS_CODES.has(response.status) && location) {
|
|
700
875
|
await cancelResponseBody(response);
|
|
701
|
-
|
|
876
|
+
const nextUrl = new URL(location, currentUrl).toString();
|
|
877
|
+
if (currentHeaders !== void 0 && !isSameOrigin(nextUrl, currentUrl)) {
|
|
878
|
+
const userAgent = currentHeaders.get("user-agent");
|
|
879
|
+
currentHeaders = new Headers(
|
|
880
|
+
userAgent == null ? void 0 : { "user-agent": userAgent }
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
currentUrl = nextUrl;
|
|
702
884
|
continue;
|
|
703
885
|
}
|
|
704
886
|
return response;
|
|
@@ -971,7 +1153,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
|
|
|
971
1153
|
}
|
|
972
1154
|
|
|
973
1155
|
// src/version.ts
|
|
974
|
-
var VERSION = true ? "5.0.
|
|
1156
|
+
var VERSION = true ? "5.0.9" : "0.0.0-test";
|
|
975
1157
|
|
|
976
1158
|
// src/get-from-api.ts
|
|
977
1159
|
var getOriginalFetch = () => globalThis.fetch;
|
|
@@ -981,16 +1163,27 @@ var getFromApi = async ({
|
|
|
981
1163
|
successfulResponseHandler,
|
|
982
1164
|
failedResponseHandler,
|
|
983
1165
|
abortSignal,
|
|
984
|
-
fetch
|
|
1166
|
+
fetch = getOriginalFetch(),
|
|
1167
|
+
validateUrl,
|
|
1168
|
+
credentialedOrigin,
|
|
1169
|
+
trustedOrigin
|
|
985
1170
|
}) => {
|
|
986
1171
|
try {
|
|
987
|
-
const
|
|
1172
|
+
const outgoingHeaders = credentialedOrigin !== void 0 && !isSameOrigin(url, credentialedOrigin) ? {} : headers;
|
|
1173
|
+
const requestHeaders = withUserAgentSuffix(
|
|
1174
|
+
outgoingHeaders,
|
|
1175
|
+
`ai-sdk/provider-utils/${VERSION}`,
|
|
1176
|
+
getRuntimeEnvironmentUserAgent()
|
|
1177
|
+
);
|
|
1178
|
+
const response = validateUrl ? await fetchWithValidatedRedirects({
|
|
1179
|
+
url,
|
|
1180
|
+
headers: requestHeaders,
|
|
1181
|
+
abortSignal,
|
|
1182
|
+
fetch,
|
|
1183
|
+
trustedOrigin
|
|
1184
|
+
}) : await fetch(url, {
|
|
988
1185
|
method: "GET",
|
|
989
|
-
headers:
|
|
990
|
-
headers,
|
|
991
|
-
`ai-sdk/provider-utils/${VERSION}`,
|
|
992
|
-
getRuntimeEnvironmentUserAgent()
|
|
993
|
-
),
|
|
1186
|
+
headers: requestHeaders,
|
|
994
1187
|
signal: abortSignal
|
|
995
1188
|
});
|
|
996
1189
|
const responseHeaders = extractResponseHeaders(response);
|
|
@@ -1088,15 +1281,6 @@ function isBuffer(value) {
|
|
|
1088
1281
|
return (_b2 = (_a2 = globalThis.Buffer) == null ? void 0 : _a2.isBuffer(value)) != null ? _b2 : false;
|
|
1089
1282
|
}
|
|
1090
1283
|
|
|
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
|
-
|
|
1100
1284
|
// src/is-non-nullable.ts
|
|
1101
1285
|
function isNonNullable(value) {
|
|
1102
1286
|
return value != null;
|
|
@@ -2814,7 +2998,7 @@ var postJsonToApi = async ({
|
|
|
2814
2998
|
failedResponseHandler,
|
|
2815
2999
|
successfulResponseHandler,
|
|
2816
3000
|
abortSignal,
|
|
2817
|
-
fetch
|
|
3001
|
+
fetch
|
|
2818
3002
|
}) => await postToApi({
|
|
2819
3003
|
url,
|
|
2820
3004
|
headers: {
|
|
@@ -2828,7 +3012,7 @@ var postJsonToApi = async ({
|
|
|
2828
3012
|
failedResponseHandler,
|
|
2829
3013
|
successfulResponseHandler,
|
|
2830
3014
|
abortSignal,
|
|
2831
|
-
fetch
|
|
3015
|
+
fetch
|
|
2832
3016
|
});
|
|
2833
3017
|
var postFormDataToApi = async ({
|
|
2834
3018
|
url,
|
|
@@ -2837,7 +3021,7 @@ var postFormDataToApi = async ({
|
|
|
2837
3021
|
failedResponseHandler,
|
|
2838
3022
|
successfulResponseHandler,
|
|
2839
3023
|
abortSignal,
|
|
2840
|
-
fetch
|
|
3024
|
+
fetch
|
|
2841
3025
|
}) => await postToApi({
|
|
2842
3026
|
url,
|
|
2843
3027
|
headers,
|
|
@@ -2848,7 +3032,7 @@ var postFormDataToApi = async ({
|
|
|
2848
3032
|
failedResponseHandler,
|
|
2849
3033
|
successfulResponseHandler,
|
|
2850
3034
|
abortSignal,
|
|
2851
|
-
fetch
|
|
3035
|
+
fetch
|
|
2852
3036
|
});
|
|
2853
3037
|
var postToApi = async ({
|
|
2854
3038
|
url,
|
|
@@ -2857,10 +3041,10 @@ var postToApi = async ({
|
|
|
2857
3041
|
successfulResponseHandler,
|
|
2858
3042
|
failedResponseHandler,
|
|
2859
3043
|
abortSignal,
|
|
2860
|
-
fetch
|
|
3044
|
+
fetch = getOriginalFetch2()
|
|
2861
3045
|
}) => {
|
|
2862
3046
|
try {
|
|
2863
|
-
const response = await
|
|
3047
|
+
const response = await fetch(url, {
|
|
2864
3048
|
method: "POST",
|
|
2865
3049
|
headers: withUserAgentSuffix(
|
|
2866
3050
|
headers,
|
|
@@ -3012,13 +3196,6 @@ function createProviderExecutedToolFactory({
|
|
|
3012
3196
|
});
|
|
3013
3197
|
}
|
|
3014
3198
|
|
|
3015
|
-
// src/remove-undefined-entries.ts
|
|
3016
|
-
function removeUndefinedEntries(record) {
|
|
3017
|
-
return Object.fromEntries(
|
|
3018
|
-
Object.entries(record).filter(([_key, value]) => value != null)
|
|
3019
|
-
);
|
|
3020
|
-
}
|
|
3021
|
-
|
|
3022
3199
|
// src/resolve.ts
|
|
3023
3200
|
async function resolve(value) {
|
|
3024
3201
|
if (typeof value === "function") {
|
|
@@ -3153,12 +3330,12 @@ async function retryWithExponentialBackoffInternal(f, {
|
|
|
3153
3330
|
|
|
3154
3331
|
// src/response-handler.ts
|
|
3155
3332
|
import { APICallError as APICallError4, EmptyResponseBodyError } from "@ai-sdk/provider";
|
|
3156
|
-
var
|
|
3333
|
+
var textDecoder2 = new TextDecoder();
|
|
3157
3334
|
async function readResponseBodyAsText({
|
|
3158
3335
|
response,
|
|
3159
3336
|
url
|
|
3160
3337
|
}) {
|
|
3161
|
-
return
|
|
3338
|
+
return textDecoder2.decode(
|
|
3162
3339
|
await readResponseWithSizeLimit({
|
|
3163
3340
|
response,
|
|
3164
3341
|
url
|
|
@@ -3481,34 +3658,150 @@ function stripFileExtension(filename) {
|
|
|
3481
3658
|
return firstDotIndex === -1 ? filename : filename.slice(0, firstDotIndex);
|
|
3482
3659
|
}
|
|
3483
3660
|
|
|
3484
|
-
// src/
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3661
|
+
// src/transcription-stream-envelope.ts
|
|
3662
|
+
var TRANSCRIPTION_STREAM_START_FRAME_TYPE = "transcription-stream.start";
|
|
3663
|
+
var TRANSCRIPTION_STREAM_AUDIO_DONE_FRAME_TYPE = "transcription-stream.audio-done";
|
|
3664
|
+
function parseTranscriptionStreamClientFrame(text) {
|
|
3665
|
+
let value;
|
|
3666
|
+
try {
|
|
3667
|
+
value = secureJsonParse(text);
|
|
3668
|
+
} catch (e) {
|
|
3669
|
+
return { type: "invalid", message: "malformed JSON" };
|
|
3670
|
+
}
|
|
3671
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
3672
|
+
return { type: "invalid", message: "frame must be a JSON object" };
|
|
3673
|
+
}
|
|
3674
|
+
const frame = value;
|
|
3675
|
+
if (typeof frame.type !== "string") {
|
|
3676
|
+
return { type: "invalid", message: "frame type must be a string" };
|
|
3677
|
+
}
|
|
3678
|
+
switch (frame.type) {
|
|
3679
|
+
case TRANSCRIPTION_STREAM_START_FRAME_TYPE: {
|
|
3680
|
+
const inputAudioFormat = frame.inputAudioFormat;
|
|
3681
|
+
if (inputAudioFormat == null || typeof inputAudioFormat !== "object" || Array.isArray(inputAudioFormat) || typeof inputAudioFormat.type !== "string") {
|
|
3682
|
+
return {
|
|
3683
|
+
type: "invalid",
|
|
3684
|
+
message: "start frame must have an inputAudioFormat object with a string type"
|
|
3685
|
+
};
|
|
3686
|
+
}
|
|
3687
|
+
if (inputAudioFormat.rate !== void 0 && typeof inputAudioFormat.rate !== "number") {
|
|
3688
|
+
return {
|
|
3689
|
+
type: "invalid",
|
|
3690
|
+
message: "inputAudioFormat.rate must be a number when present"
|
|
3691
|
+
};
|
|
3692
|
+
}
|
|
3693
|
+
if (frame.providerOptions !== void 0 && (frame.providerOptions == null || typeof frame.providerOptions !== "object" || Array.isArray(frame.providerOptions))) {
|
|
3694
|
+
return {
|
|
3695
|
+
type: "invalid",
|
|
3696
|
+
message: "providerOptions must be an object when present"
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
if (frame.includeRawChunks !== void 0 && typeof frame.includeRawChunks !== "boolean") {
|
|
3700
|
+
return {
|
|
3701
|
+
type: "invalid",
|
|
3702
|
+
message: "includeRawChunks must be a boolean when present"
|
|
3703
|
+
};
|
|
3704
|
+
}
|
|
3705
|
+
return {
|
|
3706
|
+
type: "start",
|
|
3707
|
+
frame
|
|
3708
|
+
};
|
|
3709
|
+
}
|
|
3710
|
+
case TRANSCRIPTION_STREAM_AUDIO_DONE_FRAME_TYPE:
|
|
3711
|
+
return { type: "audio-done" };
|
|
3712
|
+
default:
|
|
3713
|
+
return { type: "unknown" };
|
|
3489
3714
|
}
|
|
3490
|
-
return WebSocketConstructor;
|
|
3491
3715
|
}
|
|
3492
|
-
function
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3716
|
+
function serializeTranscriptionStreamPart(part) {
|
|
3717
|
+
try {
|
|
3718
|
+
if (part.type === "error" && isError(part.error)) {
|
|
3719
|
+
return JSON.stringify({
|
|
3720
|
+
...part,
|
|
3721
|
+
error: { name: part.error.name, message: part.error.message }
|
|
3722
|
+
});
|
|
3723
|
+
}
|
|
3724
|
+
return JSON.stringify(part);
|
|
3725
|
+
} catch (e) {
|
|
3726
|
+
return void 0;
|
|
3498
3727
|
}
|
|
3499
|
-
return wsUrl;
|
|
3500
3728
|
}
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3729
|
+
function isError(value) {
|
|
3730
|
+
return value instanceof Error || Object.prototype.toString.call(value) === "[object Error]";
|
|
3731
|
+
}
|
|
3732
|
+
function parseTranscriptionStreamPart(text) {
|
|
3733
|
+
let value;
|
|
3734
|
+
try {
|
|
3735
|
+
value = secureJsonParse(text);
|
|
3736
|
+
} catch (e) {
|
|
3737
|
+
return void 0;
|
|
3507
3738
|
}
|
|
3508
|
-
if (typeof
|
|
3509
|
-
return
|
|
3739
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
3740
|
+
return void 0;
|
|
3510
3741
|
}
|
|
3511
|
-
|
|
3742
|
+
const part = value;
|
|
3743
|
+
switch (part.type) {
|
|
3744
|
+
case "stream-start":
|
|
3745
|
+
return Array.isArray(part.warnings) && part.warnings.every(isWarning) ? part : void 0;
|
|
3746
|
+
case "transcript-delta":
|
|
3747
|
+
return isString(part.delta) && isOptional(part.id, isString) && isOptional(part.providerMetadata, isPlainObject) ? part : void 0;
|
|
3748
|
+
case "transcript-partial":
|
|
3749
|
+
return isString(part.text) && isOptional(part.id, isString) && isOptional(part.startSecond, isNumber) && isOptional(part.durationInSeconds, isNumber) && isOptional(part.channelIndex, isNumber) && isOptional(part.providerMetadata, isPlainObject) ? part : void 0;
|
|
3750
|
+
case "transcript-final":
|
|
3751
|
+
return isString(part.text) && isOptional(part.id, isString) && isOptional(part.startSecond, isNumber) && isOptional(part.endSecond, isNumber) && isOptional(part.channelIndex, isNumber) && isOptional(part.providerMetadata, isPlainObject) ? part : void 0;
|
|
3752
|
+
case "finish":
|
|
3753
|
+
return isString(part.text) && Array.isArray(part.segments) && part.segments.every(isSegment) && isOptional(part.language, isString) && isOptional(part.durationInSeconds, isNumber) && isOptional(part.providerMetadata, isPlainObject) ? part : void 0;
|
|
3754
|
+
case "response-metadata": {
|
|
3755
|
+
if (!(isOptional(part.modelId, isString) && isOptional(part.headers, isPlainObject))) {
|
|
3756
|
+
return void 0;
|
|
3757
|
+
}
|
|
3758
|
+
const timestamp = part.timestamp;
|
|
3759
|
+
if (timestamp == null) {
|
|
3760
|
+
return { ...part, timestamp: void 0 };
|
|
3761
|
+
}
|
|
3762
|
+
if (typeof timestamp !== "string") {
|
|
3763
|
+
return void 0;
|
|
3764
|
+
}
|
|
3765
|
+
const revived = new Date(timestamp);
|
|
3766
|
+
return Number.isNaN(revived.getTime()) ? void 0 : { ...part, timestamp: revived };
|
|
3767
|
+
}
|
|
3768
|
+
case "raw":
|
|
3769
|
+
return "rawValue" in part ? part : void 0;
|
|
3770
|
+
case "error":
|
|
3771
|
+
return "error" in part ? part : void 0;
|
|
3772
|
+
default:
|
|
3773
|
+
return void 0;
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
function isString(value) {
|
|
3777
|
+
return typeof value === "string";
|
|
3778
|
+
}
|
|
3779
|
+
function isNumber(value) {
|
|
3780
|
+
return typeof value === "number";
|
|
3781
|
+
}
|
|
3782
|
+
function isOptional(value, check) {
|
|
3783
|
+
return value === void 0 || check(value);
|
|
3784
|
+
}
|
|
3785
|
+
function isPlainObject(value) {
|
|
3786
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
3787
|
+
}
|
|
3788
|
+
function isWarning(value) {
|
|
3789
|
+
return isPlainObject(value) && isString(value.type);
|
|
3790
|
+
}
|
|
3791
|
+
function isSegment(value) {
|
|
3792
|
+
return isPlainObject(value) && isString(value.text) && isNumber(value.startSecond) && isNumber(value.endSecond);
|
|
3793
|
+
}
|
|
3794
|
+
|
|
3795
|
+
// src/validate-base-url.ts
|
|
3796
|
+
import { InvalidArgumentError as InvalidArgumentError3 } from "@ai-sdk/provider";
|
|
3797
|
+
function validateBaseURL(baseURL) {
|
|
3798
|
+
if ((baseURL == null ? void 0 : baseURL.trim()) === "") {
|
|
3799
|
+
throw new InvalidArgumentError3({
|
|
3800
|
+
argument: "baseURL",
|
|
3801
|
+
message: "baseURL must be a non-empty string."
|
|
3802
|
+
});
|
|
3803
|
+
}
|
|
3804
|
+
return baseURL;
|
|
3512
3805
|
}
|
|
3513
3806
|
|
|
3514
3807
|
// src/without-trailing-slash.ts
|
|
@@ -3554,6 +3847,8 @@ export {
|
|
|
3554
3847
|
DEFAULT_MAX_DOWNLOAD_SIZE,
|
|
3555
3848
|
DelayedPromise,
|
|
3556
3849
|
DownloadError,
|
|
3850
|
+
TRANSCRIPTION_STREAM_AUDIO_DONE_FRAME_TYPE as EXPERIMENTAL_TRANSCRIPTION_STREAM_AUDIO_DONE_FRAME_TYPE,
|
|
3851
|
+
TRANSCRIPTION_STREAM_START_FRAME_TYPE as EXPERIMENTAL_TRANSCRIPTION_STREAM_START_FRAME_TYPE,
|
|
3557
3852
|
EventSourceParserStream2 as EventSourceParserStream,
|
|
3558
3853
|
StreamingToolCallTracker,
|
|
3559
3854
|
VERSION,
|
|
@@ -3563,6 +3858,7 @@ export {
|
|
|
3563
3858
|
asSchema,
|
|
3564
3859
|
cancelResponseBody,
|
|
3565
3860
|
combineHeaders,
|
|
3861
|
+
connectToWebSocket,
|
|
3566
3862
|
convertAsyncIteratorToReadableStream,
|
|
3567
3863
|
convertBase64ToUint8Array,
|
|
3568
3864
|
convertImageModelFileToDataUri,
|
|
@@ -3585,6 +3881,9 @@ export {
|
|
|
3585
3881
|
downloadBlob,
|
|
3586
3882
|
dynamicTool,
|
|
3587
3883
|
executeTool,
|
|
3884
|
+
parseTranscriptionStreamClientFrame as experimental_parseTranscriptionStreamClientFrame,
|
|
3885
|
+
parseTranscriptionStreamPart as experimental_parseTranscriptionStreamPart,
|
|
3886
|
+
serializeTranscriptionStreamPart as experimental_serializeTranscriptionStreamPart,
|
|
3588
3887
|
extractLines,
|
|
3589
3888
|
extractResponseHeaders,
|
|
3590
3889
|
fetchWithValidatedRedirects,
|
|
@@ -3636,8 +3935,10 @@ export {
|
|
|
3636
3935
|
stripFileExtension,
|
|
3637
3936
|
toWebSocketUrl,
|
|
3638
3937
|
tool,
|
|
3938
|
+
validateBaseURL,
|
|
3639
3939
|
validateDownloadUrl,
|
|
3640
3940
|
validateTypes,
|
|
3941
|
+
waitForWebSocketBufferDrain,
|
|
3641
3942
|
withUserAgentSuffix,
|
|
3642
3943
|
withoutTrailingSlash,
|
|
3643
3944
|
zodSchema
|