@ai-sdk/xai 0.0.0-1c33ba03-20260114162300 → 0.0.0-4115c213-20260122152721
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 +65 -4
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/docs/01-xai.mdx +697 -0
- package/package.json +15 -6
- package/src/convert-to-xai-chat-messages.ts +142 -0
- package/src/convert-xai-chat-usage.ts +23 -0
- package/src/get-response-metadata.ts +19 -0
- package/src/index.ts +14 -0
- package/src/map-xai-finish-reason.ts +19 -0
- package/src/responses/convert-to-xai-responses-input.ts +206 -0
- package/src/responses/convert-xai-responses-usage.ts +24 -0
- package/src/responses/map-xai-responses-finish-reason.ts +20 -0
- package/src/responses/xai-responses-api.ts +393 -0
- package/src/responses/xai-responses-language-model.ts +732 -0
- package/src/responses/xai-responses-options.ts +34 -0
- package/src/responses/xai-responses-prepare-tools.ts +226 -0
- package/src/tool/code-execution.ts +17 -0
- package/src/tool/index.ts +15 -0
- package/src/tool/view-image.ts +20 -0
- package/src/tool/view-x-video.ts +18 -0
- package/src/tool/web-search.ts +56 -0
- package/src/tool/x-search.ts +63 -0
- package/src/version.ts +6 -0
- package/src/xai-chat-language-model.ts +681 -0
- package/src/xai-chat-options.ts +131 -0
- package/src/xai-chat-prompt.ts +44 -0
- package/src/xai-error.ts +19 -0
- package/src/xai-image-settings.ts +1 -0
- package/src/xai-prepare-tools.ts +95 -0
- package/src/xai-provider.ts +162 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
// https://console.x.ai and see "View models"
|
|
4
|
+
export type XaiChatModelId =
|
|
5
|
+
| 'grok-4-1'
|
|
6
|
+
| 'grok-4-1-fast-reasoning'
|
|
7
|
+
| 'grok-4-1-fast-non-reasoning'
|
|
8
|
+
| 'grok-4-fast-non-reasoning'
|
|
9
|
+
| 'grok-4-fast-reasoning'
|
|
10
|
+
| 'grok-code-fast-1'
|
|
11
|
+
| 'grok-4'
|
|
12
|
+
| 'grok-4-0709'
|
|
13
|
+
| 'grok-4-latest'
|
|
14
|
+
| 'grok-3'
|
|
15
|
+
| 'grok-3-latest'
|
|
16
|
+
| 'grok-3-fast'
|
|
17
|
+
| 'grok-3-fast-latest'
|
|
18
|
+
| 'grok-3-mini'
|
|
19
|
+
| 'grok-3-mini-latest'
|
|
20
|
+
| 'grok-3-mini-fast'
|
|
21
|
+
| 'grok-3-mini-fast-latest'
|
|
22
|
+
| 'grok-2-vision-1212'
|
|
23
|
+
| 'grok-2-vision'
|
|
24
|
+
| 'grok-2-vision-latest'
|
|
25
|
+
| 'grok-2-image-1212'
|
|
26
|
+
| 'grok-2-image'
|
|
27
|
+
| 'grok-2-image-latest'
|
|
28
|
+
| 'grok-2-1212'
|
|
29
|
+
| 'grok-2'
|
|
30
|
+
| 'grok-2-latest'
|
|
31
|
+
| 'grok-vision-beta'
|
|
32
|
+
| 'grok-beta'
|
|
33
|
+
| (string & {});
|
|
34
|
+
|
|
35
|
+
// search source schemas
|
|
36
|
+
const webSourceSchema = z.object({
|
|
37
|
+
type: z.literal('web'),
|
|
38
|
+
country: z.string().length(2).optional(),
|
|
39
|
+
excludedWebsites: z.array(z.string()).max(5).optional(),
|
|
40
|
+
allowedWebsites: z.array(z.string()).max(5).optional(),
|
|
41
|
+
safeSearch: z.boolean().optional(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const xSourceSchema = z.object({
|
|
45
|
+
type: z.literal('x'),
|
|
46
|
+
excludedXHandles: z.array(z.string()).optional(),
|
|
47
|
+
includedXHandles: z.array(z.string()).optional(),
|
|
48
|
+
postFavoriteCount: z.number().int().optional(),
|
|
49
|
+
postViewCount: z.number().int().optional(),
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated use `includedXHandles` instead
|
|
52
|
+
*/
|
|
53
|
+
xHandles: z.array(z.string()).optional(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const newsSourceSchema = z.object({
|
|
57
|
+
type: z.literal('news'),
|
|
58
|
+
country: z.string().length(2).optional(),
|
|
59
|
+
excludedWebsites: z.array(z.string()).max(5).optional(),
|
|
60
|
+
safeSearch: z.boolean().optional(),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const rssSourceSchema = z.object({
|
|
64
|
+
type: z.literal('rss'),
|
|
65
|
+
links: z.array(z.string().url()).max(1), // currently only supports one RSS link
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const searchSourceSchema = z.discriminatedUnion('type', [
|
|
69
|
+
webSourceSchema,
|
|
70
|
+
xSourceSchema,
|
|
71
|
+
newsSourceSchema,
|
|
72
|
+
rssSourceSchema,
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
// xai-specific provider options
|
|
76
|
+
export const xaiProviderOptions = z.object({
|
|
77
|
+
reasoningEffort: z.enum(['low', 'high']).optional(),
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Whether to enable parallel function calling during tool use.
|
|
81
|
+
* When true, the model can call multiple functions in parallel.
|
|
82
|
+
* When false, the model will call functions sequentially.
|
|
83
|
+
* Defaults to true.
|
|
84
|
+
*/
|
|
85
|
+
parallel_function_calling: z.boolean().optional(),
|
|
86
|
+
|
|
87
|
+
searchParameters: z
|
|
88
|
+
.object({
|
|
89
|
+
/**
|
|
90
|
+
* search mode preference
|
|
91
|
+
* - "off": disables search completely
|
|
92
|
+
* - "auto": model decides whether to search (default)
|
|
93
|
+
* - "on": always enables search
|
|
94
|
+
*/
|
|
95
|
+
mode: z.enum(['off', 'auto', 'on']),
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* whether to return citations in the response
|
|
99
|
+
* defaults to true
|
|
100
|
+
*/
|
|
101
|
+
returnCitations: z.boolean().optional(),
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* start date for search data (ISO8601 format: YYYY-MM-DD)
|
|
105
|
+
*/
|
|
106
|
+
fromDate: z.string().optional(),
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* end date for search data (ISO8601 format: YYYY-MM-DD)
|
|
110
|
+
*/
|
|
111
|
+
toDate: z.string().optional(),
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* maximum number of search results to consider
|
|
115
|
+
* defaults to 20
|
|
116
|
+
*/
|
|
117
|
+
maxSearchResults: z.number().min(1).max(50).optional(),
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* data sources to search from.
|
|
121
|
+
* defaults to [{ type: 'web' }, { type: 'x' }] if not specified.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* sources: [{ type: 'web', country: 'US' }, { type: 'x' }]
|
|
125
|
+
*/
|
|
126
|
+
sources: z.array(searchSourceSchema).optional(),
|
|
127
|
+
})
|
|
128
|
+
.optional(),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
export type XaiProviderOptions = z.infer<typeof xaiProviderOptions>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type XaiChatPrompt = Array<XaiChatMessage>;
|
|
2
|
+
|
|
3
|
+
export type XaiChatMessage =
|
|
4
|
+
| XaiSystemMessage
|
|
5
|
+
| XaiUserMessage
|
|
6
|
+
| XaiAssistantMessage
|
|
7
|
+
| XaiToolMessage;
|
|
8
|
+
|
|
9
|
+
export interface XaiSystemMessage {
|
|
10
|
+
role: 'system';
|
|
11
|
+
content: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface XaiUserMessage {
|
|
15
|
+
role: 'user';
|
|
16
|
+
content: string | Array<XaiUserMessageContent>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type XaiUserMessageContent =
|
|
20
|
+
| { type: 'text'; text: string }
|
|
21
|
+
| { type: 'image_url'; image_url: { url: string } };
|
|
22
|
+
|
|
23
|
+
export interface XaiAssistantMessage {
|
|
24
|
+
role: 'assistant';
|
|
25
|
+
content: string;
|
|
26
|
+
tool_calls?: Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
type: 'function';
|
|
29
|
+
function: { name: string; arguments: string };
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface XaiToolMessage {
|
|
34
|
+
role: 'tool';
|
|
35
|
+
tool_call_id: string;
|
|
36
|
+
content: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// xai tool choice
|
|
40
|
+
export type XaiToolChoice =
|
|
41
|
+
| 'auto'
|
|
42
|
+
| 'none'
|
|
43
|
+
| 'required'
|
|
44
|
+
| { type: 'function'; function: { name: string } };
|
package/src/xai-error.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
3
|
+
|
|
4
|
+
// Add error schema and structure
|
|
5
|
+
export const xaiErrorDataSchema = z.object({
|
|
6
|
+
error: z.object({
|
|
7
|
+
message: z.string(),
|
|
8
|
+
type: z.string().nullish(),
|
|
9
|
+
param: z.any().nullish(),
|
|
10
|
+
code: z.union([z.string(), z.number()]).nullish(),
|
|
11
|
+
}),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export type XaiErrorData = z.infer<typeof xaiErrorDataSchema>;
|
|
15
|
+
|
|
16
|
+
export const xaiFailedResponseHandler = createJsonErrorResponseHandler({
|
|
17
|
+
errorSchema: xaiErrorDataSchema,
|
|
18
|
+
errorToMessage: data => data.error.message,
|
|
19
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type XaiImageModelId = 'grok-2-image' | (string & {});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LanguageModelV3CallOptions,
|
|
3
|
+
SharedV3Warning,
|
|
4
|
+
UnsupportedFunctionalityError,
|
|
5
|
+
} from '@ai-sdk/provider';
|
|
6
|
+
import { XaiToolChoice } from './xai-chat-prompt';
|
|
7
|
+
|
|
8
|
+
export function prepareTools({
|
|
9
|
+
tools,
|
|
10
|
+
toolChoice,
|
|
11
|
+
}: {
|
|
12
|
+
tools: LanguageModelV3CallOptions['tools'];
|
|
13
|
+
toolChoice?: LanguageModelV3CallOptions['toolChoice'];
|
|
14
|
+
}): {
|
|
15
|
+
tools:
|
|
16
|
+
| Array<{
|
|
17
|
+
type: 'function';
|
|
18
|
+
function: {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string | undefined;
|
|
21
|
+
parameters: unknown;
|
|
22
|
+
};
|
|
23
|
+
}>
|
|
24
|
+
| undefined;
|
|
25
|
+
toolChoice: XaiToolChoice | undefined;
|
|
26
|
+
toolWarnings: SharedV3Warning[];
|
|
27
|
+
} {
|
|
28
|
+
// when the tools array is empty, change it to undefined to prevent errors
|
|
29
|
+
tools = tools?.length ? tools : undefined;
|
|
30
|
+
|
|
31
|
+
const toolWarnings: SharedV3Warning[] = [];
|
|
32
|
+
|
|
33
|
+
if (tools == null) {
|
|
34
|
+
return { tools: undefined, toolChoice: undefined, toolWarnings };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// convert ai sdk tools to xai format
|
|
38
|
+
const xaiTools: Array<{
|
|
39
|
+
type: 'function';
|
|
40
|
+
function: {
|
|
41
|
+
name: string;
|
|
42
|
+
description: string | undefined;
|
|
43
|
+
parameters: unknown;
|
|
44
|
+
};
|
|
45
|
+
}> = [];
|
|
46
|
+
|
|
47
|
+
for (const tool of tools) {
|
|
48
|
+
if (tool.type === 'provider') {
|
|
49
|
+
toolWarnings.push({
|
|
50
|
+
type: 'unsupported',
|
|
51
|
+
feature: `provider-defined tool ${tool.name}`,
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
xaiTools.push({
|
|
55
|
+
type: 'function',
|
|
56
|
+
function: {
|
|
57
|
+
name: tool.name,
|
|
58
|
+
description: tool.description,
|
|
59
|
+
parameters: tool.inputSchema,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (toolChoice == null) {
|
|
66
|
+
return { tools: xaiTools, toolChoice: undefined, toolWarnings };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const type = toolChoice.type;
|
|
70
|
+
|
|
71
|
+
switch (type) {
|
|
72
|
+
case 'auto':
|
|
73
|
+
case 'none':
|
|
74
|
+
return { tools: xaiTools, toolChoice: type, toolWarnings };
|
|
75
|
+
case 'required':
|
|
76
|
+
// xai supports 'required' directly
|
|
77
|
+
return { tools: xaiTools, toolChoice: 'required', toolWarnings };
|
|
78
|
+
case 'tool':
|
|
79
|
+
// xai supports specific tool selection
|
|
80
|
+
return {
|
|
81
|
+
tools: xaiTools,
|
|
82
|
+
toolChoice: {
|
|
83
|
+
type: 'function',
|
|
84
|
+
function: { name: toolChoice.toolName },
|
|
85
|
+
},
|
|
86
|
+
toolWarnings,
|
|
87
|
+
};
|
|
88
|
+
default: {
|
|
89
|
+
const _exhaustiveCheck: never = type;
|
|
90
|
+
throw new UnsupportedFunctionalityError({
|
|
91
|
+
functionality: `tool choice type: ${_exhaustiveCheck}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAICompatibleImageModel,
|
|
3
|
+
ProviderErrorStructure,
|
|
4
|
+
} from '@ai-sdk/openai-compatible';
|
|
5
|
+
import {
|
|
6
|
+
ImageModelV3,
|
|
7
|
+
LanguageModelV3,
|
|
8
|
+
NoSuchModelError,
|
|
9
|
+
ProviderV3,
|
|
10
|
+
} from '@ai-sdk/provider';
|
|
11
|
+
import {
|
|
12
|
+
FetchFunction,
|
|
13
|
+
generateId,
|
|
14
|
+
loadApiKey,
|
|
15
|
+
withoutTrailingSlash,
|
|
16
|
+
withUserAgentSuffix,
|
|
17
|
+
} from '@ai-sdk/provider-utils';
|
|
18
|
+
import { XaiChatLanguageModel } from './xai-chat-language-model';
|
|
19
|
+
import { XaiChatModelId } from './xai-chat-options';
|
|
20
|
+
import { XaiErrorData, xaiErrorDataSchema } from './xai-error';
|
|
21
|
+
import { XaiImageModelId } from './xai-image-settings';
|
|
22
|
+
import { XaiResponsesLanguageModel } from './responses/xai-responses-language-model';
|
|
23
|
+
import { XaiResponsesModelId } from './responses/xai-responses-options';
|
|
24
|
+
import { xaiTools } from './tool';
|
|
25
|
+
import { VERSION } from './version';
|
|
26
|
+
|
|
27
|
+
const xaiErrorStructure: ProviderErrorStructure<XaiErrorData> = {
|
|
28
|
+
errorSchema: xaiErrorDataSchema,
|
|
29
|
+
errorToMessage: data => data.error.message,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export interface XaiProvider extends ProviderV3 {
|
|
33
|
+
/**
|
|
34
|
+
Creates an Xai chat model for text generation.
|
|
35
|
+
*/
|
|
36
|
+
(modelId: XaiChatModelId): LanguageModelV3;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
Creates an Xai language model for text generation.
|
|
40
|
+
*/
|
|
41
|
+
languageModel(modelId: XaiChatModelId): LanguageModelV3;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
Creates an Xai chat model for text generation.
|
|
45
|
+
*/
|
|
46
|
+
chat: (modelId: XaiChatModelId) => LanguageModelV3;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
Creates an Xai responses model for agentic tool calling.
|
|
50
|
+
*/
|
|
51
|
+
responses: (modelId: XaiResponsesModelId) => LanguageModelV3;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
Creates an Xai image model for image generation.
|
|
55
|
+
*/
|
|
56
|
+
image(modelId: XaiImageModelId): ImageModelV3;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
Creates an Xai image model for image generation.
|
|
60
|
+
*/
|
|
61
|
+
imageModel(modelId: XaiImageModelId): ImageModelV3;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
Server-side agentic tools for use with the responses API.
|
|
65
|
+
*/
|
|
66
|
+
tools: typeof xaiTools;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Use `embeddingModel` instead.
|
|
70
|
+
*/
|
|
71
|
+
textEmbeddingModel(modelId: string): never;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface XaiProviderSettings {
|
|
75
|
+
/**
|
|
76
|
+
Base URL for the xAI API calls.
|
|
77
|
+
*/
|
|
78
|
+
baseURL?: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
API key for authenticating requests.
|
|
82
|
+
*/
|
|
83
|
+
apiKey?: string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
Custom headers to include in the requests.
|
|
87
|
+
*/
|
|
88
|
+
headers?: Record<string, string>;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
Custom fetch implementation. You can use it as a middleware to intercept requests,
|
|
92
|
+
or to provide a custom fetch implementation for e.g. testing.
|
|
93
|
+
*/
|
|
94
|
+
fetch?: FetchFunction;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function createXai(options: XaiProviderSettings = {}): XaiProvider {
|
|
98
|
+
const baseURL = withoutTrailingSlash(
|
|
99
|
+
options.baseURL ?? 'https://api.x.ai/v1',
|
|
100
|
+
);
|
|
101
|
+
const getHeaders = () =>
|
|
102
|
+
withUserAgentSuffix(
|
|
103
|
+
{
|
|
104
|
+
Authorization: `Bearer ${loadApiKey({
|
|
105
|
+
apiKey: options.apiKey,
|
|
106
|
+
environmentVariableName: 'XAI_API_KEY',
|
|
107
|
+
description: 'xAI API key',
|
|
108
|
+
})}`,
|
|
109
|
+
...options.headers,
|
|
110
|
+
},
|
|
111
|
+
`ai-sdk/xai/${VERSION}`,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const createChatLanguageModel = (modelId: XaiChatModelId) => {
|
|
115
|
+
return new XaiChatLanguageModel(modelId, {
|
|
116
|
+
provider: 'xai.chat',
|
|
117
|
+
baseURL,
|
|
118
|
+
headers: getHeaders,
|
|
119
|
+
generateId,
|
|
120
|
+
fetch: options.fetch,
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const createResponsesLanguageModel = (modelId: XaiResponsesModelId) => {
|
|
125
|
+
return new XaiResponsesLanguageModel(modelId, {
|
|
126
|
+
provider: 'xai.responses',
|
|
127
|
+
baseURL,
|
|
128
|
+
headers: getHeaders,
|
|
129
|
+
generateId,
|
|
130
|
+
fetch: options.fetch,
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const createImageModel = (modelId: XaiImageModelId) => {
|
|
135
|
+
return new OpenAICompatibleImageModel(modelId, {
|
|
136
|
+
provider: 'xai.image',
|
|
137
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
138
|
+
headers: getHeaders,
|
|
139
|
+
fetch: options.fetch,
|
|
140
|
+
errorStructure: xaiErrorStructure,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const provider = (modelId: XaiChatModelId) =>
|
|
145
|
+
createChatLanguageModel(modelId);
|
|
146
|
+
|
|
147
|
+
provider.specificationVersion = 'v3' as const;
|
|
148
|
+
provider.languageModel = createChatLanguageModel;
|
|
149
|
+
provider.chat = createChatLanguageModel;
|
|
150
|
+
provider.responses = createResponsesLanguageModel;
|
|
151
|
+
provider.embeddingModel = (modelId: string) => {
|
|
152
|
+
throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' });
|
|
153
|
+
};
|
|
154
|
+
provider.textEmbeddingModel = provider.embeddingModel;
|
|
155
|
+
provider.imageModel = createImageModel;
|
|
156
|
+
provider.image = createImageModel;
|
|
157
|
+
provider.tools = xaiTools;
|
|
158
|
+
|
|
159
|
+
return provider;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export const xai = createXai();
|