@ai-sdk/xai 3.0.112 → 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 +14 -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/docs/01-xai.mdx +24 -18
- package/package.json +3 -3
- package/src/xai-video-model.ts +68 -3
package/docs/01-xai.mdx
CHANGED
|
@@ -99,6 +99,26 @@ xAI language models can also be used in the `streamText` function
|
|
|
99
99
|
and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output)
|
|
100
100
|
(see [AI SDK Core](/docs/ai-sdk-core)).
|
|
101
101
|
|
|
102
|
+
### Reasoning Effort
|
|
103
|
+
|
|
104
|
+
For models with configurable reasoning, you can control how much effort the
|
|
105
|
+
model spends thinking before responding with
|
|
106
|
+
`providerOptions.xai.reasoningEffort`. The AI SDK option accepts `'none'`,
|
|
107
|
+
`'low'`, `'medium'`, and `'high'`, but each xAI model supports a subset.
|
|
108
|
+
|
|
109
|
+
<Note>
|
|
110
|
+
Support and defaults are model-specific. `grok-4.3` supports `'none'`,
|
|
111
|
+
`'low'`, `'medium'`, and `'high'`. `grok-4.5` supports `'low'`, `'medium'`,
|
|
112
|
+
and `'high'`, defaults to `'high'`, and cannot disable reasoning. The
|
|
113
|
+
`grok-4.20-reasoning` and `grok-4.20-non-reasoning` variants do not accept
|
|
114
|
+
this option, and neither does `grok-build-0.1`. For
|
|
115
|
+
`grok-4.20-multi-agent`, `'low'`, `'medium'`, and `'high'` control the number
|
|
116
|
+
of agents instead of reasoning depth. See xAI's [reasoning
|
|
117
|
+
docs](https://docs.x.ai/developers/model-capabilities/text/reasoning) and
|
|
118
|
+
[Grok 4.3 model page](https://docs.x.ai/developers/models/grok-4.3) for
|
|
119
|
+
current details.
|
|
120
|
+
</Note>
|
|
121
|
+
|
|
102
122
|
### Provider Options
|
|
103
123
|
|
|
104
124
|
xAI chat models support additional provider options that are not part of
|
|
@@ -107,7 +127,7 @@ the [standard call settings](/docs/ai-sdk-core/settings). You can pass them in t
|
|
|
107
127
|
```ts
|
|
108
128
|
import { xai, type XaiLanguageModelChatOptions } from '@ai-sdk/xai';
|
|
109
129
|
|
|
110
|
-
const model = xai('grok-
|
|
130
|
+
const model = xai('grok-4.5');
|
|
111
131
|
|
|
112
132
|
await generateText({
|
|
113
133
|
model,
|
|
@@ -123,14 +143,7 @@ The following optional provider options are available for xAI chat models:
|
|
|
123
143
|
|
|
124
144
|
- **reasoningEffort** _'none' | 'low' | 'medium' | 'high'_
|
|
125
145
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<Note>
|
|
129
|
-
Not every Grok model accepts every reasoning effort, for example
|
|
130
|
-
`grok-build-0.1` does not support reasoning effort. See xAI's [reasoning
|
|
131
|
-
docs](https://docs.x.ai/docs/guides/reasoning) for the values each model
|
|
132
|
-
accepts.
|
|
133
|
-
</Note>
|
|
146
|
+
Control the reasoning effort for supported models. See [Reasoning Effort](#reasoning-effort) for model-specific values and defaults.
|
|
134
147
|
|
|
135
148
|
- **logprobs** _boolean_
|
|
136
149
|
|
|
@@ -485,7 +498,7 @@ import { xai, type XaiLanguageModelResponsesOptions } from '@ai-sdk/xai';
|
|
|
485
498
|
import { generateText } from 'ai';
|
|
486
499
|
|
|
487
500
|
const result = await generateText({
|
|
488
|
-
model: xai.responses('grok-4.
|
|
501
|
+
model: xai.responses('grok-4.5'),
|
|
489
502
|
providerOptions: {
|
|
490
503
|
xai: {
|
|
491
504
|
reasoningEffort: 'high',
|
|
@@ -499,14 +512,7 @@ The following provider options are available:
|
|
|
499
512
|
|
|
500
513
|
- **reasoningEffort** _'none' | 'low' | 'medium' | 'high'_
|
|
501
514
|
|
|
502
|
-
Control the reasoning effort for
|
|
503
|
-
|
|
504
|
-
<Note>
|
|
505
|
-
Not every Grok model accepts every reasoning effort, for example
|
|
506
|
-
`grok-build-0.1` does not support reasoning effort. See xAI's [reasoning
|
|
507
|
-
docs](https://docs.x.ai/docs/guides/reasoning) for the values each model
|
|
508
|
-
accepts.
|
|
509
|
-
</Note>
|
|
515
|
+
Control the reasoning effort for supported models. See [Reasoning Effort](#reasoning-effort) for model-specific values and defaults.
|
|
510
516
|
|
|
511
517
|
- **logprobs** _boolean_
|
|
512
518
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.114",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/openai-compatible": "2.0.
|
|
32
|
+
"@ai-sdk/openai-compatible": "2.0.63",
|
|
33
33
|
"@ai-sdk/provider": "3.0.14",
|
|
34
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
34
|
+
"@ai-sdk/provider-utils": "4.0.41"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "20.17.24",
|
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
|
|