ai 6.0.233 → 6.0.234
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 +12 -0
- package/dist/index.d.mts +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +33 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -21
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +26 -14
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +26 -14
- package/dist/internal/index.mjs.map +1 -1
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +2 -2
- package/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +6 -1
- package/package.json +4 -4
- package/src/agent/pipe-agent-ui-stream-to-response.ts +1 -1
- package/src/generate-object/stream-object-result.ts +4 -1
- package/src/generate-object/stream-object.ts +1 -1
- package/src/generate-text/stream-text-result.ts +5 -2
- package/src/generate-text/stream-text.ts +2 -2
- package/src/text-stream/pipe-text-stream-to-response.ts +3 -2
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +3 -2
- package/src/util/detect-media-type.ts +47 -26
- package/src/util/write-to-server-response.ts +2 -2
|
@@ -13,6 +13,7 @@ import { writeToServerResponse } from '../util/write-to-server-response';
|
|
|
13
13
|
* @param options.statusText - Optional HTTP status text.
|
|
14
14
|
* @param options.headers - Optional response headers.
|
|
15
15
|
* @param options.textStream - The text stream to pipe.
|
|
16
|
+
* @returns A promise that resolves when the stream has been written.
|
|
16
17
|
*/
|
|
17
18
|
export function pipeTextStreamToResponse({
|
|
18
19
|
response,
|
|
@@ -23,8 +24,8 @@ export function pipeTextStreamToResponse({
|
|
|
23
24
|
}: {
|
|
24
25
|
response: ServerResponse;
|
|
25
26
|
textStream: ReadableStream<string>;
|
|
26
|
-
} & ResponseInit): void {
|
|
27
|
-
writeToServerResponse({
|
|
27
|
+
} & ResponseInit): Promise<void> {
|
|
28
|
+
return writeToServerResponse({
|
|
28
29
|
response,
|
|
29
30
|
status,
|
|
30
31
|
statusText,
|
|
@@ -16,6 +16,7 @@ import type { UIMessageStreamResponseInit } from './ui-message-stream-response-i
|
|
|
16
16
|
* @param options.headers - Additional HTTP headers to include in the response.
|
|
17
17
|
* @param options.stream - The UI message chunk stream to send.
|
|
18
18
|
* @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently.
|
|
19
|
+
* @returns A promise that resolves when the stream has been written.
|
|
19
20
|
*/
|
|
20
21
|
export function pipeUIMessageStreamToResponse({
|
|
21
22
|
response,
|
|
@@ -27,7 +28,7 @@ export function pipeUIMessageStreamToResponse({
|
|
|
27
28
|
}: {
|
|
28
29
|
response: ServerResponse;
|
|
29
30
|
stream: ReadableStream<UIMessageChunk>;
|
|
30
|
-
} & UIMessageStreamResponseInit): void {
|
|
31
|
+
} & UIMessageStreamResponseInit): Promise<void> {
|
|
31
32
|
let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
|
|
32
33
|
|
|
33
34
|
// when the consumeSseStream is provided, we need to tee the stream
|
|
@@ -39,7 +40,7 @@ export function pipeUIMessageStreamToResponse({
|
|
|
39
40
|
consumeSseStream({ stream: stream2 }); // no await (do not block the response)
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
writeToServerResponse({
|
|
43
|
+
return writeToServerResponse({
|
|
43
44
|
response,
|
|
44
45
|
status,
|
|
45
46
|
statusText,
|
|
@@ -168,31 +168,54 @@ export const videoMediaTypeSignatures = [
|
|
|
168
168
|
},
|
|
169
169
|
] as const;
|
|
170
170
|
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
const DEFAULT_SNIFF_BYTES = 18;
|
|
172
|
+
|
|
173
|
+
// Longest signature prefix in the tables above (e.g. image/avif = 12 bytes).
|
|
174
|
+
const MAX_SIGNATURE_BYTES = 12;
|
|
175
|
+
|
|
176
|
+
// Largest ID3v2 tag (10-byte header + body) skipped to reach the audio frame.
|
|
177
|
+
// Covers typical tags including embedded cover art while keeping the decode
|
|
178
|
+
// bounded and O(1) in the attachment size. Exported for boundary tests.
|
|
179
|
+
export const MAX_ID3_TAG_BYTES = 128 * 1024;
|
|
180
|
+
|
|
181
|
+
// Total prefix decoded when an ID3 tag is present: the tag plus room for the
|
|
182
|
+
// trailing signature, so a tag right at the size limit stays detectable.
|
|
183
|
+
const ID3_SCAN_BYTES = MAX_ID3_TAG_BYTES + MAX_SIGNATURE_BYTES;
|
|
184
|
+
|
|
185
|
+
// Decode/view exactly the first `maxBytes` bytes from the front of the input.
|
|
186
|
+
// The base64 and raw-byte paths yield the same length, so detection does not
|
|
187
|
+
// depend on the input's representation.
|
|
188
|
+
function decodePrefix(data: Uint8Array | string, maxBytes: number): Uint8Array {
|
|
189
|
+
if (typeof data !== 'string') {
|
|
190
|
+
return data.length > maxBytes ? data.subarray(0, maxBytes) : data;
|
|
191
|
+
}
|
|
192
|
+
// base64: 4 chars -> 3 bytes. Decode whole 4-char groups, then trim the 0-2
|
|
193
|
+
// extra bytes so the result matches the raw-byte path exactly.
|
|
194
|
+
const maxChars = Math.ceil(maxBytes / 3) * 4;
|
|
195
|
+
const bytes = convertBase64ToUint8Array(
|
|
196
|
+
data.substring(0, Math.min(data.length, maxChars)),
|
|
197
|
+
);
|
|
198
|
+
return bytes.length > maxBytes ? bytes.subarray(0, maxBytes) : bytes;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function hasID3(bytes: Uint8Array): boolean {
|
|
202
|
+
return (
|
|
203
|
+
bytes.length > 10 &&
|
|
204
|
+
bytes[0] === 0x49 && // 'I'
|
|
205
|
+
bytes[1] === 0x44 && // 'D'
|
|
206
|
+
bytes[2] === 0x33 // '3'
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const stripID3 = (bytes: Uint8Array): Uint8Array => {
|
|
174
211
|
const id3Size =
|
|
175
212
|
((bytes[6] & 0x7f) << 21) |
|
|
176
213
|
((bytes[7] & 0x7f) << 14) |
|
|
177
214
|
((bytes[8] & 0x7f) << 7) |
|
|
178
215
|
(bytes[9] & 0x7f);
|
|
179
|
-
|
|
180
|
-
// The raw MP3 starts here
|
|
181
|
-
return bytes.slice(id3Size + 10);
|
|
216
|
+
return bytes.subarray(id3Size + 10);
|
|
182
217
|
};
|
|
183
218
|
|
|
184
|
-
function stripID3TagsIfPresent(data: Uint8Array | string): Uint8Array | string {
|
|
185
|
-
const hasId3 =
|
|
186
|
-
(typeof data === 'string' && data.startsWith('SUQz')) ||
|
|
187
|
-
(typeof data !== 'string' &&
|
|
188
|
-
data.length > 10 &&
|
|
189
|
-
data[0] === 0x49 && // 'I'
|
|
190
|
-
data[1] === 0x44 && // 'D'
|
|
191
|
-
data[2] === 0x33); // '3'
|
|
192
|
-
|
|
193
|
-
return hasId3 ? stripID3(data) : data;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
219
|
/**
|
|
197
220
|
* Detect the media IANA media type of a file using a list of signatures.
|
|
198
221
|
*
|
|
@@ -210,15 +233,13 @@ export function detectMediaType({
|
|
|
210
233
|
| typeof imageMediaTypeSignatures
|
|
211
234
|
| typeof videoMediaTypeSignatures;
|
|
212
235
|
}): (typeof signatures)[number]['mediaType'] | undefined {
|
|
213
|
-
|
|
236
|
+
let bytes = decodePrefix(data, DEFAULT_SNIFF_BYTES);
|
|
214
237
|
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
)
|
|
221
|
-
: processedData;
|
|
238
|
+
// ID3v2-tagged MP3s carry the audio frame after the tag; scan a bounded
|
|
239
|
+
// prefix past it rather than decoding the whole input.
|
|
240
|
+
if (hasID3(bytes)) {
|
|
241
|
+
bytes = stripID3(decodePrefix(data, ID3_SCAN_BYTES));
|
|
242
|
+
}
|
|
222
243
|
|
|
223
244
|
for (const signature of signatures) {
|
|
224
245
|
if (
|
|
@@ -15,7 +15,7 @@ export function writeToServerResponse({
|
|
|
15
15
|
statusText?: string;
|
|
16
16
|
headers?: Record<string, string | number | string[]>;
|
|
17
17
|
stream: ReadableStream<Uint8Array>;
|
|
18
|
-
}): void {
|
|
18
|
+
}): Promise<void> {
|
|
19
19
|
const statusCode = status ?? 200;
|
|
20
20
|
if (statusText !== undefined) {
|
|
21
21
|
response.writeHead(statusCode, statusText, headers);
|
|
@@ -45,5 +45,5 @@ export function writeToServerResponse({
|
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
read();
|
|
48
|
+
return read();
|
|
49
49
|
}
|