@ai-sdk/xai 3.0.113 → 3.0.114
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 +6 -0
- package/dist/index.js +50 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/xai-video-model.ts +68 -3
package/package.json
CHANGED
package/src/xai-video-model.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AISDKError,
|
|
3
|
+
APICallError,
|
|
3
4
|
type Experimental_VideoModelV3,
|
|
4
5
|
type Experimental_VideoModelV3File,
|
|
5
6
|
type SharedV3Warning,
|
|
6
7
|
} from '@ai-sdk/provider';
|
|
7
8
|
import {
|
|
8
|
-
cancelResponseBody,
|
|
9
9
|
combineHeaders,
|
|
10
10
|
convertUint8ArrayToBase64,
|
|
11
11
|
createJsonResponseHandler,
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
getFromApi,
|
|
16
16
|
parseProviderOptions,
|
|
17
17
|
postJsonToApi,
|
|
18
|
+
safeParseJSON,
|
|
18
19
|
type ResponseHandler,
|
|
19
20
|
} from '@ai-sdk/provider-utils';
|
|
20
21
|
import { z } from 'zod/v4';
|
|
@@ -552,16 +553,80 @@ const xaiVideoStatusJsonResponseHandler = createJsonResponseHandler(
|
|
|
552
553
|
xaiVideoStatusResponseSchema,
|
|
553
554
|
);
|
|
554
555
|
|
|
556
|
+
// Generous bound for a `{status, progress}` payload of ~50 bytes.
|
|
557
|
+
const MAX_PENDING_BODY_BYTES = 1024 * 1024;
|
|
558
|
+
|
|
559
|
+
const textDecoder = new TextDecoder();
|
|
560
|
+
|
|
561
|
+
// Bounded replacement for `response.text()`. Throws on overflow without
|
|
562
|
+
// cancelling the body: cancelling a tee branch neither settles nor releases
|
|
563
|
+
// the underlying source while the sibling branch is live.
|
|
564
|
+
async function readPendingBody({
|
|
565
|
+
response,
|
|
566
|
+
url,
|
|
567
|
+
requestBodyValues,
|
|
568
|
+
}: Parameters<ResponseHandler<unknown>>[0]): Promise<string> {
|
|
569
|
+
if (response.body == null) {
|
|
570
|
+
return '';
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const reader = response.body.getReader();
|
|
574
|
+
const chunks: Uint8Array[] = [];
|
|
575
|
+
let totalBytes = 0;
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
while (true) {
|
|
579
|
+
const { done, value } = await reader.read();
|
|
580
|
+
if (done) break;
|
|
581
|
+
|
|
582
|
+
totalBytes += value.length;
|
|
583
|
+
if (totalBytes > MAX_PENDING_BODY_BYTES) {
|
|
584
|
+
throw new APICallError({
|
|
585
|
+
message: `xAI video status response exceeded ${MAX_PENDING_BODY_BYTES} bytes`,
|
|
586
|
+
url,
|
|
587
|
+
requestBodyValues,
|
|
588
|
+
statusCode: response.status,
|
|
589
|
+
responseHeaders: extractResponseHeaders(response),
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
chunks.push(value);
|
|
594
|
+
}
|
|
595
|
+
} finally {
|
|
596
|
+
reader.releaseLock();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const merged = new Uint8Array(totalBytes);
|
|
600
|
+
let offset = 0;
|
|
601
|
+
for (const chunk of chunks) {
|
|
602
|
+
merged.set(chunk, offset);
|
|
603
|
+
offset += chunk.length;
|
|
604
|
+
}
|
|
605
|
+
return textDecoder.decode(merged);
|
|
606
|
+
}
|
|
607
|
+
|
|
555
608
|
const xaiVideoStatusResponseHandler: ResponseHandler<
|
|
556
609
|
z.infer<typeof xaiVideoStatusResponseSchema>
|
|
557
610
|
> = async options => {
|
|
611
|
+
// xAI answers 202 while a generation is still running, sometimes with an
|
|
612
|
+
// empty body. Read it rather than cancelling: `body.cancel()` never settles
|
|
613
|
+
// on a tee branch, which `Response.clone()` in fetch instrumentation creates.
|
|
558
614
|
if (options.response.status === 202) {
|
|
559
615
|
const responseHeaders = extractResponseHeaders(options.response);
|
|
560
|
-
await
|
|
616
|
+
const text = await readPendingBody(options);
|
|
617
|
+
|
|
618
|
+
if (text.trim().length === 0) {
|
|
619
|
+
return { responseHeaders, value: { status: 'pending' } };
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const parsed = await safeParseJSON({
|
|
623
|
+
text,
|
|
624
|
+
schema: xaiVideoStatusResponseSchema,
|
|
625
|
+
});
|
|
561
626
|
|
|
562
627
|
return {
|
|
563
628
|
responseHeaders,
|
|
564
|
-
value: { status: 'pending' },
|
|
629
|
+
value: parsed.success ? parsed.value : { status: 'pending' },
|
|
565
630
|
};
|
|
566
631
|
}
|
|
567
632
|
|