@gullabs/xai 0.7.1 → 0.9.0

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { zodToStandardSchema, toConfigJsonSchema, createModelRegistry, LlmError, classifyError, assertNever, redactSecrets } from '@gullabs/core';
1
+ import { zodToStandardSchema, toConfigJsonSchema, createModelRegistry, LlmError, computeCost, classifyError, assertNever, redactSecrets } from '@gullabs/core';
2
2
  import { z } from 'zod';
3
3
 
4
4
  // src/client.ts
@@ -28,6 +28,546 @@ async function buildXaiClient(auth) {
28
28
  }
29
29
  };
30
30
  }
31
+ var webSearchFlags = {
32
+ enableImageUnderstanding: z.boolean().optional().meta({
33
+ title: "Enable Image Understanding",
34
+ description: "Ask xAI to analyze images found during web search."
35
+ }),
36
+ enableImageSearch: z.boolean().optional().meta({
37
+ title: "Enable Image Search",
38
+ description: "Ask xAI to include image search results."
39
+ })
40
+ };
41
+ var XaiWebSearchToolSchema = z.union([
42
+ z.strictObject({
43
+ type: z.literal("web_search"),
44
+ allowedDomains: z.array(z.string()).max(5),
45
+ ...webSearchFlags
46
+ }),
47
+ z.strictObject({
48
+ type: z.literal("web_search"),
49
+ excludedDomains: z.array(z.string()).max(5),
50
+ ...webSearchFlags
51
+ }),
52
+ z.strictObject({
53
+ type: z.literal("web_search"),
54
+ ...webSearchFlags
55
+ })
56
+ ]).meta({
57
+ title: "XaiWebSearchTool",
58
+ description: "xAI web_search server tool. allowedDomains and excludedDomains are mutually exclusive (max 5)."
59
+ });
60
+ var xSearchFlags = {
61
+ fromDate: z.iso.date().optional().meta({
62
+ title: "From Date",
63
+ description: "Inclusive ISO-8601 date lower bound for X search."
64
+ }),
65
+ toDate: z.iso.date().optional().meta({
66
+ title: "To Date",
67
+ description: "Inclusive ISO-8601 date upper bound for X search."
68
+ }),
69
+ enableImageUnderstanding: z.boolean().optional().meta({
70
+ title: "Enable Image Understanding",
71
+ description: "Ask xAI to analyze images in matched posts."
72
+ }),
73
+ enableVideoUnderstanding: z.boolean().optional().meta({
74
+ title: "Enable Video Understanding",
75
+ description: "Ask xAI to analyze videos in matched posts."
76
+ })
77
+ };
78
+ var XaiXSearchToolSchema = z.union([
79
+ z.strictObject({
80
+ type: z.literal("x_search"),
81
+ allowedXHandles: z.array(z.string()).max(20),
82
+ ...xSearchFlags
83
+ }),
84
+ z.strictObject({
85
+ type: z.literal("x_search"),
86
+ excludedXHandles: z.array(z.string()).max(20),
87
+ ...xSearchFlags
88
+ }),
89
+ z.strictObject({
90
+ type: z.literal("x_search"),
91
+ ...xSearchFlags
92
+ })
93
+ ]).meta({
94
+ title: "XaiXSearchTool",
95
+ description: "xAI x_search server tool. allowedXHandles and excludedXHandles are mutually exclusive (max 20)."
96
+ });
97
+ var XaiToolsSchema = z.union([
98
+ z.tuple([XaiWebSearchToolSchema]),
99
+ z.tuple([XaiXSearchToolSchema]),
100
+ z.tuple([XaiWebSearchToolSchema, XaiXSearchToolSchema]),
101
+ z.tuple([XaiXSearchToolSchema, XaiWebSearchToolSchema])
102
+ ]).meta({
103
+ title: "XaiTools",
104
+ description: "xAI Live Search tools. At most one web_search and at most one x_search."
105
+ });
106
+ var XaiProviderOptionsSchema = z.strictObject({
107
+ promptCacheKey: z.string().min(1).optional().meta({
108
+ title: "Prompt Cache Key",
109
+ description: "xAI conversation-routing cache key \u2014 maps to Responses API `prompt_cache_key`."
110
+ }),
111
+ tools: XaiToolsSchema.optional().meta({
112
+ title: "Live Search Tools",
113
+ description: "xAI server-side web_search / x_search tools."
114
+ }),
115
+ parallelToolCalls: z.boolean().optional().meta({
116
+ title: "Parallel Tool Calls",
117
+ description: "xAI Responses parallel_tool_calls. Not a generic contract field."
118
+ }),
119
+ toolChoice: z.enum(["auto", "required", "none"]).optional().meta({
120
+ title: "Server Tool Choice",
121
+ description: "xAI Responses `tool_choice` for the server-side search tools; `required` forces at least one search, `none` disables them. Requires `tools`. Cannot be combined with function tools, file attachments or the request-level toolChoice."
122
+ }),
123
+ maxTurns: z.number().int().min(1).optional().meta({
124
+ title: "Max Turns",
125
+ description: "xAI Responses `max_turns`: cap on agentic tool-calling turns for the server-side search tools. Requires `tools`. A turn can run several searches. Not enforced by xAI as of 2026-10-02."
126
+ })
127
+ }).meta({
128
+ title: "xAI Provider Options",
129
+ description: "Allowlisted xAI provider options."
130
+ });
131
+
132
+ // src/model-config/grok-4-5.ts
133
+ var Grok45ConfigSchema = z.strictObject({
134
+ temperature: z.number().optional().meta({
135
+ title: "Temperature",
136
+ description: "Sampling temperature forwarded verbatim to grok-4.5."
137
+ }),
138
+ topP: z.number().optional().meta({
139
+ title: "Top P",
140
+ description: "Nucleus sampling parameter forwarded verbatim to grok-4.5."
141
+ }),
142
+ maxOutputTokens: z.number().int().positive().optional().meta({
143
+ title: "Max Output Tokens",
144
+ description: "Maximum output token cap for grok-4.5. No artificial ceiling \u2014 xAI accepts arbitrarily large values (live-verified); truncation surfaces as finishReason:'length', not an error."
145
+ }),
146
+ reasoning: z.strictObject({
147
+ effort: z.enum(["low", "medium", "high"]).meta({
148
+ title: "Reasoning Effort",
149
+ description: 'Reasoning effort for grok-4.5. "low", "medium", and "high" are admitted (live-verified 2026-08-24). "xhigh" is rejected here even though /v1/language-models lists it: the reasoning guide says it is treated as high, and an echo does not prove a distinct level. "none" is rejected. Vendor default when omitted is "high".'
150
+ })
151
+ }).optional().meta({
152
+ title: "Reasoning",
153
+ description: "grok-4.5 effort-level reasoning configuration. No budgetTokens field \u2014 xAI uses level-style reasoning, not token budgets."
154
+ }),
155
+ serviceTier: z.literal("priority").optional().meta({
156
+ title: "Service Tier",
157
+ description: "xAI priority processing for grok-4.5, billed at 2\xD7 on input, cached input, and output tokens. Live-verified 2026-09-25."
158
+ }),
159
+ timeoutMs: z.number().int().positive().optional().meta({
160
+ title: "Timeout",
161
+ description: "Logical request timeout in milliseconds."
162
+ }),
163
+ providerOptions: z.strictObject({
164
+ xai: XaiProviderOptionsSchema.optional()
165
+ }).optional().meta({
166
+ title: "Provider Options",
167
+ description: "Provider-specific options accepted for grok-4.5."
168
+ })
169
+ }).meta({
170
+ title: "Grok45Config",
171
+ description: "Strict Responses API config for model grok-4.5. Level reasoning (low/medium/high), optional priority service tier, tunable sampling, structured output, vision, Live Search tools, priced.",
172
+ examples: [{ reasoning: { effort: "high" } }]
173
+ });
174
+ var Grok46ConfigSchema = z.strictObject({
175
+ temperature: z.number().optional().meta({
176
+ title: "Temperature",
177
+ description: "Sampling temperature forwarded verbatim to grok-4.6."
178
+ }),
179
+ topP: z.number().optional().meta({
180
+ title: "Top P",
181
+ description: "Nucleus sampling parameter forwarded verbatim to grok-4.6."
182
+ }),
183
+ maxOutputTokens: z.number().int().positive().optional().meta({
184
+ title: "Max Output Tokens",
185
+ description: "Maximum output token cap for grok-4.6. No artificial ceiling \u2014 xAI accepts arbitrarily large values; truncation surfaces as finishReason:'length', not an error."
186
+ }),
187
+ reasoning: z.strictObject({
188
+ effort: z.enum(["low", "medium", "high", "xhigh"]).meta({
189
+ title: "Reasoning Effort",
190
+ description: 'Reasoning effort for grok-4.6. Live-verified 2026-08-12: "low", "medium", "high", and "xhigh" are accepted; "none" is rejected. Vendor default when omitted is "high".'
191
+ })
192
+ }).optional().meta({
193
+ title: "Reasoning",
194
+ description: "grok-4.6 effort-level reasoning configuration. No budgetTokens field \u2014 xAI uses level-style reasoning, not token budgets."
195
+ }),
196
+ serviceTier: z.literal("priority").optional().meta({
197
+ title: "Service Tier",
198
+ description: 'xAI priority processing for grok-4.6 (Responses `service_tier: "priority"`). Echo live-verified 2026-08-12. Bills at 2\xD7 after the cache discount (uncached standard-list 2\xD7 confirmed by live ticks; cached/long-context legs follow the official 2\xD7 rule). Omitted requests stay on xAI default. "flex"/"standard"/"batch" are rejected.'
199
+ }),
200
+ timeoutMs: z.number().int().positive().optional().meta({
201
+ title: "Timeout",
202
+ description: "Logical request timeout in milliseconds."
203
+ }),
204
+ providerOptions: z.strictObject({
205
+ xai: XaiProviderOptionsSchema.optional()
206
+ }).optional().meta({
207
+ title: "Provider Options",
208
+ description: "Provider-specific options accepted for grok-4.6."
209
+ })
210
+ }).meta({
211
+ title: "Grok46Config",
212
+ description: "Strict Responses API config for model grok-4.6. Level reasoning (low/medium/high/xhigh), optional priority service tier, tunable sampling, structured output, vision, priced.",
213
+ examples: [{ reasoning: { effort: "high" } }]
214
+ });
215
+ var Grok47ConfigSchema = z.strictObject({
216
+ temperature: z.number().optional().meta({
217
+ title: "Temperature",
218
+ description: "Sampling temperature forwarded verbatim to grok-4.7."
219
+ }),
220
+ topP: z.number().optional().meta({
221
+ title: "Top P",
222
+ description: "Nucleus sampling parameter forwarded verbatim to grok-4.7."
223
+ }),
224
+ maxOutputTokens: z.number().int().positive().optional().meta({
225
+ title: "Max Output Tokens",
226
+ description: "Maximum output token cap for grok-4.7. No artificial ceiling \u2014 xAI accepts arbitrarily large values; truncation surfaces as finishReason:'length', not an error."
227
+ }),
228
+ reasoning: z.strictObject({
229
+ effort: z.enum(["low", "medium", "high", "xhigh"]).meta({
230
+ title: "Reasoning Effort",
231
+ description: 'Reasoning effort for grok-4.7. "low", "medium", "high", and "xhigh" are accepted; "none" is rejected. Vendor default when omitted is "high".'
232
+ })
233
+ }).optional().meta({
234
+ title: "Reasoning",
235
+ description: "grok-4.7 effort-level reasoning configuration. No budgetTokens field \u2014 xAI uses level-style reasoning, not token budgets."
236
+ }),
237
+ serviceTier: z.literal("priority").optional().meta({
238
+ title: "Service Tier",
239
+ description: 'xAI priority processing for grok-4.7 (Responses `service_tier: "priority"`). Bills at 2\xD7 after the cache discount (uncached standard-list 2\xD7 cached/long-context legs follow the official 2\xD7 rule). Omitted requests stay on xAI default. "flex"/"standard"/"batch" are rejected.'
240
+ }),
241
+ timeoutMs: z.number().int().positive().optional().meta({
242
+ title: "Timeout",
243
+ description: "Logical request timeout in milliseconds."
244
+ }),
245
+ providerOptions: z.strictObject({
246
+ xai: XaiProviderOptionsSchema.optional()
247
+ }).optional().meta({
248
+ title: "Provider Options",
249
+ description: "Provider-specific options accepted for grok-4.7."
250
+ })
251
+ }).meta({
252
+ title: "Grok47Config",
253
+ description: "Strict Responses API config for model grok-4.7. Level reasoning (low/medium/high/xhigh), optional priority service tier, tunable sampling, structured output, vision, priced.",
254
+ examples: [{ reasoning: { effort: "high" } }]
255
+ });
256
+
257
+ // src/models.ts
258
+ var grok45ModelDescriptor = {
259
+ model: "grok-4.5",
260
+ provider: "xai",
261
+ pricingFamily: "grok-4.5",
262
+ capabilities: {
263
+ reasoning: true,
264
+ reasoningApi: "level",
265
+ admittedReasoningEfforts: ["low", "medium", "high"],
266
+ structuredOutput: true,
267
+ nativeStructuredOutput: true,
268
+ vision: true,
269
+ audioInput: false,
270
+ sampling: "tunable",
271
+ caching: { explicit: false, minTokens: 0 },
272
+ grounding: true,
273
+ structuredOutputWithTools: true,
274
+ functionCalling: true,
275
+ serviceTiers: ["priority"]
276
+ },
277
+ configSchema: Grok45ConfigSchema,
278
+ configJsonSchema: toConfigJsonSchema(Grok45ConfigSchema),
279
+ validateConfig: zodToStandardSchema(Grok45ConfigSchema)
280
+ };
281
+ var grok46ModelDescriptor = {
282
+ model: "grok-4.6",
283
+ provider: "xai",
284
+ pricingFamily: "grok-4.6",
285
+ capabilities: {
286
+ reasoning: true,
287
+ reasoningApi: "level",
288
+ admittedReasoningEfforts: ["low", "medium", "high", "xhigh"],
289
+ structuredOutput: true,
290
+ nativeStructuredOutput: true,
291
+ vision: true,
292
+ audioInput: false,
293
+ sampling: "tunable",
294
+ caching: { explicit: false, minTokens: 0 },
295
+ grounding: true,
296
+ structuredOutputWithTools: true,
297
+ functionCalling: true,
298
+ serviceTiers: ["priority"]
299
+ },
300
+ configSchema: Grok46ConfigSchema,
301
+ configJsonSchema: toConfigJsonSchema(Grok46ConfigSchema),
302
+ validateConfig: zodToStandardSchema(Grok46ConfigSchema)
303
+ };
304
+ var grok47ModelDescriptor = {
305
+ model: "grok-4.7",
306
+ provider: "xai",
307
+ pricingFamily: "grok-4.7",
308
+ capabilities: {
309
+ reasoning: true,
310
+ reasoningApi: "level",
311
+ admittedReasoningEfforts: ["low", "medium", "high", "xhigh"],
312
+ structuredOutput: true,
313
+ nativeStructuredOutput: true,
314
+ vision: true,
315
+ audioInput: false,
316
+ sampling: "tunable",
317
+ caching: { explicit: false, minTokens: 0 },
318
+ grounding: true,
319
+ structuredOutputWithTools: true,
320
+ functionCalling: true,
321
+ statelessReasoningReplay: true,
322
+ serviceTiers: ["priority"]
323
+ },
324
+ configSchema: Grok47ConfigSchema,
325
+ configJsonSchema: toConfigJsonSchema(Grok47ConfigSchema),
326
+ validateConfig: zodToStandardSchema(Grok47ConfigSchema)
327
+ };
328
+ var xaiModelDescriptors = [
329
+ grok45ModelDescriptor,
330
+ grok46ModelDescriptor,
331
+ grok47ModelDescriptor
332
+ ];
333
+ var xaiRegistry = createModelRegistry(xaiModelDescriptors);
334
+ var JSON_SCHEMA_TYPES = /* @__PURE__ */ new Set([
335
+ "string",
336
+ "number",
337
+ "integer",
338
+ "boolean",
339
+ "object",
340
+ "array",
341
+ "null"
342
+ ]);
343
+ var SINGLE_SCHEMA_KEYWORDS = [
344
+ "additionalProperties",
345
+ "additionalItems",
346
+ "items",
347
+ "contains",
348
+ "not",
349
+ "if",
350
+ "then",
351
+ "else",
352
+ "propertyNames",
353
+ "unevaluatedProperties",
354
+ "unevaluatedItems",
355
+ "contentSchema"
356
+ ];
357
+ var SCHEMA_ARRAY_KEYWORDS = ["items", "prefixItems", "anyOf", "oneOf", "allOf"];
358
+ var SCHEMA_MAP_KEYWORDS = [
359
+ "properties",
360
+ "patternProperties",
361
+ "dependentSchemas",
362
+ // Draft-07 `dependencies`: schema-valued entries are walked; array-valued
363
+ // entries are property-name lists and are skipped by the object check.
364
+ "dependencies",
365
+ "$defs",
366
+ "definitions"
367
+ ];
368
+ function isPlainObject(value) {
369
+ return value !== null && typeof value === "object" && !Array.isArray(value);
370
+ }
371
+ function badSchema(message) {
372
+ return new LlmError(message, { kind: "bad_request", retryable: false, provider: "xai" });
373
+ }
374
+ function assertNode(node, path) {
375
+ const at = path.length > 0 ? path : "<root>";
376
+ if ("nullable" in node) {
377
+ throw badSchema(
378
+ `xAI structured output takes standard JSON Schema, which has no \`nullable\` keyword (found at \`${at}\`). xAI ignores it, so the field would be required and non-null. List 'null' in \`type\` instead, e.g. type: ['string', 'null'].`
379
+ );
380
+ }
381
+ const type = node["type"];
382
+ if (type !== void 0) {
383
+ const names = Array.isArray(type) ? type : [type];
384
+ for (const name of names) {
385
+ if (typeof name !== "string" || !JSON_SCHEMA_TYPES.has(name)) {
386
+ throw badSchema(
387
+ `xAI structured output takes standard JSON Schema; \`type\` ${JSON.stringify(
388
+ name
389
+ )} at \`${at}\` is not a JSON Schema type. Use lowercase string, number, integer, boolean, object, array or null.`
390
+ );
391
+ }
392
+ }
393
+ }
394
+ const child = (segment) => path.length > 0 ? `${path}.${segment}` : segment;
395
+ for (const keyword of SCHEMA_MAP_KEYWORDS) {
396
+ const map = node[keyword];
397
+ if (!isPlainObject(map)) continue;
398
+ for (const [key, member] of Object.entries(map)) {
399
+ if (isPlainObject(member)) assertNode(member, child(`${keyword}.${key}`));
400
+ }
401
+ }
402
+ for (const keyword of SCHEMA_ARRAY_KEYWORDS) {
403
+ const members = node[keyword];
404
+ if (!Array.isArray(members)) continue;
405
+ members.forEach((member, index) => {
406
+ if (isPlainObject(member)) assertNode(member, child(`${keyword}[${index}]`));
407
+ });
408
+ }
409
+ for (const keyword of SINGLE_SCHEMA_KEYWORDS) {
410
+ const member = node[keyword];
411
+ if (isPlainObject(member)) assertNode(member, child(keyword));
412
+ }
413
+ }
414
+ function assertXaiOutputJsonSchema(schema) {
415
+ if (isPlainObject(schema)) assertNode(schema, "");
416
+ }
417
+ var xaiPricingVersion = "xai-2026-09-25";
418
+ var XAI_TOOL_RATE_MICRO_USD = {
419
+ web_search_calls: 5e3,
420
+ x_posts_fetched: 5e3,
421
+ x_users_fetched: 1e4
422
+ };
423
+ var XAI_TOOL_COUNTER_KEYS = [
424
+ "web_search_calls",
425
+ "x_posts_fetched",
426
+ "x_users_fetched"
427
+ ];
428
+ var X_SEARCH_ITEM_COUNTERS = ["x_posts_fetched", "x_users_fetched"];
429
+ var LONG_CONTEXT_THRESHOLD = 2e5;
430
+ var XAI_PRICING = Object.freeze({
431
+ // ── grok-4.5 ── $2.00/$6.00 (<200k), $4.00/$12.00 (>=200k); cached $0.30/$0.60
432
+ "grok-4.5": {
433
+ inputPerM: 2e6,
434
+ cachedPerM: 3e5,
435
+ outputPerM: 6e6,
436
+ gt200k: {
437
+ inputPerM: 4e6,
438
+ cachedPerM: 6e5,
439
+ outputPerM: 12e6
440
+ },
441
+ priorityFactor: 2
442
+ },
443
+ // ── grok-4.6 ── $2.00/$6.00 (<200k), $4.00/$12.00 (>=200k); cached $0.50/$1.00
444
+ "grok-4.6": {
445
+ inputPerM: 2e6,
446
+ cachedPerM: 5e5,
447
+ outputPerM: 6e6,
448
+ gt200k: {
449
+ inputPerM: 4e6,
450
+ cachedPerM: 1e6,
451
+ outputPerM: 12e6
452
+ },
453
+ // Confirmed 2026-08-12 by fixture 12 cost_in_usd_ticks (2× list).
454
+ priorityFactor: 2
455
+ },
456
+ // ── grok-4.7 ── $2.00/$0.50/$6.00 (<200k), $4.00/$1.00/$12.00 (≥200k); priority 2×
457
+ "grok-4.7": {
458
+ inputPerM: 2e6,
459
+ cachedPerM: 5e5,
460
+ outputPerM: 6e6,
461
+ gt200k: {
462
+ inputPerM: 4e6,
463
+ cachedPerM: 1e6,
464
+ outputPerM: 12e6
465
+ },
466
+ priorityFactor: 2
467
+ }
468
+ });
469
+ function lookupRates(model) {
470
+ return Object.hasOwn(XAI_PRICING, model) ? XAI_PRICING[model] : void 0;
471
+ }
472
+ var lookupConcreteRates = (model, tier) => {
473
+ const rates = lookupRates(model);
474
+ if (rates === void 0) return void 0;
475
+ if (tier === void 0 || tier === "default") return rates;
476
+ if (tier === "priority" && rates.priorityFactor !== void 0) {
477
+ return scaleRates(rates, rates.priorityFactor);
478
+ }
479
+ return void 0;
480
+ };
481
+ function selectXaiRates(rates, grossInputTokens) {
482
+ if (rates.gt200k !== void 0 && grossInputTokens >= LONG_CONTEXT_THRESHOLD) {
483
+ return rates.gt200k;
484
+ }
485
+ return {
486
+ inputPerM: rates.inputPerM,
487
+ cachedPerM: rates.cachedPerM,
488
+ outputPerM: rates.outputPerM
489
+ };
490
+ }
491
+ function scaleRates(rates, factor) {
492
+ const scaled = {
493
+ inputPerM: rates.inputPerM * factor,
494
+ cachedPerM: rates.cachedPerM * factor,
495
+ outputPerM: rates.outputPerM * factor
496
+ };
497
+ if (rates.gt200k !== void 0) {
498
+ scaled.gt200k = {
499
+ inputPerM: rates.gt200k.inputPerM * factor,
500
+ cachedPerM: rates.gt200k.cachedPerM * factor,
501
+ outputPerM: rates.gt200k.outputPerM * factor
502
+ };
503
+ }
504
+ return scaled;
505
+ }
506
+ function computeXaiCost(model, usage, tier) {
507
+ const listed = lookupConcreteRates(model, tier);
508
+ if (listed === void 0) {
509
+ return computeCost(model, usage, tier, lookupConcreteRates, xaiPricingVersion);
510
+ }
511
+ const band = selectXaiRates(listed, usage.inputTokens);
512
+ const bandLookup = () => ({
513
+ inputPerM: band.inputPerM,
514
+ cachedPerM: band.cachedPerM,
515
+ outputPerM: band.outputPerM
516
+ });
517
+ const tokenCost = computeCost(model, usage, void 0, bandLookup, xaiPricingVersion);
518
+ const inputCost = tokenCost.details.input;
519
+ const cachedCost = tokenCost.details.cached;
520
+ const outputCost = tokenCost.details.output;
521
+ const serverToolsRequested = usage.details["server_tools_requested"] === 1;
522
+ const xSearchRequested = usage.details["x_search_requested"] === 1;
523
+ const missingXSearchCounter = xSearchRequested && X_SEARCH_ITEM_COUNTERS.some((key) => typeof usage.details[key] !== "number");
524
+ if (missingXSearchCounter || usage.details["server_tools_missing"] === 1) {
525
+ return {
526
+ microUsd: null,
527
+ usd: null,
528
+ pricingVersion: xaiPricingVersion,
529
+ confidence: "estimated",
530
+ details: { input: 0, cached: 0, output: 0, tools: 0 },
531
+ unpricedReason: missingXSearchCounter ? "x_search usage is missing x_posts_fetched or x_users_fetched; refusing to bill a per-call estimate." : "Server tool usage is missing a required counter; refusing to guess a tool cost."
532
+ };
533
+ }
534
+ const attachmentUnpinned = usage.details["attachment_search_unpinned"] === 1;
535
+ const missingWebCounter = serverToolsRequested && !xSearchRequested && !attachmentUnpinned && !XAI_TOOL_COUNTER_KEYS.some((key) => key in usage.details);
536
+ const toolsCost = missingWebCounter ? 0 : XAI_TOOL_COUNTER_KEYS.reduce((sum, key) => {
537
+ const count = usage.details[key];
538
+ if (typeof count !== "number" || count <= 0) return sum;
539
+ return sum + Math.round(count * XAI_TOOL_RATE_MICRO_USD[key]);
540
+ }, 0);
541
+ const microUsd = inputCost + cachedCost + outputCost + toolsCost;
542
+ return {
543
+ microUsd,
544
+ usd: microUsd / 1e6,
545
+ pricingVersion: xaiPricingVersion,
546
+ confidence: missingWebCounter || attachmentUnpinned ? "estimated" : "exact",
547
+ details: {
548
+ input: inputCost,
549
+ cached: cachedCost,
550
+ output: outputCost,
551
+ tools: toolsCost
552
+ }
553
+ };
554
+ }
555
+ function xaiPricingSource() {
556
+ return {
557
+ version: xaiPricingVersion,
558
+ price(model, usage, tier) {
559
+ return computeXaiCost(model, usage, tier);
560
+ },
561
+ hasModel(model) {
562
+ return lookupRates(model) !== void 0;
563
+ },
564
+ listModels() {
565
+ return Object.keys(XAI_PRICING);
566
+ }
567
+ };
568
+ }
569
+
570
+ // src/adapter.ts
31
571
  function isPlainRecord(value) {
32
572
  return typeof value === "object" && value !== null && !Array.isArray(value);
33
573
  }
@@ -90,7 +630,14 @@ function mapPart(p) {
90
630
  return assertNever(p);
91
631
  }
92
632
  }
93
- var XAI_PROVIDER_OPTION_KEYS = /* @__PURE__ */ new Set(["promptCacheKey", "tools", "parallelToolCalls"]);
633
+ var XAI_PROVIDER_OPTION_KEYS = /* @__PURE__ */ new Set([
634
+ "promptCacheKey",
635
+ "tools",
636
+ "parallelToolCalls",
637
+ "toolChoice",
638
+ "maxTurns"
639
+ ]);
640
+ var XAI_SERVER_TOOL_CHOICES = /* @__PURE__ */ new Set(["auto", "required", "none"]);
94
641
  function mapXaiProviderOptions(xaiOpts, model) {
95
642
  if (xaiOpts === void 0) {
96
643
  return {};
@@ -105,7 +652,7 @@ function mapXaiProviderOptions(xaiOpts, model) {
105
652
  throw badXaiRequest(
106
653
  `providerOptions.xai contains unsupported keys [${unknownKeys.join(
107
654
  ", "
108
- )}] for model "${model}". Allowed keys: promptCacheKey, tools, parallelToolCalls.`
655
+ )}] for model "${model}". Allowed keys: promptCacheKey, tools, parallelToolCalls, toolChoice, maxTurns.`
109
656
  );
110
657
  }
111
658
  const mapped = {};
@@ -128,8 +675,47 @@ function mapXaiProviderOptions(xaiOpts, model) {
128
675
  }
129
676
  mapped.parallelToolCalls = xaiOpts["parallelToolCalls"];
130
677
  }
678
+ const toolChoice = xaiOpts["toolChoice"];
679
+ if (toolChoice !== void 0) {
680
+ if (typeof toolChoice !== "string" || !XAI_SERVER_TOOL_CHOICES.has(toolChoice)) {
681
+ throw badXaiRequest(
682
+ `providerOptions.xai.toolChoice must be "auto", "required" or "none" for model "${model}".`
683
+ );
684
+ }
685
+ if (mapped.tools === void 0 || mapped.tools.length === 0) {
686
+ throw badXaiRequest(
687
+ `providerOptions.xai.toolChoice requires a non-empty providerOptions.xai.tools for model "${model}".`
688
+ );
689
+ }
690
+ mapped.toolChoice = toolChoice;
691
+ }
692
+ const maxTurns = xaiOpts["maxTurns"];
693
+ if (maxTurns !== void 0) {
694
+ if (typeof maxTurns !== "number" || !Number.isInteger(maxTurns) || maxTurns < 1) {
695
+ throw badXaiRequest(
696
+ `providerOptions.xai.maxTurns must be an integer >= 1 for model "${model}".`
697
+ );
698
+ }
699
+ if (mapped.tools === void 0 || mapped.tools.length === 0) {
700
+ throw badXaiRequest(
701
+ `providerOptions.xai.maxTurns requires a non-empty providerOptions.xai.tools for model "${model}".`
702
+ );
703
+ }
704
+ mapped.maxTurns = maxTurns;
705
+ }
131
706
  return mapped;
132
707
  }
708
+ function parseXaiReplayState(value, model) {
709
+ if (value === void 0) return void 0;
710
+ if (!isPlainRecord(value) || value["model"] !== model || !Array.isArray(value["input"]) || value["input"].length === 0 || value["input"].some(
711
+ (item) => !isPlainRecord(item) || typeof item["type"] !== "string" && typeof item["role"] !== "string"
712
+ )) {
713
+ throw badXaiRequest(
714
+ `transientProviderState must contain the full xAI wire input for model "${model}".`
715
+ );
716
+ }
717
+ return value;
718
+ }
133
719
  function mapXaiSearchTools(tools, model) {
134
720
  if (!Array.isArray(tools)) {
135
721
  throw badXaiRequest(
@@ -336,9 +922,53 @@ function xaiAdapter(opts) {
336
922
  }
337
923
  const warnings = [];
338
924
  const model = req.model;
925
+ if (req.modelDescriptor !== void 0 && (req.modelDescriptor.model !== model || req.modelDescriptor.provider !== "xai")) {
926
+ throw badXaiRequest(`Mismatched xAI model descriptor for "${model}".`);
927
+ }
928
+ if (xaiRegistry.resolve("xai", model)?.capabilities?.statelessReasoningReplay === true && req.modelDescriptor?.capabilities?.statelessReasoningReplay !== true) {
929
+ throw badXaiRequest(
930
+ `A matching xAI model descriptor with statelessReasoningReplay is required for "${model}".`
931
+ );
932
+ }
339
933
  const genConfig = req.config;
340
- const input = [];
934
+ const xaiProviderConfig = mapXaiProviderOptions(
935
+ genConfig.providerOptions?.["xai"],
936
+ model
937
+ );
938
+ const replayRequired = req.modelDescriptor?.capabilities?.statelessReasoningReplay === true;
939
+ const replayState = parseXaiReplayState(req.transientProviderState, model);
940
+ if (replayState !== void 0 && !replayRequired) {
941
+ throw badXaiRequest(
942
+ `transientProviderState requires a statelessReasoningReplay model descriptor for "${model}".`
943
+ );
944
+ }
945
+ if (replayState !== void 0 && req.messages.length === 0) {
946
+ throw badXaiRequest(
947
+ `Stateless conversation replay for model "${model}" requires new messages to append.`
948
+ );
949
+ }
950
+ const input = [...replayState?.input ?? []];
951
+ const replayCallIds = new Set(
952
+ replayState?.input.filter((item) => isPlainRecord(item) && item["type"] === "function_call").map((item) => isPlainRecord(item) ? item["call_id"] : void 0).filter((id) => typeof id === "string") ?? []
953
+ );
954
+ const replayedResultIds = new Set(
955
+ replayState?.input.filter(
956
+ (item) => isPlainRecord(item) && item["type"] === "function_call_output"
957
+ ).map((item) => isPlainRecord(item) ? item["call_id"] : void 0).filter((id) => typeof id === "string") ?? []
958
+ );
341
959
  for (const msg of req.messages) {
960
+ if (replayState !== void 0 && msg.role === "assistant") {
961
+ throw badXaiRequest(
962
+ `New messages for model "${model}" cannot contain assistant history when transientProviderState is supplied.`
963
+ );
964
+ }
965
+ if (replayRequired && replayState === void 0 && msg.parts.some(
966
+ (part) => part.kind === "tool-call" || part.kind === "tool-result"
967
+ )) {
968
+ throw badXaiRequest(
969
+ `Function-call history for model "${model}" requires transientProviderState from the prior result.`
970
+ );
971
+ }
342
972
  const contentParts = [];
343
973
  for (const part of msg.parts) {
344
974
  if (part.kind === "tool-call") {
@@ -357,6 +987,12 @@ function xaiAdapter(opts) {
357
987
  continue;
358
988
  }
359
989
  if (part.kind === "tool-result") {
990
+ if (replayState !== void 0 && (!replayCallIds.has(part.toolCallId) || replayedResultIds.has(part.toolCallId))) {
991
+ throw badXaiRequest(
992
+ `Tool result "${part.toolCallId}" must match an unanswered function call in transientProviderState.`
993
+ );
994
+ }
995
+ replayedResultIds.add(part.toolCallId);
360
996
  if (contentParts.length > 0) {
361
997
  input.push({
362
998
  role: msg.role === "assistant" ? "assistant" : "user",
@@ -419,9 +1055,9 @@ function xaiAdapter(opts) {
419
1055
  }
420
1056
  if (reasoning.effort !== void 0) {
421
1057
  const effort = reasoning.effort;
422
- if (effort === "none") {
1058
+ if (effort === "none" || effort === "max") {
423
1059
  throw badXaiRequest(
424
- `reasoning.effort "none" is not supported for xai model "${model}".`
1060
+ `reasoning.effort "${effort}" is not supported for xai model "${model}".`
425
1061
  );
426
1062
  }
427
1063
  const admitted = req.modelDescriptor?.capabilities?.admittedReasoningEfforts;
@@ -436,20 +1072,19 @@ function xaiAdapter(opts) {
436
1072
  const structuredOutputRequested = req.outputJsonSchema !== void 0;
437
1073
  if (structuredOutputRequested) {
438
1074
  const schema = req.outputJsonSchema;
1075
+ assertXaiOutputJsonSchema(schema);
439
1076
  const name = isPlainRecord(schema) && typeof schema["title"] === "string" && schema["title"].length > 0 ? schema["title"] : "structured_output";
440
1077
  params.text = {
441
1078
  format: { type: "json_schema", name, schema, strict: true }
442
1079
  };
443
1080
  }
444
- const xaiProviderConfig = mapXaiProviderOptions(
445
- genConfig.providerOptions?.["xai"],
446
- model
447
- );
448
1081
  if (xaiProviderConfig.promptCacheKey !== void 0) {
449
1082
  params.prompt_cache_key = xaiProviderConfig.promptCacheKey;
450
1083
  }
451
- const hasFileRef = req.messages.some(
452
- (msg) => msg.parts.some((part) => part.kind === "file-ref")
1084
+ const hasFileRef = input.some(
1085
+ (item) => isPlainRecord(item) && Array.isArray(item["content"]) && item["content"].some(
1086
+ (part) => isPlainRecord(part) && part["type"] === "input_file"
1087
+ )
453
1088
  );
454
1089
  const searchTools = xaiProviderConfig.tools;
455
1090
  if (searchTools !== void 0) {
@@ -458,7 +1093,33 @@ function xaiAdapter(opts) {
458
1093
  `providerOptions.xai.tools requires capabilities.grounding on the model descriptor for "${model}".`
459
1094
  );
460
1095
  }
1096
+ if (structuredOutputRequested && req.modelDescriptor.capabilities.structuredOutputWithTools !== true) {
1097
+ throw badXaiRequest(
1098
+ `Structured output with providerOptions.xai.tools is not supported for model "${model}".`
1099
+ );
1100
+ }
461
1101
  params.tools = searchTools;
1102
+ if (xaiProviderConfig.toolChoice !== void 0) {
1103
+ if (req.toolChoice !== void 0) {
1104
+ throw badXaiRequest(
1105
+ `providerOptions.xai.toolChoice and toolChoice cannot both be set for model "${model}"; xAI accepts one tool_choice per request.`
1106
+ );
1107
+ }
1108
+ if (req.tools !== void 0 && req.tools.length > 0) {
1109
+ throw badXaiRequest(
1110
+ `providerOptions.xai.toolChoice applies to the server-side search tools only and cannot be combined with function tools for model "${model}".`
1111
+ );
1112
+ }
1113
+ if (hasFileRef) {
1114
+ throw badXaiRequest(
1115
+ `providerOptions.xai.toolChoice cannot be combined with file attachments for model "${model}"; xAI's implicit attachment_search would count as the tool call.`
1116
+ );
1117
+ }
1118
+ params.tool_choice = xaiProviderConfig.toolChoice;
1119
+ }
1120
+ if (xaiProviderConfig.maxTurns !== void 0) {
1121
+ params.max_turns = xaiProviderConfig.maxTurns;
1122
+ }
462
1123
  }
463
1124
  if (req.tools !== void 0 && req.tools.length > 0) {
464
1125
  if (req.modelDescriptor?.capabilities?.functionCalling !== true) {
@@ -544,8 +1205,12 @@ function xaiAdapter(opts) {
544
1205
  const finishReason = mapFinishReason(response);
545
1206
  const expectedToolCounters = expectedServerToolCounters(
546
1207
  xaiProviderConfig.tools);
547
- if (expectedToolCounters.length > 0 || hasFileRef) {
1208
+ const noServerToolRan = response.usage["num_server_side_tools_used"] === 0 && response.usage["server_side_tool_usage_details"] === void 0;
1209
+ if ((expectedToolCounters.length > 0 || hasFileRef) && !noServerToolRan) {
548
1210
  usage.details["server_tools_requested"] = 1;
1211
+ if (xaiProviderConfig.tools?.some((tool) => tool["type"] === "x_search") === true) {
1212
+ usage.details["x_search_requested"] = 1;
1213
+ }
549
1214
  const missing = expectedToolCounters.filter((key) => !(key in usage.details));
550
1215
  if (missing.length > 0) {
551
1216
  usage.details["server_tools_missing"] = 1;
@@ -553,7 +1218,7 @@ function xaiAdapter(opts) {
553
1218
  type: "other",
554
1219
  message: `xai: server tools were requested but usage is missing counters [${missing.join(
555
1220
  ", "
556
- )}]; tool cost will be estimated.`
1221
+ )}]; the call is unpriced.`
557
1222
  });
558
1223
  }
559
1224
  if (hasFileRef) {
@@ -573,6 +1238,14 @@ function xaiAdapter(opts) {
573
1238
  if (isPlainRecord(response.metadata)) {
574
1239
  providerMeta["metadata"] = response.metadata;
575
1240
  }
1241
+ let transientProviderState;
1242
+ if (replayRequired) {
1243
+ const state = {
1244
+ model,
1245
+ input: [...params.input, ...response.output]
1246
+ };
1247
+ transientProviderState = state;
1248
+ }
576
1249
  const servedServiceTier = typeof response.service_tier === "string" && response.service_tier.length > 0 ? response.service_tier : void 0;
577
1250
  const result = {
578
1251
  model: response.model,
@@ -585,6 +1258,7 @@ function xaiAdapter(opts) {
585
1258
  ...rawStructured !== void 0 ? { rawStructured } : {},
586
1259
  ...servedServiceTier !== void 0 ? { servedServiceTier } : {},
587
1260
  ...Object.keys(providerMeta).length > 0 ? { providerMetadata: providerMeta } : {},
1261
+ ...transientProviderState !== void 0 ? { transientProviderState } : {},
588
1262
  ...citations.length > 0 ? { citations } : {},
589
1263
  ...toolCalls.length > 0 ? { toolCalls, finishReason: "tool_calls" } : {}
590
1264
  };
@@ -656,13 +1330,12 @@ function xaiAdapter(opts) {
656
1330
  };
657
1331
  }
658
1332
  var WEB_SEARCH_COUNTER = "web_search_calls";
659
- var X_SEARCH_COUNTER = "x_search_calls";
660
1333
  function expectedServerToolCounters(tools, _hasFileRef) {
661
1334
  const keys = [];
662
1335
  if (tools !== void 0) {
663
1336
  for (const tool of tools) {
664
1337
  if (tool["type"] === "web_search") keys.push(WEB_SEARCH_COUNTER);
665
- if (tool["type"] === "x_search") keys.push(X_SEARCH_COUNTER);
1338
+ if (tool["type"] === "x_search") keys.push(...X_SEARCH_ITEM_COUNTERS);
666
1339
  }
667
1340
  }
668
1341
  return keys;
@@ -987,553 +1660,211 @@ var XaiFileStore = class {
987
1660
  this.filesUrl(),
988
1661
  this.requestInit("POST", {
989
1662
  body: form,
990
- ...signal !== void 0 ? { signal } : {}
991
- })
992
- );
993
- } catch (e) {
994
- if (signal?.aborted === true) {
995
- throw new LlmError("xAI file upload aborted", {
996
- kind: "aborted",
997
- retryable: false,
998
- provider: "xai"
999
- });
1000
- }
1001
- throw classifyStoreError(e);
1002
- }
1003
- if (!res.ok) {
1004
- try {
1005
- await throwHttpFailure(res);
1006
- } catch (e) {
1007
- throw classifyStoreError(e);
1008
- }
1009
- }
1010
- let json;
1011
- try {
1012
- json = await res.json();
1013
- } catch (e) {
1014
- throw new LlmError("xAI file upload returned non-JSON body", {
1015
- kind: "server",
1016
- retryable: false,
1017
- provider: "xai",
1018
- cause: e
1019
- });
1020
- }
1021
- return makeHandle(json);
1022
- }
1023
- async get(fileId, signal) {
1024
- if (typeof fileId !== "string" || fileId.trim() === "") {
1025
- throw badRequest("fileId must be a non-empty string.");
1026
- }
1027
- let res;
1028
- try {
1029
- res = await this.fetchImpl(
1030
- this.filesUrl(fileId),
1031
- this.requestInit("GET", signal !== void 0 ? { signal } : {})
1032
- );
1033
- } catch (e) {
1034
- if (signal?.aborted === true) {
1035
- throw new LlmError("xAI file get aborted", {
1036
- kind: "aborted",
1037
- retryable: false,
1038
- provider: "xai"
1039
- });
1040
- }
1041
- throw classifyStoreError(e);
1042
- }
1043
- if (res.status === 404) {
1044
- throw notFoundError(fileId, "get");
1045
- }
1046
- if (!res.ok) {
1047
- try {
1048
- await throwHttpFailure(res);
1049
- } catch (e) {
1050
- throw classifyStoreError(e);
1051
- }
1052
- }
1053
- const json = await res.json();
1054
- return makeHandle(json);
1055
- }
1056
- async list(opts = {}, signal) {
1057
- if (opts.limit !== void 0) {
1058
- if (typeof opts.limit !== "number" || !Number.isInteger(opts.limit) || opts.limit < 1 || opts.limit > 100) {
1059
- throw badRequest("list.limit must be an integer in [1, 100].");
1060
- }
1061
- }
1062
- const params = new URLSearchParams();
1063
- if (opts.limit !== void 0) params.set("limit", String(opts.limit));
1064
- if (opts.order !== void 0) params.set("order", opts.order);
1065
- if (opts.sortBy !== void 0) params.set("sort_by", opts.sortBy);
1066
- if (opts.paginationToken !== void 0) {
1067
- params.set("pagination_token", opts.paginationToken);
1068
- }
1069
- const qs = params.toString();
1070
- const url = qs.length > 0 ? `${this.filesUrl()}?${qs}` : this.filesUrl();
1071
- let res;
1072
- try {
1073
- res = await this.fetchImpl(
1074
- url,
1075
- this.requestInit("GET", signal !== void 0 ? { signal } : {})
1076
- );
1077
- } catch (e) {
1078
- if (signal?.aborted === true) {
1079
- throw new LlmError("xAI file list aborted", {
1080
- kind: "aborted",
1081
- retryable: false,
1082
- provider: "xai"
1083
- });
1084
- }
1085
- throw classifyStoreError(e);
1086
- }
1087
- if (!res.ok) {
1088
- try {
1089
- await throwHttpFailure(res);
1090
- } catch (e) {
1091
- throw classifyStoreError(e);
1092
- }
1093
- }
1094
- const json = await res.json();
1095
- const files = Array.isArray(json.data) ? json.data.map((f) => makeHandle(f)) : [];
1096
- const result = { files };
1097
- if (typeof json.pagination_token === "string" && json.pagination_token.length > 0) {
1098
- result.paginationToken = json.pagination_token;
1099
- }
1100
- return result;
1101
- }
1102
- /**
1103
- * Delete a file. Idempotent: HTTP 404 → success.
1104
- *
1105
- * Default (`failClosed` omitted/false): non-404 errors go to `onDeleteError`
1106
- * and resolve (P5 fail-open). With `failClosed: true`, non-404 errors throw
1107
- * typed `LlmError` and `onDeleteError` is not called.
1108
- *
1109
- * Empty/blank ids always throw `bad_request` (caller fault).
1110
- */
1111
- async delete(fileIdOrHandle, opts) {
1112
- const fileId = resolveFileId(fileIdOrHandle);
1113
- if (typeof fileId !== "string" || fileId.trim() === "") {
1114
- throw badRequest("fileId must be a non-empty string.");
1115
- }
1116
- const failClosed = opts?.failClosed === true;
1117
- const signal = opts?.signal;
1118
- try {
1119
- const res = await this.fetchImpl(
1120
- this.filesUrl(fileId),
1121
- this.requestInit("DELETE", signal !== void 0 ? { signal } : {})
1122
- );
1123
- if (res.status === 404) {
1124
- return;
1125
- }
1126
- if (!res.ok) {
1127
- await throwHttpFailure(res);
1128
- }
1129
- } catch (err) {
1130
- if (isNotFoundError(err)) {
1131
- return;
1132
- }
1133
- const classified = signal?.aborted === true && !(err instanceof LlmError) ? new LlmError("xAI file delete aborted", {
1134
- kind: "aborted",
1135
- retryable: false,
1136
- provider: "xai",
1137
- cause: err
1138
- }) : classifyStoreError(err);
1139
- if (failClosed) {
1140
- throw classified;
1141
- }
1142
- this.onDeleteError(fileId, classified);
1143
- }
1144
- }
1145
- /**
1146
- * Delete many files.
1147
- *
1148
- * Fail-open (default): `Promise.allSettled` — each failure → `onDeleteError`.
1149
- * Fail-closed: `Promise.all` — first throw rejects; in-flight siblings are
1150
- * not cancelled (partial deletes may already have succeeded at the provider).
1151
- * Prefer per-id delete + host DB mark when gating durable release state.
1152
- */
1153
- async deleteAll(ids, opts) {
1154
- if (opts?.failClosed === true) {
1155
- await Promise.all(ids.map((id) => this.delete(id, opts)));
1156
- return;
1157
- }
1158
- await Promise.allSettled(ids.map((id) => this.delete(id, opts)));
1159
- }
1160
- /** Download raw file bytes. */
1161
- async getContent(fileId, signal) {
1162
- if (typeof fileId !== "string" || fileId.trim() === "") {
1163
- throw badRequest("fileId must be a non-empty string.");
1164
- }
1165
- let res;
1166
- try {
1167
- res = await this.fetchImpl(
1168
- this.filesUrl(`${fileId}/content`),
1169
- this.requestInit("GET", signal !== void 0 ? { signal } : {})
1663
+ ...signal !== void 0 ? { signal } : {}
1664
+ })
1170
1665
  );
1171
1666
  } catch (e) {
1172
1667
  if (signal?.aborted === true) {
1173
- throw new LlmError("xAI file content download aborted", {
1174
- kind: "aborted",
1175
- retryable: false,
1176
- provider: "xai"
1177
- });
1178
- }
1179
- throw classifyStoreError(e);
1180
- }
1181
- if (res.status === 404) {
1182
- throw notFoundError(fileId, "getContent");
1183
- }
1184
- if (!res.ok) {
1185
- try {
1186
- await throwHttpFailure(res);
1187
- } catch (e) {
1188
- throw classifyStoreError(e);
1189
- }
1190
- }
1191
- const buf = await res.arrayBuffer();
1192
- return new Uint8Array(buf);
1193
- }
1194
- };
1195
- var webSearchFlags = {
1196
- enableImageUnderstanding: z.boolean().optional().meta({
1197
- title: "Enable Image Understanding",
1198
- description: "Ask xAI to analyze images found during web search."
1199
- }),
1200
- enableImageSearch: z.boolean().optional().meta({
1201
- title: "Enable Image Search",
1202
- description: "Ask xAI to include image search results."
1203
- })
1204
- };
1205
- var XaiWebSearchToolSchema = z.union([
1206
- z.strictObject({
1207
- type: z.literal("web_search"),
1208
- allowedDomains: z.array(z.string()).max(5),
1209
- ...webSearchFlags
1210
- }),
1211
- z.strictObject({
1212
- type: z.literal("web_search"),
1213
- excludedDomains: z.array(z.string()).max(5),
1214
- ...webSearchFlags
1215
- }),
1216
- z.strictObject({
1217
- type: z.literal("web_search"),
1218
- ...webSearchFlags
1219
- })
1220
- ]).meta({
1221
- title: "XaiWebSearchTool",
1222
- description: "xAI web_search server tool. allowedDomains and excludedDomains are mutually exclusive (max 5)."
1223
- });
1224
- var xSearchFlags = {
1225
- fromDate: z.iso.date().optional().meta({
1226
- title: "From Date",
1227
- description: "Inclusive ISO-8601 date lower bound for X search."
1228
- }),
1229
- toDate: z.iso.date().optional().meta({
1230
- title: "To Date",
1231
- description: "Inclusive ISO-8601 date upper bound for X search."
1232
- }),
1233
- enableImageUnderstanding: z.boolean().optional().meta({
1234
- title: "Enable Image Understanding",
1235
- description: "Ask xAI to analyze images in matched posts."
1236
- }),
1237
- enableVideoUnderstanding: z.boolean().optional().meta({
1238
- title: "Enable Video Understanding",
1239
- description: "Ask xAI to analyze videos in matched posts."
1240
- })
1241
- };
1242
- var XaiXSearchToolSchema = z.union([
1243
- z.strictObject({
1244
- type: z.literal("x_search"),
1245
- allowedXHandles: z.array(z.string()).max(20),
1246
- ...xSearchFlags
1247
- }),
1248
- z.strictObject({
1249
- type: z.literal("x_search"),
1250
- excludedXHandles: z.array(z.string()).max(20),
1251
- ...xSearchFlags
1252
- }),
1253
- z.strictObject({
1254
- type: z.literal("x_search"),
1255
- ...xSearchFlags
1256
- })
1257
- ]).meta({
1258
- title: "XaiXSearchTool",
1259
- description: "xAI x_search server tool. allowedXHandles and excludedXHandles are mutually exclusive (max 20)."
1260
- });
1261
- var XaiToolsSchema = z.union([
1262
- z.tuple([XaiWebSearchToolSchema]),
1263
- z.tuple([XaiXSearchToolSchema]),
1264
- z.tuple([XaiWebSearchToolSchema, XaiXSearchToolSchema]),
1265
- z.tuple([XaiXSearchToolSchema, XaiWebSearchToolSchema])
1266
- ]).meta({
1267
- title: "XaiTools",
1268
- description: "xAI Live Search tools. At most one web_search and at most one x_search."
1269
- });
1270
- var XaiProviderOptionsSchema = z.strictObject({
1271
- promptCacheKey: z.string().min(1).optional().meta({
1272
- title: "Prompt Cache Key",
1273
- description: "xAI conversation-routing cache key \u2014 maps to Responses API `prompt_cache_key`."
1274
- }),
1275
- tools: XaiToolsSchema.optional().meta({
1276
- title: "Live Search Tools",
1277
- description: "xAI server-side web_search / x_search tools."
1278
- }),
1279
- parallelToolCalls: z.boolean().optional().meta({
1280
- title: "Parallel Tool Calls",
1281
- description: "xAI Responses parallel_tool_calls. Not a generic contract field."
1282
- })
1283
- }).meta({
1284
- title: "xAI Provider Options",
1285
- description: "Allowlisted xAI provider options."
1286
- });
1287
-
1288
- // src/model-config/grok-4-5.ts
1289
- var Grok45ConfigSchema = z.strictObject({
1290
- temperature: z.number().optional().meta({
1291
- title: "Temperature",
1292
- description: "Sampling temperature forwarded verbatim to grok-4.5."
1293
- }),
1294
- topP: z.number().optional().meta({
1295
- title: "Top P",
1296
- description: "Nucleus sampling parameter forwarded verbatim to grok-4.5."
1297
- }),
1298
- maxOutputTokens: z.number().int().positive().optional().meta({
1299
- title: "Max Output Tokens",
1300
- description: "Maximum output token cap for grok-4.5. No artificial ceiling \u2014 xAI accepts arbitrarily large values (live-verified); truncation surfaces as finishReason:'length', not an error."
1301
- }),
1302
- reasoning: z.strictObject({
1303
- effort: z.enum(["low", "medium", "high"]).meta({
1304
- title: "Reasoning Effort",
1305
- description: 'Reasoning effort for grok-4.5. "low", "medium", and "high" are admitted (live-verified 2026-08-24); "none"/"xhigh" are rejected by the live API. Vendor default when omitted is "high".'
1306
- })
1307
- }).optional().meta({
1308
- title: "Reasoning",
1309
- description: "grok-4.5 effort-level reasoning configuration. No budgetTokens field \u2014 xAI uses level-style reasoning, not token budgets."
1310
- }),
1311
- timeoutMs: z.number().int().positive().optional().meta({
1312
- title: "Timeout",
1313
- description: "Logical request timeout in milliseconds."
1314
- }),
1315
- providerOptions: z.strictObject({
1316
- xai: XaiProviderOptionsSchema.optional()
1317
- }).optional().meta({
1318
- title: "Provider Options",
1319
- description: "Provider-specific options accepted for grok-4.5."
1320
- })
1321
- }).meta({
1322
- title: "Grok45Config",
1323
- description: "Strict Responses API config for model grok-4.5. Level reasoning (low/medium/high), tunable sampling, no service tiers, structured output, vision, Live Search tools, priced.",
1324
- examples: [{ reasoning: { effort: "high" } }]
1325
- });
1326
- var Grok46ConfigSchema = z.strictObject({
1327
- temperature: z.number().optional().meta({
1328
- title: "Temperature",
1329
- description: "Sampling temperature forwarded verbatim to grok-4.6."
1330
- }),
1331
- topP: z.number().optional().meta({
1332
- title: "Top P",
1333
- description: "Nucleus sampling parameter forwarded verbatim to grok-4.6."
1334
- }),
1335
- maxOutputTokens: z.number().int().positive().optional().meta({
1336
- title: "Max Output Tokens",
1337
- description: "Maximum output token cap for grok-4.6. No artificial ceiling \u2014 xAI accepts arbitrarily large values; truncation surfaces as finishReason:'length', not an error."
1338
- }),
1339
- reasoning: z.strictObject({
1340
- effort: z.enum(["low", "medium", "high", "xhigh"]).meta({
1341
- title: "Reasoning Effort",
1342
- description: 'Reasoning effort for grok-4.6. Live-verified 2026-08-12: "low", "medium", "high", and "xhigh" are accepted; "none" is rejected. Vendor default when omitted is "high".'
1343
- })
1344
- }).optional().meta({
1345
- title: "Reasoning",
1346
- description: "grok-4.6 effort-level reasoning configuration. No budgetTokens field \u2014 xAI uses level-style reasoning, not token budgets."
1347
- }),
1348
- serviceTier: z.literal("priority").optional().meta({
1349
- title: "Service Tier",
1350
- description: 'xAI priority processing for grok-4.6 (Responses `service_tier: "priority"`). Echo live-verified 2026-08-12. Bills at 2\xD7 after the cache discount (uncached standard-list 2\xD7 confirmed by live ticks; cached/long-context legs follow the official 2\xD7 rule). Omitted requests stay on xAI default. "flex"/"standard"/"batch" are rejected.'
1351
- }),
1352
- timeoutMs: z.number().int().positive().optional().meta({
1353
- title: "Timeout",
1354
- description: "Logical request timeout in milliseconds."
1355
- }),
1356
- providerOptions: z.strictObject({
1357
- xai: XaiProviderOptionsSchema.optional()
1358
- }).optional().meta({
1359
- title: "Provider Options",
1360
- description: "Provider-specific options accepted for grok-4.6."
1361
- })
1362
- }).meta({
1363
- title: "Grok46Config",
1364
- description: "Strict Responses API config for model grok-4.6. Level reasoning (low/medium/high/xhigh), optional priority service tier, tunable sampling, structured output, vision, priced.",
1365
- examples: [{ reasoning: { effort: "high" } }]
1366
- });
1367
-
1368
- // src/models.ts
1369
- var grok45ModelDescriptor = {
1370
- model: "grok-4.5",
1371
- provider: "xai",
1372
- pricingFamily: "grok-4.5",
1373
- capabilities: {
1374
- reasoning: true,
1375
- reasoningApi: "level",
1376
- admittedReasoningEfforts: ["low", "medium", "high"],
1377
- structuredOutput: true,
1378
- nativeStructuredOutput: true,
1379
- vision: true,
1380
- audioInput: false,
1381
- sampling: "tunable",
1382
- caching: { explicit: false, minTokens: 0 },
1383
- grounding: true,
1384
- functionCalling: true
1385
- // No serviceTiers key — grok-4.5 has no admitted service-tier vocabulary.
1386
- },
1387
- configSchema: Grok45ConfigSchema,
1388
- configJsonSchema: toConfigJsonSchema(Grok45ConfigSchema),
1389
- validateConfig: zodToStandardSchema(Grok45ConfigSchema)
1390
- };
1391
- var grok46ModelDescriptor = {
1392
- model: "grok-4.6",
1393
- provider: "xai",
1394
- pricingFamily: "grok-4.6",
1395
- capabilities: {
1396
- reasoning: true,
1397
- reasoningApi: "level",
1398
- admittedReasoningEfforts: ["low", "medium", "high", "xhigh"],
1399
- structuredOutput: true,
1400
- nativeStructuredOutput: true,
1401
- vision: true,
1402
- audioInput: false,
1403
- sampling: "tunable",
1404
- caching: { explicit: false, minTokens: 0 },
1405
- grounding: true,
1406
- functionCalling: true,
1407
- serviceTiers: ["priority"]
1408
- },
1409
- configSchema: Grok46ConfigSchema,
1410
- configJsonSchema: toConfigJsonSchema(Grok46ConfigSchema),
1411
- validateConfig: zodToStandardSchema(Grok46ConfigSchema)
1412
- };
1413
- var xaiModelDescriptors = [
1414
- grok45ModelDescriptor,
1415
- grok46ModelDescriptor
1416
- ];
1417
- var xaiRegistry = createModelRegistry(xaiModelDescriptors);
1418
-
1419
- // src/pricing.ts
1420
- var xaiPricingVersion = "xai-2026-08-24";
1421
- var XAI_TOOL_RATE_MICRO_USD = {
1422
- web_search_calls: 5e3,
1423
- x_search_calls: 5e3
1424
- };
1425
- var XAI_TOOL_COUNTER_KEYS = ["web_search_calls", "x_search_calls"];
1426
- var XAI_PRICING = Object.freeze({
1427
- // ── grok-4.5 ── $2.00/$6.00 (≤200k), $4.00/$12.00 (>200k); cached $0.30/$0.60
1428
- "grok-4.5": {
1429
- inputPerM: 2e6,
1430
- cachedPerM: 3e5,
1431
- outputPerM: 6e6,
1432
- gt200k: {
1433
- inputPerM: 4e6,
1434
- cachedPerM: 6e5,
1435
- outputPerM: 12e6
1668
+ throw new LlmError("xAI file upload aborted", {
1669
+ kind: "aborted",
1670
+ retryable: false,
1671
+ provider: "xai"
1672
+ });
1673
+ }
1674
+ throw classifyStoreError(e);
1436
1675
  }
1437
- },
1438
- // ── grok-4.6 ── $2.00/$6.00 (≤200k), $4.00/$12.00 (>200k); cached $0.50/$1.00
1439
- "grok-4.6": {
1440
- inputPerM: 2e6,
1441
- cachedPerM: 5e5,
1442
- outputPerM: 6e6,
1443
- gt200k: {
1444
- inputPerM: 4e6,
1445
- cachedPerM: 1e6,
1446
- outputPerM: 12e6
1447
- },
1448
- // Confirmed 2026-08-12 by fixture 12 cost_in_usd_ticks (2× list).
1449
- priorityFactor: 2
1676
+ if (!res.ok) {
1677
+ try {
1678
+ await throwHttpFailure(res);
1679
+ } catch (e) {
1680
+ throw classifyStoreError(e);
1681
+ }
1682
+ }
1683
+ let json;
1684
+ try {
1685
+ json = await res.json();
1686
+ } catch (e) {
1687
+ throw new LlmError("xAI file upload returned non-JSON body", {
1688
+ kind: "server",
1689
+ retryable: false,
1690
+ provider: "xai",
1691
+ cause: e
1692
+ });
1693
+ }
1694
+ return makeHandle(json);
1450
1695
  }
1451
- });
1452
- var LONG_CONTEXT_THRESHOLD = 2e5;
1453
- function lookupRates(model) {
1454
- return XAI_PRICING[model];
1455
- }
1456
- function selectRates(rates, grossInputTokens) {
1457
- if (rates.gt200k !== void 0 && grossInputTokens > LONG_CONTEXT_THRESHOLD) {
1458
- return rates.gt200k;
1696
+ async get(fileId, signal) {
1697
+ if (typeof fileId !== "string" || fileId.trim() === "") {
1698
+ throw badRequest("fileId must be a non-empty string.");
1699
+ }
1700
+ let res;
1701
+ try {
1702
+ res = await this.fetchImpl(
1703
+ this.filesUrl(fileId),
1704
+ this.requestInit("GET", signal !== void 0 ? { signal } : {})
1705
+ );
1706
+ } catch (e) {
1707
+ if (signal?.aborted === true) {
1708
+ throw new LlmError("xAI file get aborted", {
1709
+ kind: "aborted",
1710
+ retryable: false,
1711
+ provider: "xai"
1712
+ });
1713
+ }
1714
+ throw classifyStoreError(e);
1715
+ }
1716
+ if (res.status === 404) {
1717
+ throw notFoundError(fileId, "get");
1718
+ }
1719
+ if (!res.ok) {
1720
+ try {
1721
+ await throwHttpFailure(res);
1722
+ } catch (e) {
1723
+ throw classifyStoreError(e);
1724
+ }
1725
+ }
1726
+ const json = await res.json();
1727
+ return makeHandle(json);
1459
1728
  }
1460
- return {
1461
- inputPerM: rates.inputPerM,
1462
- cachedPerM: rates.cachedPerM,
1463
- outputPerM: rates.outputPerM
1464
- };
1465
- }
1466
- function computeXaiCost(model, usage, tier) {
1467
- const rates = lookupRates(model);
1468
- if (rates === void 0) {
1469
- return {
1470
- microUsd: null,
1471
- usd: null,
1472
- pricingVersion: xaiPricingVersion,
1473
- confidence: "estimated",
1474
- details: { input: 0, cached: 0, output: 0, tools: 0 },
1475
- unpricedReason: `Unknown model "${model}"; no pricing entry found.`
1476
- };
1729
+ async list(opts = {}, signal) {
1730
+ if (opts.limit !== void 0) {
1731
+ if (typeof opts.limit !== "number" || !Number.isInteger(opts.limit) || opts.limit < 1 || opts.limit > 100) {
1732
+ throw badRequest("list.limit must be an integer in [1, 100].");
1733
+ }
1734
+ }
1735
+ const params = new URLSearchParams();
1736
+ if (opts.limit !== void 0) params.set("limit", String(opts.limit));
1737
+ if (opts.order !== void 0) params.set("order", opts.order);
1738
+ if (opts.sortBy !== void 0) params.set("sort_by", opts.sortBy);
1739
+ if (opts.paginationToken !== void 0) {
1740
+ params.set("pagination_token", opts.paginationToken);
1741
+ }
1742
+ const qs = params.toString();
1743
+ const url = qs.length > 0 ? `${this.filesUrl()}?${qs}` : this.filesUrl();
1744
+ let res;
1745
+ try {
1746
+ res = await this.fetchImpl(
1747
+ url,
1748
+ this.requestInit("GET", signal !== void 0 ? { signal } : {})
1749
+ );
1750
+ } catch (e) {
1751
+ if (signal?.aborted === true) {
1752
+ throw new LlmError("xAI file list aborted", {
1753
+ kind: "aborted",
1754
+ retryable: false,
1755
+ provider: "xai"
1756
+ });
1757
+ }
1758
+ throw classifyStoreError(e);
1759
+ }
1760
+ if (!res.ok) {
1761
+ try {
1762
+ await throwHttpFailure(res);
1763
+ } catch (e) {
1764
+ throw classifyStoreError(e);
1765
+ }
1766
+ }
1767
+ const json = await res.json();
1768
+ const files = Array.isArray(json.data) ? json.data.map((f) => makeHandle(f)) : [];
1769
+ const result = { files };
1770
+ if (typeof json.pagination_token === "string" && json.pagination_token.length > 0) {
1771
+ result.paginationToken = json.pagination_token;
1772
+ }
1773
+ return result;
1477
1774
  }
1478
- let factor = 1;
1479
- if (tier !== void 0 && tier !== "default") {
1480
- if (tier === "priority" && rates.priorityFactor !== void 0) {
1481
- factor = rates.priorityFactor;
1482
- } else {
1483
- return {
1484
- microUsd: null,
1485
- usd: null,
1486
- pricingVersion: xaiPricingVersion,
1487
- confidence: "estimated",
1488
- details: { input: 0, cached: 0, output: 0, tools: 0 },
1489
- unpricedReason: `Unknown service tier "${tier}"; xai model "${model}" has no such tier, refusing to guess a pricing multiplier.`
1490
- };
1775
+ /**
1776
+ * Delete a file. Idempotent: HTTP 404 → success.
1777
+ *
1778
+ * Default (`failClosed` omitted/false): non-404 errors go to `onDeleteError`
1779
+ * and resolve (P5 fail-open). With `failClosed: true`, non-404 errors throw
1780
+ * typed `LlmError` and `onDeleteError` is not called.
1781
+ *
1782
+ * Empty/blank ids always throw `bad_request` (caller fault).
1783
+ */
1784
+ async delete(fileIdOrHandle, opts) {
1785
+ const fileId = resolveFileId(fileIdOrHandle);
1786
+ if (typeof fileId !== "string" || fileId.trim() === "") {
1787
+ throw badRequest("fileId must be a non-empty string.");
1788
+ }
1789
+ const failClosed = opts?.failClosed === true;
1790
+ const signal = opts?.signal;
1791
+ try {
1792
+ const res = await this.fetchImpl(
1793
+ this.filesUrl(fileId),
1794
+ this.requestInit("DELETE", signal !== void 0 ? { signal } : {})
1795
+ );
1796
+ if (res.status === 404) {
1797
+ return;
1798
+ }
1799
+ if (!res.ok) {
1800
+ await throwHttpFailure(res);
1801
+ }
1802
+ } catch (err) {
1803
+ if (isNotFoundError(err)) {
1804
+ return;
1805
+ }
1806
+ const classified = signal?.aborted === true && !(err instanceof LlmError) ? new LlmError("xAI file delete aborted", {
1807
+ kind: "aborted",
1808
+ retryable: false,
1809
+ provider: "xai",
1810
+ cause: err
1811
+ }) : classifyStoreError(err);
1812
+ if (failClosed) {
1813
+ throw classified;
1814
+ }
1815
+ this.onDeleteError(fileId, classified);
1491
1816
  }
1492
1817
  }
1493
- const base = selectRates(rates, usage.inputTokens);
1494
- const cached = usage.cachedInputTokens ?? 0;
1495
- const billableInput = Math.max(0, usage.inputTokens - cached);
1496
- const inputCost = Math.round(billableInput * base.inputPerM * factor / 1e6);
1497
- const cachedCost = Math.round(cached * base.cachedPerM * factor / 1e6);
1498
- const outputCost = Math.round(
1499
- usage.outputTokens * base.outputPerM * factor / 1e6
1500
- );
1501
- const serverToolsRequested = usage.details["server_tools_requested"] === 1;
1502
- const missingRequestedCounters = usage.details["server_tools_missing"] === 1 || serverToolsRequested && usage.details["attachment_search_unpinned"] !== 1 && !XAI_TOOL_COUNTER_KEYS.some((key) => key in usage.details);
1503
- const attachmentUnpinned = usage.details["attachment_search_unpinned"] === 1;
1504
- const toolsCost = missingRequestedCounters ? 0 : XAI_TOOL_COUNTER_KEYS.reduce((sum, key) => {
1505
- const count = usage.details[key];
1506
- if (typeof count !== "number" || count <= 0) return sum;
1507
- return sum + Math.round(count * XAI_TOOL_RATE_MICRO_USD[key]);
1508
- }, 0);
1509
- const microUsd = inputCost + cachedCost + outputCost + toolsCost;
1510
- return {
1511
- microUsd,
1512
- usd: microUsd / 1e6,
1513
- pricingVersion: xaiPricingVersion,
1514
- confidence: missingRequestedCounters || attachmentUnpinned ? "estimated" : "exact",
1515
- details: {
1516
- input: inputCost,
1517
- cached: cachedCost,
1518
- output: outputCost,
1519
- tools: toolsCost
1818
+ /**
1819
+ * Delete many files.
1820
+ *
1821
+ * Fail-open (default): `Promise.allSettled` — each failure → `onDeleteError`.
1822
+ * Fail-closed: `Promise.all` — first throw rejects; in-flight siblings are
1823
+ * not cancelled (partial deletes may already have succeeded at the provider).
1824
+ * Prefer per-id delete + host DB mark when gating durable release state.
1825
+ */
1826
+ async deleteAll(ids, opts) {
1827
+ if (opts?.failClosed === true) {
1828
+ await Promise.all(ids.map((id) => this.delete(id, opts)));
1829
+ return;
1520
1830
  }
1521
- };
1522
- }
1523
- function xaiPricingSource() {
1524
- return {
1525
- version: xaiPricingVersion,
1526
- price(model, usage, tier) {
1527
- return computeXaiCost(model, usage, tier);
1528
- },
1529
- hasModel(model) {
1530
- return lookupRates(model) !== void 0;
1531
- },
1532
- listModels() {
1533
- return Object.keys(XAI_PRICING);
1831
+ await Promise.allSettled(ids.map((id) => this.delete(id, opts)));
1832
+ }
1833
+ /** Download raw file bytes. */
1834
+ async getContent(fileId, signal) {
1835
+ if (typeof fileId !== "string" || fileId.trim() === "") {
1836
+ throw badRequest("fileId must be a non-empty string.");
1534
1837
  }
1535
- };
1536
- }
1838
+ let res;
1839
+ try {
1840
+ res = await this.fetchImpl(
1841
+ this.filesUrl(`${fileId}/content`),
1842
+ this.requestInit("GET", signal !== void 0 ? { signal } : {})
1843
+ );
1844
+ } catch (e) {
1845
+ if (signal?.aborted === true) {
1846
+ throw new LlmError("xAI file content download aborted", {
1847
+ kind: "aborted",
1848
+ retryable: false,
1849
+ provider: "xai"
1850
+ });
1851
+ }
1852
+ throw classifyStoreError(e);
1853
+ }
1854
+ if (res.status === 404) {
1855
+ throw notFoundError(fileId, "getContent");
1856
+ }
1857
+ if (!res.ok) {
1858
+ try {
1859
+ await throwHttpFailure(res);
1860
+ } catch (e) {
1861
+ throw classifyStoreError(e);
1862
+ }
1863
+ }
1864
+ const buf = await res.arrayBuffer();
1865
+ return new Uint8Array(buf);
1866
+ }
1867
+ };
1537
1868
 
1538
1869
  // src/provider.ts
1539
1870
  function xaiProvider(opts) {
@@ -1544,6 +1875,6 @@ function xaiProvider(opts) {
1544
1875
  };
1545
1876
  }
1546
1877
 
1547
- export { Grok45ConfigSchema, Grok46ConfigSchema, XAI_FILES_DEFAULT_BASE_URL, XAI_FILE_MAX_BYTES, XAI_FILE_TTL_MAX_SECONDS, XAI_FILE_TTL_MIN_SECONDS, XAI_PRICING, XAI_TOOL_RATE_MICRO_USD, XaiFileStore, buildXaiClient, classifyXaiError, computeXaiCost, grok45ModelDescriptor, grok46ModelDescriptor, requireApiKey, xaiAdapter, xaiModelDescriptors, xaiPricingSource, xaiPricingVersion, xaiProvider, xaiRegistry };
1878
+ export { Grok45ConfigSchema, Grok46ConfigSchema, Grok47ConfigSchema, XAI_FILES_DEFAULT_BASE_URL, XAI_FILE_MAX_BYTES, XAI_FILE_TTL_MAX_SECONDS, XAI_FILE_TTL_MIN_SECONDS, XAI_PRICING, XAI_TOOL_RATE_MICRO_USD, XaiFileStore, buildXaiClient, classifyXaiError, computeXaiCost, grok45ModelDescriptor, grok46ModelDescriptor, grok47ModelDescriptor, requireApiKey, xaiAdapter, xaiModelDescriptors, xaiPricingSource, xaiPricingVersion, xaiProvider, xaiRegistry };
1548
1879
  //# sourceMappingURL=index.js.map
1549
1880
  //# sourceMappingURL=index.js.map