@ai-sdk/xai 2.0.0-alpha.8 → 2.0.0-beta.1

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/dist/index.mjs CHANGED
@@ -1,47 +1,736 @@
1
1
  // src/xai-provider.ts
2
2
  import {
3
- OpenAICompatibleChatLanguageModel,
4
3
  OpenAICompatibleImageModel
5
4
  } from "@ai-sdk/openai-compatible";
6
5
  import {
7
6
  NoSuchModelError
8
7
  } from "@ai-sdk/provider";
9
8
  import {
9
+ generateId,
10
10
  loadApiKey,
11
11
  withoutTrailingSlash
12
12
  } from "@ai-sdk/provider-utils";
13
13
 
14
- // src/xai-chat-options.ts
15
- function supportsStructuredOutputs(modelId) {
16
- return [
17
- "grok-3",
18
- "grok-3-beta",
19
- "grok-3-latest",
20
- "grok-3-fast",
21
- "grok-3-fast-beta",
22
- "grok-3-fast-latest",
23
- "grok-3-mini",
24
- "grok-3-mini-beta",
25
- "grok-3-mini-latest",
26
- "grok-3-mini-fast",
27
- "grok-3-mini-fast-beta",
28
- "grok-3-mini-fast-latest",
29
- "grok-2-1212",
30
- "grok-2-vision-1212"
31
- ].includes(modelId);
14
+ // src/xai-chat-language-model.ts
15
+ import {
16
+ combineHeaders,
17
+ createEventSourceResponseHandler,
18
+ createJsonResponseHandler,
19
+ parseProviderOptions,
20
+ postJsonToApi
21
+ } from "@ai-sdk/provider-utils";
22
+ import { z as z3 } from "zod";
23
+
24
+ // src/convert-to-xai-chat-messages.ts
25
+ import {
26
+ UnsupportedFunctionalityError
27
+ } from "@ai-sdk/provider";
28
+ import { convertToBase64 } from "@ai-sdk/provider-utils";
29
+ function convertToXaiChatMessages(prompt) {
30
+ const messages = [];
31
+ const warnings = [];
32
+ for (const { role, content } of prompt) {
33
+ switch (role) {
34
+ case "system": {
35
+ messages.push({ role: "system", content });
36
+ break;
37
+ }
38
+ case "user": {
39
+ if (content.length === 1 && content[0].type === "text") {
40
+ messages.push({ role: "user", content: content[0].text });
41
+ break;
42
+ }
43
+ messages.push({
44
+ role: "user",
45
+ content: content.map((part) => {
46
+ switch (part.type) {
47
+ case "text": {
48
+ return { type: "text", text: part.text };
49
+ }
50
+ case "file": {
51
+ if (part.mediaType.startsWith("image/")) {
52
+ const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
53
+ return {
54
+ type: "image_url",
55
+ image_url: {
56
+ url: part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${convertToBase64(part.data)}`
57
+ }
58
+ };
59
+ } else {
60
+ throw new UnsupportedFunctionalityError({
61
+ functionality: `file part media type ${part.mediaType}`
62
+ });
63
+ }
64
+ }
65
+ }
66
+ })
67
+ });
68
+ break;
69
+ }
70
+ case "assistant": {
71
+ let text = "";
72
+ const toolCalls = [];
73
+ for (const part of content) {
74
+ switch (part.type) {
75
+ case "text": {
76
+ text += part.text;
77
+ break;
78
+ }
79
+ case "tool-call": {
80
+ toolCalls.push({
81
+ id: part.toolCallId,
82
+ type: "function",
83
+ function: {
84
+ name: part.toolName,
85
+ arguments: JSON.stringify(part.input)
86
+ }
87
+ });
88
+ break;
89
+ }
90
+ }
91
+ }
92
+ messages.push({
93
+ role: "assistant",
94
+ content: text,
95
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
96
+ });
97
+ break;
98
+ }
99
+ case "tool": {
100
+ for (const toolResponse of content) {
101
+ const output = toolResponse.output;
102
+ let contentValue;
103
+ switch (output.type) {
104
+ case "text":
105
+ case "error-text":
106
+ contentValue = output.value;
107
+ break;
108
+ case "content":
109
+ case "json":
110
+ case "error-json":
111
+ contentValue = JSON.stringify(output.value);
112
+ break;
113
+ }
114
+ messages.push({
115
+ role: "tool",
116
+ tool_call_id: toolResponse.toolCallId,
117
+ content: contentValue
118
+ });
119
+ }
120
+ break;
121
+ }
122
+ default: {
123
+ const _exhaustiveCheck = role;
124
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
125
+ }
126
+ }
127
+ }
128
+ return { messages, warnings };
32
129
  }
33
130
 
34
- // src/xai-error.ts
131
+ // src/get-response-metadata.ts
132
+ function getResponseMetadata({
133
+ id,
134
+ model,
135
+ created
136
+ }) {
137
+ return {
138
+ id: id != null ? id : void 0,
139
+ modelId: model != null ? model : void 0,
140
+ timestamp: created != null ? new Date(created * 1e3) : void 0
141
+ };
142
+ }
143
+
144
+ // src/map-xai-finish-reason.ts
145
+ function mapXaiFinishReason(finishReason) {
146
+ switch (finishReason) {
147
+ case "stop":
148
+ return "stop";
149
+ case "length":
150
+ return "length";
151
+ case "tool_calls":
152
+ case "function_call":
153
+ return "tool-calls";
154
+ case "content_filter":
155
+ return "content-filter";
156
+ default:
157
+ return "unknown";
158
+ }
159
+ }
160
+
161
+ // src/xai-chat-options.ts
35
162
  import { z } from "zod";
36
- var xaiErrorSchema = z.object({
37
- code: z.string(),
38
- error: z.string()
163
+ var webSourceSchema = z.object({
164
+ type: z.literal("web"),
165
+ country: z.string().length(2).optional(),
166
+ excludedWebsites: z.array(z.string()).max(5).optional(),
167
+ allowedWebsites: z.array(z.string()).max(5).optional(),
168
+ safeSearch: z.boolean().optional()
169
+ });
170
+ var xSourceSchema = z.object({
171
+ type: z.literal("x"),
172
+ xHandles: z.array(z.string()).optional()
173
+ });
174
+ var newsSourceSchema = z.object({
175
+ type: z.literal("news"),
176
+ country: z.string().length(2).optional(),
177
+ excludedWebsites: z.array(z.string()).max(5).optional(),
178
+ safeSearch: z.boolean().optional()
179
+ });
180
+ var rssSourceSchema = z.object({
181
+ type: z.literal("rss"),
182
+ links: z.array(z.string().url()).max(1)
183
+ // currently only supports one RSS link
184
+ });
185
+ var searchSourceSchema = z.discriminatedUnion("type", [
186
+ webSourceSchema,
187
+ xSourceSchema,
188
+ newsSourceSchema,
189
+ rssSourceSchema
190
+ ]);
191
+ var xaiProviderOptions = z.object({
192
+ /**
193
+ * reasoning effort for reasoning models
194
+ * only supported by grok-3-mini and grok-3-mini-fast models
195
+ */
196
+ reasoningEffort: z.enum(["low", "high"]).optional(),
197
+ searchParameters: z.object({
198
+ /**
199
+ * search mode preference
200
+ * - "off": disables search completely
201
+ * - "auto": model decides whether to search (default)
202
+ * - "on": always enables search
203
+ */
204
+ mode: z.enum(["off", "auto", "on"]),
205
+ /**
206
+ * whether to return citations in the response
207
+ * defaults to true
208
+ */
209
+ returnCitations: z.boolean().optional(),
210
+ /**
211
+ * start date for search data (ISO8601 format: YYYY-MM-DD)
212
+ */
213
+ fromDate: z.string().optional(),
214
+ /**
215
+ * end date for search data (ISO8601 format: YYYY-MM-DD)
216
+ */
217
+ toDate: z.string().optional(),
218
+ /**
219
+ * maximum number of search results to consider
220
+ * defaults to 20
221
+ */
222
+ maxSearchResults: z.number().min(1).max(50).optional(),
223
+ /**
224
+ * data sources to search from
225
+ * defaults to ["web", "x"] if not specified
226
+ */
227
+ sources: z.array(searchSourceSchema).optional()
228
+ }).optional()
229
+ });
230
+
231
+ // src/xai-error.ts
232
+ import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
233
+ import { z as z2 } from "zod";
234
+ var xaiErrorDataSchema = z2.object({
235
+ error: z2.object({
236
+ message: z2.string(),
237
+ type: z2.string().nullish(),
238
+ param: z2.any().nullish(),
239
+ code: z2.union([z2.string(), z2.number()]).nullish()
240
+ })
241
+ });
242
+ var xaiFailedResponseHandler = createJsonErrorResponseHandler({
243
+ errorSchema: xaiErrorDataSchema,
244
+ errorToMessage: (data) => data.error.message
245
+ });
246
+
247
+ // src/xai-prepare-tools.ts
248
+ import {
249
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError2
250
+ } from "@ai-sdk/provider";
251
+ function prepareTools({
252
+ tools,
253
+ toolChoice
254
+ }) {
255
+ tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
256
+ const toolWarnings = [];
257
+ if (tools == null) {
258
+ return { tools: void 0, toolChoice: void 0, toolWarnings };
259
+ }
260
+ const xaiTools = [];
261
+ for (const tool of tools) {
262
+ if (tool.type === "provider-defined") {
263
+ toolWarnings.push({ type: "unsupported-tool", tool });
264
+ } else {
265
+ xaiTools.push({
266
+ type: "function",
267
+ function: {
268
+ name: tool.name,
269
+ description: tool.description,
270
+ parameters: tool.inputSchema
271
+ }
272
+ });
273
+ }
274
+ }
275
+ if (toolChoice == null) {
276
+ return { tools: xaiTools, toolChoice: void 0, toolWarnings };
277
+ }
278
+ const type = toolChoice.type;
279
+ switch (type) {
280
+ case "auto":
281
+ case "none":
282
+ return { tools: xaiTools, toolChoice: type, toolWarnings };
283
+ case "required":
284
+ return { tools: xaiTools, toolChoice: "required", toolWarnings };
285
+ case "tool":
286
+ return {
287
+ tools: xaiTools,
288
+ toolChoice: {
289
+ type: "function",
290
+ function: { name: toolChoice.toolName }
291
+ },
292
+ toolWarnings
293
+ };
294
+ default: {
295
+ const _exhaustiveCheck = type;
296
+ throw new UnsupportedFunctionalityError2({
297
+ functionality: `tool choice type: ${_exhaustiveCheck}`
298
+ });
299
+ }
300
+ }
301
+ }
302
+
303
+ // src/xai-chat-language-model.ts
304
+ var XaiChatLanguageModel = class {
305
+ constructor(modelId, config) {
306
+ this.specificationVersion = "v2";
307
+ this.supportedUrls = {
308
+ "image/*": [/^https?:\/\/.*$/]
309
+ };
310
+ this.modelId = modelId;
311
+ this.config = config;
312
+ }
313
+ get provider() {
314
+ return this.config.provider;
315
+ }
316
+ async getArgs({
317
+ prompt,
318
+ maxOutputTokens,
319
+ temperature,
320
+ topP,
321
+ topK,
322
+ frequencyPenalty,
323
+ presencePenalty,
324
+ stopSequences,
325
+ seed,
326
+ responseFormat,
327
+ providerOptions,
328
+ tools,
329
+ toolChoice
330
+ }) {
331
+ var _a, _b, _c;
332
+ const warnings = [];
333
+ const options = (_a = await parseProviderOptions({
334
+ provider: "xai",
335
+ providerOptions,
336
+ schema: xaiProviderOptions
337
+ })) != null ? _a : {};
338
+ if (topK != null) {
339
+ warnings.push({
340
+ type: "unsupported-setting",
341
+ setting: "topK"
342
+ });
343
+ }
344
+ if (frequencyPenalty != null) {
345
+ warnings.push({
346
+ type: "unsupported-setting",
347
+ setting: "frequencyPenalty"
348
+ });
349
+ }
350
+ if (presencePenalty != null) {
351
+ warnings.push({
352
+ type: "unsupported-setting",
353
+ setting: "presencePenalty"
354
+ });
355
+ }
356
+ if (stopSequences != null) {
357
+ warnings.push({
358
+ type: "unsupported-setting",
359
+ setting: "stopSequences"
360
+ });
361
+ }
362
+ if (responseFormat != null && responseFormat.type === "json" && responseFormat.schema != null) {
363
+ warnings.push({
364
+ type: "unsupported-setting",
365
+ setting: "responseFormat",
366
+ details: "JSON response format schema is not supported"
367
+ });
368
+ }
369
+ const { messages, warnings: messageWarnings } = convertToXaiChatMessages(prompt);
370
+ warnings.push(...messageWarnings);
371
+ const {
372
+ tools: xaiTools,
373
+ toolChoice: xaiToolChoice,
374
+ toolWarnings
375
+ } = prepareTools({
376
+ tools,
377
+ toolChoice
378
+ });
379
+ warnings.push(...toolWarnings);
380
+ const baseArgs = {
381
+ // model id
382
+ model: this.modelId,
383
+ // standard generation settings
384
+ max_tokens: maxOutputTokens,
385
+ temperature,
386
+ top_p: topP,
387
+ seed,
388
+ reasoning_effort: options.reasoningEffort,
389
+ // response format
390
+ response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? responseFormat.schema != null ? {
391
+ type: "json_schema",
392
+ json_schema: {
393
+ name: (_b = responseFormat.name) != null ? _b : "response",
394
+ schema: responseFormat.schema,
395
+ strict: true
396
+ }
397
+ } : { type: "json_object" } : void 0,
398
+ // search parameters
399
+ search_parameters: options.searchParameters ? {
400
+ mode: options.searchParameters.mode,
401
+ return_citations: options.searchParameters.returnCitations,
402
+ from_date: options.searchParameters.fromDate,
403
+ to_date: options.searchParameters.toDate,
404
+ max_search_results: options.searchParameters.maxSearchResults,
405
+ sources: (_c = options.searchParameters.sources) == null ? void 0 : _c.map((source) => ({
406
+ type: source.type,
407
+ ...source.type === "web" && {
408
+ country: source.country,
409
+ excluded_websites: source.excludedWebsites,
410
+ allowed_websites: source.allowedWebsites,
411
+ safe_search: source.safeSearch
412
+ },
413
+ ...source.type === "x" && {
414
+ x_handles: source.xHandles
415
+ },
416
+ ...source.type === "news" && {
417
+ country: source.country,
418
+ excluded_websites: source.excludedWebsites,
419
+ safe_search: source.safeSearch
420
+ },
421
+ ...source.type === "rss" && {
422
+ links: source.links
423
+ }
424
+ }))
425
+ } : void 0,
426
+ // messages in xai format
427
+ messages,
428
+ // tools in xai format
429
+ tools: xaiTools,
430
+ tool_choice: xaiToolChoice
431
+ };
432
+ return {
433
+ args: baseArgs,
434
+ warnings
435
+ };
436
+ }
437
+ async doGenerate(options) {
438
+ var _a, _b, _c;
439
+ const { args: body, warnings } = await this.getArgs(options);
440
+ const {
441
+ responseHeaders,
442
+ value: response,
443
+ rawValue: rawResponse
444
+ } = await postJsonToApi({
445
+ url: `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`,
446
+ headers: combineHeaders(this.config.headers(), options.headers),
447
+ body,
448
+ failedResponseHandler: xaiFailedResponseHandler,
449
+ successfulResponseHandler: createJsonResponseHandler(
450
+ xaiChatResponseSchema
451
+ ),
452
+ abortSignal: options.abortSignal,
453
+ fetch: this.config.fetch
454
+ });
455
+ const choice = response.choices[0];
456
+ const content = [];
457
+ if (choice.message.content != null && choice.message.content.length > 0) {
458
+ let text = choice.message.content;
459
+ const lastMessage = body.messages[body.messages.length - 1];
460
+ if ((lastMessage == null ? void 0 : lastMessage.role) === "assistant" && text === lastMessage.content) {
461
+ text = "";
462
+ }
463
+ if (text.length > 0) {
464
+ content.push({ type: "text", text });
465
+ }
466
+ }
467
+ if (choice.message.reasoning_content != null && choice.message.reasoning_content.length > 0) {
468
+ content.push({
469
+ type: "reasoning",
470
+ text: choice.message.reasoning_content
471
+ });
472
+ }
473
+ if (choice.message.tool_calls != null) {
474
+ for (const toolCall of choice.message.tool_calls) {
475
+ content.push({
476
+ type: "tool-call",
477
+ toolCallId: toolCall.id,
478
+ toolName: toolCall.function.name,
479
+ input: toolCall.function.arguments
480
+ });
481
+ }
482
+ }
483
+ if (response.citations != null) {
484
+ for (const url of response.citations) {
485
+ content.push({
486
+ type: "source",
487
+ sourceType: "url",
488
+ id: this.config.generateId(),
489
+ url
490
+ });
491
+ }
492
+ }
493
+ return {
494
+ content,
495
+ finishReason: mapXaiFinishReason(choice.finish_reason),
496
+ usage: {
497
+ inputTokens: response.usage.prompt_tokens,
498
+ outputTokens: response.usage.completion_tokens,
499
+ totalTokens: response.usage.total_tokens,
500
+ reasoningTokens: (_c = (_b = response.usage.completion_tokens_details) == null ? void 0 : _b.reasoning_tokens) != null ? _c : void 0
501
+ },
502
+ request: { body },
503
+ response: {
504
+ ...getResponseMetadata(response),
505
+ headers: responseHeaders,
506
+ body: rawResponse
507
+ },
508
+ warnings
509
+ };
510
+ }
511
+ async doStream(options) {
512
+ var _a;
513
+ const { args, warnings } = await this.getArgs(options);
514
+ const body = {
515
+ ...args,
516
+ stream: true,
517
+ stream_options: {
518
+ include_usage: true
519
+ }
520
+ };
521
+ const { responseHeaders, value: response } = await postJsonToApi({
522
+ url: `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`,
523
+ headers: combineHeaders(this.config.headers(), options.headers),
524
+ body,
525
+ failedResponseHandler: xaiFailedResponseHandler,
526
+ successfulResponseHandler: createEventSourceResponseHandler(xaiChatChunkSchema),
527
+ abortSignal: options.abortSignal,
528
+ fetch: this.config.fetch
529
+ });
530
+ let finishReason = "unknown";
531
+ const usage = {
532
+ inputTokens: void 0,
533
+ outputTokens: void 0,
534
+ totalTokens: void 0
535
+ };
536
+ let isFirstChunk = true;
537
+ const contentBlocks = {};
538
+ const self = this;
539
+ return {
540
+ stream: response.pipeThrough(
541
+ new TransformStream({
542
+ start(controller) {
543
+ controller.enqueue({ type: "stream-start", warnings });
544
+ },
545
+ transform(chunk, controller) {
546
+ var _a2, _b;
547
+ if (options.includeRawChunks) {
548
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
549
+ }
550
+ if (!chunk.success) {
551
+ controller.enqueue({ type: "error", error: chunk.error });
552
+ return;
553
+ }
554
+ const value = chunk.value;
555
+ if (isFirstChunk) {
556
+ controller.enqueue({
557
+ type: "response-metadata",
558
+ ...getResponseMetadata(value)
559
+ });
560
+ isFirstChunk = false;
561
+ }
562
+ if (value.citations != null) {
563
+ for (const url of value.citations) {
564
+ controller.enqueue({
565
+ type: "source",
566
+ sourceType: "url",
567
+ id: self.config.generateId(),
568
+ url
569
+ });
570
+ }
571
+ }
572
+ if (value.usage != null) {
573
+ usage.inputTokens = value.usage.prompt_tokens;
574
+ usage.outputTokens = value.usage.completion_tokens;
575
+ usage.totalTokens = value.usage.total_tokens;
576
+ usage.reasoningTokens = (_b = (_a2 = value.usage.completion_tokens_details) == null ? void 0 : _a2.reasoning_tokens) != null ? _b : void 0;
577
+ }
578
+ const choice = value.choices[0];
579
+ if ((choice == null ? void 0 : choice.finish_reason) != null) {
580
+ finishReason = mapXaiFinishReason(choice.finish_reason);
581
+ }
582
+ if ((choice == null ? void 0 : choice.delta) == null) {
583
+ return;
584
+ }
585
+ const delta = choice.delta;
586
+ const choiceIndex = choice.index;
587
+ if (delta.content != null && delta.content.length > 0) {
588
+ const textContent = delta.content;
589
+ const lastMessage = body.messages[body.messages.length - 1];
590
+ if ((lastMessage == null ? void 0 : lastMessage.role) === "assistant" && textContent === lastMessage.content) {
591
+ return;
592
+ }
593
+ const blockId = `text-${value.id || choiceIndex}`;
594
+ if (contentBlocks[blockId] == null) {
595
+ contentBlocks[blockId] = { type: "text" };
596
+ controller.enqueue({
597
+ type: "text-start",
598
+ id: blockId
599
+ });
600
+ }
601
+ controller.enqueue({
602
+ type: "text-delta",
603
+ id: blockId,
604
+ delta: textContent
605
+ });
606
+ }
607
+ if (delta.reasoning_content != null && delta.reasoning_content.length > 0) {
608
+ const blockId = `reasoning-${value.id || choiceIndex}`;
609
+ if (contentBlocks[blockId] == null) {
610
+ contentBlocks[blockId] = { type: "reasoning" };
611
+ controller.enqueue({
612
+ type: "reasoning-start",
613
+ id: blockId
614
+ });
615
+ }
616
+ controller.enqueue({
617
+ type: "reasoning-delta",
618
+ id: blockId,
619
+ delta: delta.reasoning_content
620
+ });
621
+ }
622
+ if (delta.tool_calls != null) {
623
+ for (const toolCall of delta.tool_calls) {
624
+ const toolCallId = toolCall.id;
625
+ controller.enqueue({
626
+ type: "tool-input-start",
627
+ id: toolCallId,
628
+ toolName: toolCall.function.name
629
+ });
630
+ controller.enqueue({
631
+ type: "tool-input-delta",
632
+ id: toolCallId,
633
+ delta: toolCall.function.arguments
634
+ });
635
+ controller.enqueue({
636
+ type: "tool-input-end",
637
+ id: toolCallId
638
+ });
639
+ controller.enqueue({
640
+ type: "tool-call",
641
+ toolCallId,
642
+ toolName: toolCall.function.name,
643
+ input: toolCall.function.arguments
644
+ });
645
+ }
646
+ }
647
+ },
648
+ flush(controller) {
649
+ for (const [blockId, block] of Object.entries(contentBlocks)) {
650
+ controller.enqueue({
651
+ type: block.type === "text" ? "text-end" : "reasoning-end",
652
+ id: blockId
653
+ });
654
+ }
655
+ controller.enqueue({ type: "finish", finishReason, usage });
656
+ }
657
+ })
658
+ ),
659
+ request: { body },
660
+ response: { headers: responseHeaders }
661
+ };
662
+ }
663
+ };
664
+ var xaiUsageSchema = z3.object({
665
+ prompt_tokens: z3.number(),
666
+ completion_tokens: z3.number(),
667
+ total_tokens: z3.number(),
668
+ completion_tokens_details: z3.object({
669
+ reasoning_tokens: z3.number().nullish()
670
+ }).nullish()
671
+ });
672
+ var xaiChatResponseSchema = z3.object({
673
+ id: z3.string().nullish(),
674
+ created: z3.number().nullish(),
675
+ model: z3.string().nullish(),
676
+ choices: z3.array(
677
+ z3.object({
678
+ message: z3.object({
679
+ role: z3.literal("assistant"),
680
+ content: z3.string().nullish(),
681
+ reasoning_content: z3.string().nullish(),
682
+ tool_calls: z3.array(
683
+ z3.object({
684
+ id: z3.string(),
685
+ type: z3.literal("function"),
686
+ function: z3.object({
687
+ name: z3.string(),
688
+ arguments: z3.string()
689
+ })
690
+ })
691
+ ).nullish()
692
+ }),
693
+ index: z3.number(),
694
+ finish_reason: z3.string().nullish()
695
+ })
696
+ ),
697
+ object: z3.literal("chat.completion"),
698
+ usage: xaiUsageSchema,
699
+ citations: z3.array(z3.string().url()).nullish()
700
+ });
701
+ var xaiChatChunkSchema = z3.object({
702
+ id: z3.string().nullish(),
703
+ created: z3.number().nullish(),
704
+ model: z3.string().nullish(),
705
+ choices: z3.array(
706
+ z3.object({
707
+ delta: z3.object({
708
+ role: z3.enum(["assistant"]).optional(),
709
+ content: z3.string().nullish(),
710
+ reasoning_content: z3.string().nullish(),
711
+ tool_calls: z3.array(
712
+ z3.object({
713
+ id: z3.string(),
714
+ type: z3.literal("function"),
715
+ function: z3.object({
716
+ name: z3.string(),
717
+ arguments: z3.string()
718
+ })
719
+ })
720
+ ).nullish()
721
+ }),
722
+ finish_reason: z3.string().nullish(),
723
+ index: z3.number()
724
+ })
725
+ ),
726
+ usage: xaiUsageSchema.nullish(),
727
+ citations: z3.array(z3.string().url()).nullish()
39
728
  });
40
729
 
41
730
  // src/xai-provider.ts
42
731
  var xaiErrorStructure = {
43
- errorSchema: xaiErrorSchema,
44
- errorToMessage: (data) => data.error
732
+ errorSchema: xaiErrorDataSchema,
733
+ errorToMessage: (data) => data.error.message
45
734
  };
46
735
  function createXai(options = {}) {
47
736
  var _a;
@@ -57,15 +746,12 @@ function createXai(options = {}) {
57
746
  ...options.headers
58
747
  });
59
748
  const createLanguageModel = (modelId) => {
60
- const structuredOutputs = supportsStructuredOutputs(modelId);
61
- return new OpenAICompatibleChatLanguageModel(modelId, {
749
+ return new XaiChatLanguageModel(modelId, {
62
750
  provider: "xai.chat",
63
- url: ({ path }) => `${baseURL}${path}`,
751
+ baseURL,
64
752
  headers: getHeaders,
65
- fetch: options.fetch,
66
- errorStructure: xaiErrorStructure,
67
- supportsStructuredOutputs: structuredOutputs,
68
- includeUsage: true
753
+ generateId,
754
+ fetch: options.fetch
69
755
  });
70
756
  };
71
757
  const createImageModel = (modelId) => {