@ai-sdk/xai 4.0.21 → 4.0.22
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.js +56 -8
- package/dist/index.js.map +1 -1
- package/docs/01-xai.mdx +19 -14
- package/package.json +3 -3
- package/src/xai-video-model.ts +68 -3
package/docs/01-xai.mdx
CHANGED
|
@@ -92,10 +92,10 @@ and support structured data generation with [`Output`](/docs/reference/ai-sdk-co
|
|
|
92
92
|
|
|
93
93
|
### Reasoning Effort
|
|
94
94
|
|
|
95
|
-
For reasoning
|
|
96
|
-
thinking before responding via
|
|
97
|
-
works for both the Responses API
|
|
98
|
-
(`xai.chat()`).
|
|
95
|
+
For models with configurable reasoning, you can control how much effort the
|
|
96
|
+
model spends thinking before responding via
|
|
97
|
+
`providerOptions.xai.reasoningEffort`. This works for both the Responses API
|
|
98
|
+
(default) and the Chat Completions API (`xai.chat()`).
|
|
99
99
|
|
|
100
100
|
```ts
|
|
101
101
|
import { xai } from '@ai-sdk/xai';
|
|
@@ -110,13 +110,12 @@ const { text } = await generateText({
|
|
|
110
110
|
});
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
The AI SDK option accepts these values, but each xAI model supports a subset:
|
|
114
114
|
|
|
115
115
|
- `'none'` — Disables reasoning entirely; no thinking tokens are used. Best
|
|
116
|
-
for simple use cases that need a near-instant response.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
general agentic use and tool calling.
|
|
116
|
+
for simple use cases that need a near-instant response.
|
|
117
|
+
- `'low'` — Uses some reasoning tokens, but still fast. Good for general
|
|
118
|
+
agentic use and tool calling.
|
|
120
119
|
- `'medium'` — More thinking for less-latency-sensitive applications such as
|
|
121
120
|
complex data analysis and long-context reasoning.
|
|
122
121
|
- `'high'` — More reasoning tokens for deeper thinking. Suited for very
|
|
@@ -124,9 +123,15 @@ Supported values:
|
|
|
124
123
|
tasks.
|
|
125
124
|
|
|
126
125
|
<Note>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
Support and defaults are model-specific. `grok-4.3` supports `'none'`,
|
|
127
|
+
`'low'`, `'medium'`, and `'high'`. `grok-4.5` supports `'low'`, `'medium'`,
|
|
128
|
+
and `'high'`, defaults to `'high'`, and cannot disable reasoning. The
|
|
129
|
+
`grok-4.20-reasoning` and `grok-4.20-non-reasoning` variants do not accept
|
|
130
|
+
this option. For `grok-4.20-multi-agent`, `'low'`, `'medium'`, and `'high'`
|
|
131
|
+
control the number of agents instead of reasoning depth. See xAI's [reasoning
|
|
132
|
+
docs](https://docs.x.ai/developers/model-capabilities/text/reasoning) and
|
|
133
|
+
[Grok 4.3 model page](https://docs.x.ai/developers/models/grok-4.3) for
|
|
134
|
+
current details.
|
|
130
135
|
</Note>
|
|
131
136
|
|
|
132
137
|
## Realtime Models
|
|
@@ -499,7 +504,7 @@ import { xai, type XaiLanguageModelResponsesOptions } from '@ai-sdk/xai';
|
|
|
499
504
|
import { generateText } from 'ai';
|
|
500
505
|
|
|
501
506
|
const result = await generateText({
|
|
502
|
-
model: xai.responses('grok-4.
|
|
507
|
+
model: xai.responses('grok-4.5'),
|
|
503
508
|
providerOptions: {
|
|
504
509
|
xai: {
|
|
505
510
|
reasoningEffort: 'high',
|
|
@@ -513,7 +518,7 @@ The following provider options are available:
|
|
|
513
518
|
|
|
514
519
|
- **reasoningEffort** _'none' | 'low' | 'medium' | 'high'_
|
|
515
520
|
|
|
516
|
-
Control the reasoning effort for
|
|
521
|
+
Control the reasoning effort for supported models. See [Reasoning Effort](#reasoning-effort) for model-specific values and defaults.
|
|
517
522
|
|
|
518
523
|
- **logprobs** _boolean_
|
|
519
524
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@ai-sdk/openai-compatible": "3.0.17",
|
|
32
33
|
"@ai-sdk/provider": "4.0.4",
|
|
33
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
34
|
-
"@ai-sdk/openai-compatible": "3.0.16"
|
|
34
|
+
"@ai-sdk/provider-utils": "5.0.15"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "22.19.19",
|
package/src/xai-video-model.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AISDKError,
|
|
3
|
+
APICallError,
|
|
3
4
|
type Experimental_VideoModelV4,
|
|
4
5
|
type Experimental_VideoModelV4File,
|
|
5
6
|
type SharedV4Warning,
|
|
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
|
getTopLevelMediaType,
|
|
16
16
|
parseProviderOptions,
|
|
17
17
|
postJsonToApi,
|
|
18
|
+
safeParseJSON,
|
|
18
19
|
type FetchFunction,
|
|
19
20
|
type ResponseHandler,
|
|
20
21
|
} from '@ai-sdk/provider-utils';
|
|
@@ -549,16 +550,80 @@ const xaiVideoStatusJsonResponseHandler = createJsonResponseHandler(
|
|
|
549
550
|
xaiVideoStatusResponseSchema,
|
|
550
551
|
);
|
|
551
552
|
|
|
553
|
+
// Generous bound for a `{status, progress}` payload of ~50 bytes.
|
|
554
|
+
const MAX_PENDING_BODY_BYTES = 1024 * 1024;
|
|
555
|
+
|
|
556
|
+
const textDecoder = new TextDecoder();
|
|
557
|
+
|
|
558
|
+
// Bounded replacement for `response.text()`. Throws on overflow without
|
|
559
|
+
// cancelling the body: cancelling a tee branch neither settles nor releases
|
|
560
|
+
// the underlying source while the sibling branch is live.
|
|
561
|
+
async function readPendingBody({
|
|
562
|
+
response,
|
|
563
|
+
url,
|
|
564
|
+
requestBodyValues,
|
|
565
|
+
}: Parameters<ResponseHandler<unknown>>[0]): Promise<string> {
|
|
566
|
+
if (response.body == null) {
|
|
567
|
+
return '';
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const reader = response.body.getReader();
|
|
571
|
+
const chunks: Uint8Array[] = [];
|
|
572
|
+
let totalBytes = 0;
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
while (true) {
|
|
576
|
+
const { done, value } = await reader.read();
|
|
577
|
+
if (done) break;
|
|
578
|
+
|
|
579
|
+
totalBytes += value.length;
|
|
580
|
+
if (totalBytes > MAX_PENDING_BODY_BYTES) {
|
|
581
|
+
throw new APICallError({
|
|
582
|
+
message: `xAI video status response exceeded ${MAX_PENDING_BODY_BYTES} bytes`,
|
|
583
|
+
url,
|
|
584
|
+
requestBodyValues,
|
|
585
|
+
statusCode: response.status,
|
|
586
|
+
responseHeaders: extractResponseHeaders(response),
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
chunks.push(value);
|
|
591
|
+
}
|
|
592
|
+
} finally {
|
|
593
|
+
reader.releaseLock();
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const merged = new Uint8Array(totalBytes);
|
|
597
|
+
let offset = 0;
|
|
598
|
+
for (const chunk of chunks) {
|
|
599
|
+
merged.set(chunk, offset);
|
|
600
|
+
offset += chunk.length;
|
|
601
|
+
}
|
|
602
|
+
return textDecoder.decode(merged);
|
|
603
|
+
}
|
|
604
|
+
|
|
552
605
|
const xaiVideoStatusResponseHandler: ResponseHandler<
|
|
553
606
|
z.infer<typeof xaiVideoStatusResponseSchema>
|
|
554
607
|
> = async options => {
|
|
608
|
+
// xAI answers 202 while a generation is still running, sometimes with an
|
|
609
|
+
// empty body. Read it rather than cancelling: `body.cancel()` never settles
|
|
610
|
+
// on a tee branch, which `Response.clone()` in fetch instrumentation creates.
|
|
555
611
|
if (options.response.status === 202) {
|
|
556
612
|
const responseHeaders = extractResponseHeaders(options.response);
|
|
557
|
-
await
|
|
613
|
+
const text = await readPendingBody(options);
|
|
614
|
+
|
|
615
|
+
if (text.trim().length === 0) {
|
|
616
|
+
return { responseHeaders, value: { status: 'pending' } };
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const parsed = await safeParseJSON({
|
|
620
|
+
text,
|
|
621
|
+
schema: xaiVideoStatusResponseSchema,
|
|
622
|
+
});
|
|
558
623
|
|
|
559
624
|
return {
|
|
560
625
|
responseHeaders,
|
|
561
|
-
value: { status: 'pending' },
|
|
626
|
+
value: parsed.success ? parsed.value : { status: 'pending' },
|
|
562
627
|
};
|
|
563
628
|
}
|
|
564
629
|
|