@ai-sdk/xai 0.0.0-70e0935a-20260114150030 → 0.0.0-98261322-20260122142521

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +64 -5
  2. package/dist/index.js +1 -1
  3. package/dist/index.mjs +1 -1
  4. package/docs/01-xai.mdx +697 -0
  5. package/package.json +11 -6
  6. package/src/convert-to-xai-chat-messages.test.ts +243 -0
  7. package/src/convert-to-xai-chat-messages.ts +142 -0
  8. package/src/convert-xai-chat-usage.test.ts +240 -0
  9. package/src/convert-xai-chat-usage.ts +23 -0
  10. package/src/get-response-metadata.ts +19 -0
  11. package/src/index.ts +14 -0
  12. package/src/map-xai-finish-reason.ts +19 -0
  13. package/src/responses/__fixtures__/xai-code-execution-tool.1.json +68 -0
  14. package/src/responses/__fixtures__/xai-text-streaming.1.chunks.txt +698 -0
  15. package/src/responses/__fixtures__/xai-text-with-reasoning-streaming-store-false.1.chunks.txt +655 -0
  16. package/src/responses/__fixtures__/xai-text-with-reasoning-streaming.1.chunks.txt +679 -0
  17. package/src/responses/__fixtures__/xai-web-search-tool.1.chunks.txt +274 -0
  18. package/src/responses/__fixtures__/xai-web-search-tool.1.json +90 -0
  19. package/src/responses/__fixtures__/xai-x-search-tool.1.json +149 -0
  20. package/src/responses/__fixtures__/xai-x-search-tool.chunks.txt +1757 -0
  21. package/src/responses/__snapshots__/xai-responses-language-model.test.ts.snap +21929 -0
  22. package/src/responses/convert-to-xai-responses-input.test.ts +463 -0
  23. package/src/responses/convert-to-xai-responses-input.ts +206 -0
  24. package/src/responses/convert-xai-responses-usage.ts +24 -0
  25. package/src/responses/map-xai-responses-finish-reason.ts +20 -0
  26. package/src/responses/xai-responses-api.ts +393 -0
  27. package/src/responses/xai-responses-language-model.test.ts +1803 -0
  28. package/src/responses/xai-responses-language-model.ts +732 -0
  29. package/src/responses/xai-responses-options.ts +34 -0
  30. package/src/responses/xai-responses-prepare-tools.test.ts +497 -0
  31. package/src/responses/xai-responses-prepare-tools.ts +226 -0
  32. package/src/tool/code-execution.ts +17 -0
  33. package/src/tool/index.ts +15 -0
  34. package/src/tool/view-image.ts +20 -0
  35. package/src/tool/view-x-video.ts +18 -0
  36. package/src/tool/web-search.ts +56 -0
  37. package/src/tool/x-search.ts +63 -0
  38. package/src/version.ts +6 -0
  39. package/src/xai-chat-language-model.test.ts +1805 -0
  40. package/src/xai-chat-language-model.ts +681 -0
  41. package/src/xai-chat-options.ts +131 -0
  42. package/src/xai-chat-prompt.ts +44 -0
  43. package/src/xai-error.ts +19 -0
  44. package/src/xai-image-settings.ts +1 -0
  45. package/src/xai-prepare-tools.ts +95 -0
  46. package/src/xai-provider.test.ts +167 -0
  47. 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 } };
@@ -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,167 @@
1
+ import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
2
+ import { createXai } from './xai-provider';
3
+ import { loadApiKey } from '@ai-sdk/provider-utils';
4
+ import { XaiChatLanguageModel } from './xai-chat-language-model';
5
+ import { OpenAICompatibleImageModel } from '@ai-sdk/openai-compatible';
6
+
7
+ const XaiChatLanguageModelMock = XaiChatLanguageModel as unknown as Mock;
8
+ const OpenAICompatibleImageModelMock =
9
+ OpenAICompatibleImageModel as unknown as Mock;
10
+
11
+ vi.mock('./xai-chat-language-model', () => ({
12
+ XaiChatLanguageModel: vi.fn(),
13
+ }));
14
+
15
+ vi.mock('@ai-sdk/openai-compatible', () => ({
16
+ OpenAICompatibleChatLanguageModel: vi.fn(),
17
+ OpenAICompatibleCompletionLanguageModel: vi.fn(),
18
+ OpenAICompatibleEmbeddingModel: vi.fn(),
19
+ OpenAICompatibleImageModel: vi.fn(),
20
+ }));
21
+
22
+ vi.mock('./xai-image-model', () => ({
23
+ XaiImageModel: vi.fn(),
24
+ }));
25
+
26
+ vi.mock('@ai-sdk/provider-utils', async () => {
27
+ const actual = await vi.importActual('@ai-sdk/provider-utils');
28
+ return {
29
+ ...actual,
30
+ loadApiKey: vi.fn().mockReturnValue('mock-api-key'),
31
+ withoutTrailingSlash: vi.fn(url => url),
32
+ createJsonErrorResponseHandler: vi.fn().mockReturnValue(() => {}),
33
+ generateId: vi.fn().mockReturnValue('mock-id'),
34
+ };
35
+ });
36
+
37
+ vi.mock('./version', () => ({
38
+ VERSION: '0.0.0-test',
39
+ }));
40
+
41
+ describe('xAIProvider', () => {
42
+ beforeEach(() => {
43
+ vi.clearAllMocks();
44
+ });
45
+
46
+ describe('createXAI', () => {
47
+ it('should create an XAIProvider instance with default options', () => {
48
+ const provider = createXai();
49
+ const model = provider('model-id');
50
+
51
+ const constructorCall = XaiChatLanguageModelMock.mock.calls[0];
52
+ const config = constructorCall[1];
53
+ config.headers();
54
+
55
+ expect(loadApiKey).toHaveBeenCalledWith({
56
+ apiKey: undefined,
57
+ environmentVariableName: 'XAI_API_KEY',
58
+ description: 'xAI API key',
59
+ });
60
+ });
61
+
62
+ it('should create an XAIProvider instance with custom options', () => {
63
+ const options = {
64
+ apiKey: 'custom-key',
65
+ baseURL: 'https://custom.url',
66
+ headers: { 'Custom-Header': 'value' },
67
+ };
68
+ const provider = createXai(options);
69
+ provider('model-id');
70
+
71
+ const constructorCall = XaiChatLanguageModelMock.mock.calls[0];
72
+ const config = constructorCall[1];
73
+ config.headers();
74
+
75
+ expect(loadApiKey).toHaveBeenCalledWith({
76
+ apiKey: 'custom-key',
77
+ environmentVariableName: 'XAI_API_KEY',
78
+ description: 'xAI API key',
79
+ });
80
+ });
81
+
82
+ it('should return a chat model when called as a function', () => {
83
+ const provider = createXai();
84
+ const modelId = 'foo-model-id';
85
+
86
+ const model = provider(modelId);
87
+ expect(model).toBeInstanceOf(XaiChatLanguageModel);
88
+ });
89
+ });
90
+
91
+ describe('chatModel', () => {
92
+ it('should construct a chat model with correct configuration', () => {
93
+ const provider = createXai();
94
+ const modelId = 'xai-chat-model';
95
+
96
+ const model = provider.chat(modelId);
97
+
98
+ expect(model).toBeInstanceOf(XaiChatLanguageModel);
99
+ });
100
+
101
+ it('should pass the includeUsage option to the chat model, to make sure usage is reported while streaming', () => {
102
+ const provider = createXai();
103
+ const modelId = 'xai-chat-model';
104
+
105
+ const model = provider.chat(modelId);
106
+
107
+ expect(model).toBeInstanceOf(XaiChatLanguageModel);
108
+
109
+ const constructorCall = XaiChatLanguageModelMock.mock.calls[0];
110
+
111
+ expect(constructorCall[0]).toBe(modelId);
112
+ expect(constructorCall[1].provider).toBe('xai.chat');
113
+ expect(constructorCall[1].baseURL).toBe('https://api.x.ai/v1');
114
+ });
115
+ });
116
+
117
+ describe('imageModel', () => {
118
+ it('should construct an image model with correct configuration', () => {
119
+ const provider = createXai();
120
+ const modelId = 'grok-2-image';
121
+
122
+ const model = provider.imageModel(modelId);
123
+
124
+ expect(model).toBeInstanceOf(OpenAICompatibleImageModel);
125
+
126
+ const constructorCall = OpenAICompatibleImageModelMock.mock.calls[0];
127
+ expect(constructorCall[0]).toBe(modelId);
128
+
129
+ const config = constructorCall[1];
130
+ expect(config.provider).toBe('xai.image');
131
+ expect(config.url({ path: '/test-path' })).toBe(
132
+ 'https://api.x.ai/v1/test-path',
133
+ );
134
+ });
135
+
136
+ it('should use custom baseURL for image model', () => {
137
+ const customBaseURL = 'https://custom.xai.api';
138
+ const provider = createXai({ baseURL: customBaseURL });
139
+ const modelId = 'grok-2-image';
140
+
141
+ provider.imageModel(modelId);
142
+
143
+ const constructorCall = OpenAICompatibleImageModelMock.mock.calls[0];
144
+ const config = constructorCall[1];
145
+ expect(config.url({ path: '/test-path' })).toBe(
146
+ `${customBaseURL}/test-path`,
147
+ );
148
+ });
149
+
150
+ it('should pass custom headers to image model', () => {
151
+ const customHeaders = { 'Custom-Header': 'test-value' };
152
+ const provider = createXai({ headers: customHeaders });
153
+
154
+ provider.imageModel('grok-2-image');
155
+
156
+ const constructorCall = OpenAICompatibleImageModelMock.mock.calls[0];
157
+ const config = constructorCall[1];
158
+ const headers = config.headers();
159
+
160
+ expect(headers).toMatchObject({
161
+ authorization: 'Bearer mock-api-key',
162
+ 'custom-header': 'test-value',
163
+ 'user-agent': 'ai-sdk/xai/0.0.0-test',
164
+ });
165
+ });
166
+ });
167
+ });
@@ -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();