@gullabs/xai 0.8.0 → 0.16.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.d.cts CHANGED
@@ -35,6 +35,20 @@ type XaiProviderOptions = {
35
35
  tools?: Array<XaiWebSearchTool | XaiXSearchTool>;
36
36
  /** xAI-only; Gemini has no parallel-tool knob. */
37
37
  parallelToolCalls?: boolean;
38
+ /**
39
+ * Responses API `tool_choice` for the server-side search tools; `required`
40
+ * forces at least one search. Requires `tools`, and cannot be combined
41
+ * with the request-level `toolChoice`.
42
+ */
43
+ toolChoice?: 'auto' | 'required' | 'none';
44
+ /**
45
+ * Responses API `max_turns`: the cap on agentic tool-calling turns for the
46
+ * server-side search tools. A turn can run several searches, so this is
47
+ * not a search count. Requires `tools`. As of 2026-10-02 xAI did not
48
+ * enforce it on grok-4.5 / 4.6 / 4.7; assert on
49
+ * `usage.details.web_search_calls` rather than trusting the cap.
50
+ */
51
+ maxTurns?: number;
38
52
  };
39
53
  declare module '@gullabs/core' {
40
54
  interface ProviderOptionsMap {
@@ -76,15 +90,13 @@ interface XaiInputImagePart {
76
90
  image_url: string;
77
91
  }
78
92
  /**
79
- * A file attachment content item within an xAI Responses API input message.
80
- * Prefer `file_id` for private uploads (via {@link XaiFileStore}); `file_url`
81
- * is for publicly reachable documents. Attaching either implicitly enables
82
- * xAI's `attachment_search` agentic tool.
93
+ * A file attachment content item within an xAI Responses API input message:
94
+ * a private upload made through {@link XaiFileStore}. Attaching one implicitly
95
+ * enables xAI's `attachment_search` agentic tool.
83
96
  */
84
97
  interface XaiInputFilePart {
85
98
  type: 'input_file';
86
- file_id?: string;
87
- file_url?: string;
99
+ file_id: string;
88
100
  }
89
101
  /** Union of content-part shapes an input message may carry. */
90
102
  type XaiInputContentPart = XaiInputTextPart | XaiInputImagePart | XaiInputFilePart;
@@ -107,10 +119,15 @@ interface XaiFunctionCallOutputInputItem {
107
119
  output: string;
108
120
  }
109
121
  type XaiRequestInputItem = XaiInputItem | XaiFunctionCallInputItem | XaiFunctionCallOutputInputItem | XaiOutputItem;
110
- /** Full wire history for stateless continuation. */
122
+ /**
123
+ * Full wire history for stateless continuation (`continuation: 'state'`),
124
+ * scoped under the provider key and bound to the requested model string.
125
+ */
111
126
  interface XaiReplayState {
112
- model: string;
113
- input: XaiRequestInputItem[];
127
+ xai: {
128
+ model: string;
129
+ input: XaiRequestInputItem[];
130
+ };
114
131
  }
115
132
  /**
116
133
  * Structured-output text-format request shape.
@@ -119,18 +136,16 @@ interface XaiReplayState {
119
136
  * conventions even though the live fixture's request-echo does not surface
120
137
  * them (only the schema is echoed back).
121
138
  */
122
- type XaiTextFormat = {
139
+ interface XaiTextFormat {
123
140
  type: 'json_schema';
124
141
  name: string;
125
142
  schema: unknown;
126
143
  strict: boolean;
127
- } | {
128
- type: 'text';
129
- };
144
+ }
130
145
  /**
131
146
  * Parameters for `client.responses.create`.
132
147
  * Structurally modeled from live-captured xAI Responses API fixtures
133
- * (see docs/provider-plugins-and-xai-grok-4-5-plan.md §3.1), not from the
148
+ * (see docs/archive/provider-plugins-and-xai-grok-4-5-plan.md §3.1), not from the
134
149
  * `openai` npm package's TS types — xAI's actual endpoint shape differs.
135
150
  */
136
151
  interface XaiResponseCreateParams {
@@ -164,6 +179,7 @@ interface XaiResponseCreateParams {
164
179
  type: 'function';
165
180
  name: string;
166
181
  };
182
+ max_turns?: number;
167
183
  parallel_tool_calls?: boolean;
168
184
  }
169
185
  /** A single summary-text segment of a `type: 'reasoning'` output item. */
@@ -185,13 +201,24 @@ interface XaiOutputTextPart {
185
201
  logprobs?: unknown[];
186
202
  annotations?: unknown[];
187
203
  }
188
- /** A `type: 'message'` item in `output`. */
204
+ /**
205
+ * A refusal content segment of a `type: 'message'` output item (the OpenAI
206
+ * Responses grammar xAI mirrors; not yet captured from xAI).
207
+ */
208
+ interface XaiRefusalPart {
209
+ type: 'refusal';
210
+ refusal: string;
211
+ }
212
+ /**
213
+ * A `type: 'message'` item in `output`. A part of any other type may arrive at
214
+ * runtime; the adapter ignores it with a warning.
215
+ */
189
216
  interface XaiMessageOutputItem {
190
217
  type: 'message';
191
218
  id?: string;
192
219
  role?: string;
193
220
  status?: string;
194
- content: XaiOutputTextPart[];
221
+ content: Array<XaiOutputTextPart | XaiRefusalPart>;
195
222
  }
196
223
  /** Server-tool or function-call output items we do not collapse as messages. */
197
224
  interface XaiOtherOutputItem {
@@ -228,13 +255,22 @@ interface XaiResponseShape {
228
255
  id: string;
229
256
  model: string;
230
257
  /**
231
- * Real field: `status`. Observed values: "completed", "incomplete" — kept
232
- * as a plain `string` since xAI may add further status values over time.
258
+ * Real field: `status`. Observed values: "completed", "incomplete"; the API
259
+ * also documents "failed" and "cancelled" (never captured). Kept as a plain
260
+ * `string` since xAI may add further status values over time.
233
261
  */
234
262
  status: string;
235
263
  incomplete_details?: {
236
264
  reason?: string;
237
265
  } | null;
266
+ /**
267
+ * Error object the Responses API puts on a response that failed after the
268
+ * HTTP 200 (documented shape, never captured).
269
+ */
270
+ error?: {
271
+ code?: string;
272
+ message?: string;
273
+ } | null;
238
274
  output: XaiOutputItem[];
239
275
  usage: XaiUsageShape;
240
276
  reasoning?: {
@@ -273,11 +309,101 @@ interface XaiResponseShape {
273
309
  */
274
310
  interface XaiClientLike {
275
311
  responses: {
276
- create(params: XaiResponseCreateParams, options?: {
277
- signal?: AbortSignal;
278
- }): Promise<XaiResponseShape>;
312
+ create(params: XaiResponseCreateParams, options?: XaiRequestOptions): Promise<XaiResponseShape>;
279
313
  };
280
314
  }
315
+ /**
316
+ * What the HTTP response of a successful `responses.create` says outside its
317
+ * body: xAI's request id (quote it in a support ticket) and the remaining-quota
318
+ * headers.
319
+ */
320
+ interface XaiResponseMeta {
321
+ /** The `x-request-id` response header. Absent when xAI sent none. */
322
+ requestId?: string;
323
+ /**
324
+ * Response headers that state remaining quota (`x-ratelimit-remaining-*`, the names xAI sent in
325
+ * every captured response), lower-cased name to the verbatim value. Absent when
326
+ * the response carried none.
327
+ */
328
+ rateLimitRemaining?: Record<string, string>;
329
+ /**
330
+ * What reconciling the streamed events with the final response object did
331
+ * (ADR-040): items the final object lacked and the stream completed, fields
332
+ * taken from the stream, fields that differed. Absent when they agreed. The
333
+ * adapter reports each as a warning.
334
+ */
335
+ streamNotes?: string[];
336
+ /**
337
+ * True when output events arrived before the response's terminal event. A
338
+ * `response.failed` after output began is not retried (the run already spent
339
+ * tokens). Set by the real client; absent from a fake one.
340
+ */
341
+ streamProgressed?: boolean;
342
+ }
343
+ /** Per-request options the adapter passes to `responses.create`. */
344
+ interface XaiRequestOptions {
345
+ signal?: AbortSignal;
346
+ /**
347
+ * The request's whole-call deadline in milliseconds. The real client sends
348
+ * the request as a stream (ADR-040) and applies it twice: as the SDK's
349
+ * `timeout`, which for a stream covers only the wait for response headers,
350
+ * and as its own timer over the remaining stream, so the deadline bounds the
351
+ * whole call. It does not move Node's header and body timers; see
352
+ * {@link XaiTransport}.
353
+ */
354
+ timeout?: number;
355
+ /**
356
+ * Called with the response's {@link XaiResponseMeta} once the response
357
+ * is complete, before `create` resolves. Only the real client calls it; a
358
+ * fake client may ignore it.
359
+ */
360
+ onResponse?: (meta: XaiResponseMeta) => void;
361
+ }
362
+ /**
363
+ * Host-supplied HTTP transport for every `responses.create` call.
364
+ *
365
+ * Node's `fetch` enforces its own 300 s header and body timers, independent of
366
+ * the SDK `timeout`. A call whose response headers take longer than that (a
367
+ * tool-using call that streams nothing for minutes) is killed unless the host
368
+ * passes a `fetch` whose dispatcher raises those timers (for example undici's
369
+ * `fetch` with `new Agent({ headersTimeout, bodyTimeout })` in
370
+ * `fetchOptions.dispatcher`). See ADR-032 and the package README.
371
+ *
372
+ * `fetch` must return the request's own `text/event-stream` response: the call
373
+ * always streams (ADR-040), and a `fetch` that buffers the answer into a JSON
374
+ * body (a record/replay or caching wrapper) fails every call with a non-retryable
375
+ * error naming the cause.
376
+ */
377
+ interface XaiTransport {
378
+ fetch: typeof fetch;
379
+ /**
380
+ * Extra `fetch` init (for example `{ dispatcher }`). `headers`, `signal`,
381
+ * `body` and `method` belong to the request and are rejected.
382
+ */
383
+ fetchOptions?: Omit<RequestInit, 'headers' | 'signal' | 'body' | 'method'>;
384
+ /**
385
+ * Ends a stream that sends no bytes at all (heartbeat comments included) for
386
+ * this many milliseconds, as a non-retryable `timeout` with
387
+ * `reason: 'transport_timeout'`. Off by default. The request deadline bounds
388
+ * the whole call; this bounds a half-open connection (a NAT drop with no
389
+ * reset) that the deadline would hold for up to an hour. Integer, at least 1.
390
+ * Set it above the longest quiet gap you expect: live reasoning runs showed a
391
+ * longest gap of 15 s.
392
+ */
393
+ idleTimeoutMs?: number;
394
+ }
395
+ /**
396
+ * SDK deadline for a request with no `timeoutMs`: one hour. xAI reasoning and
397
+ * agentic calls can run for many minutes; the SDK default (10 minutes) would
398
+ * cut them off.
399
+ */
400
+ declare const XAI_DEFAULT_TIMEOUT_MS = 3600000;
401
+ /**
402
+ * Added to `timeoutMs` for the SDK deadline, so the engine's own deadline
403
+ * (armed at exactly `timeoutMs`) always fires first and the caller sees the
404
+ * engine's clean timeout rather than a raw SDK error.
405
+ */
406
+ declare const XAI_TIMEOUT_BUFFER_MS = 5000;
281
407
  /**
282
408
  * Build a real `openai`-SDK-backed client from AuthMaterial, pointed at
283
409
  * xAI's Responses API endpoint.
@@ -285,8 +411,10 @@ interface XaiClientLike {
285
411
  * Only API-key authentication is supported.
286
412
  *
287
413
  * @param auth - API key credentials ({ apiKey }).
414
+ * @param transport - Optional host-supplied `fetch` and `fetchOptions` passed to
415
+ * the SDK client unchanged.
288
416
  */
289
- declare function buildXaiClient(auth: AuthMaterial): Promise<XaiClientLike>;
417
+ declare function buildXaiClient(auth: AuthMaterial, transport?: XaiTransport): Promise<XaiClientLike>;
290
418
 
291
419
  /**
292
420
  * xaiAdapter — @gullabs/xai xAI Grok provider adapter.
@@ -297,6 +425,17 @@ declare function buildXaiClient(auth: AuthMaterial): Promise<XaiClientLike>;
297
425
  * @module
298
426
  */
299
427
 
428
+ /**
429
+ * What the adapter knows about the SDK deadline of the call that failed: the
430
+ * `timeout` it handed the SDK and how long the call ran. Without it an
431
+ * `APIConnectionTimeoutError` is never taken for the SDK's own deadline.
432
+ */
433
+ interface XaiSdkDeadline {
434
+ /** The per-request `timeout` the adapter passed to the SDK, in ms. */
435
+ timeoutMs: number;
436
+ /** Wall-clock ms between the SDK call starting and the error. */
437
+ elapsedMs: number;
438
+ }
300
439
  /**
301
440
  * Classify a raw error thrown from the xAI Responses API call into a typed
302
441
  * {@link LlmError}.
@@ -314,12 +453,31 @@ declare function buildXaiClient(auth: AuthMaterial): Promise<XaiClientLike>;
314
453
  * `"Content violates usage guidelines"` (fixture 15; `SAFETY_CHECK_TYPE_*`
315
454
  * suffixes vary) → `content_filter`. A bare 403 without that body stays
316
455
  * the core default, `invalid_auth`.
317
- * 4. `kind: 'unknown'` with a known transport-failure signature (see
318
- * {@link isXaiTransportError}) → `server`, retryable. A connection that
319
- * never reached xAI is not the caller's fault.
320
- * 5. Else rebuild the core classification tagged `provider: 'xai'`.
456
+ * 3b. HTTP 429 or 403 whose structured body is the credits-exhausted /
457
+ * spending-limit sentence (doc-derived, see `XAI_CREDITS_EXHAUSTED_BODY`) →
458
+ * `rate_limited`, `retryable: false`, `reason: 'credits_exhausted'`.
459
+ * 4. A transport deadline (undici header or body timer, or the SDK's own
460
+ * deadline, which needs the `deadline` argument to be recognised; see
461
+ * {@link xaiTransportTimeoutKind}) → `timeout`,
462
+ * `retryable: false`, `reason: 'transport_timeout'`.
463
+ * 5. A transport failure (core's `classifyError` already makes it a retryable
464
+ * `server` error; an `openai` SDK connection error that core left `unknown`
465
+ * is made one here). A connection that never reached xAI is not the
466
+ * caller's fault.
467
+ * 6. Else rebuild the core classification tagged `provider: 'xai'`.
468
+ *
469
+ * A streamed call that failed mid-stream arrives as an `XaiStreamError`; see
470
+ * {@link classifyStreamError} (`estimatedInputTokens` is the request's input
471
+ * estimate, used only for a failure after output began; `requestTimeoutMs` is
472
+ * the timeout the caller configured, quoted by the client-deadline message).
473
+ */
474
+ declare function classifyXaiError(rawErr: unknown, deadline?: XaiSdkDeadline, estimatedInputTokens?: number, requestTimeoutMs?: number): LlmError;
475
+ /**
476
+ * Default deadline of one `countTokens` call (`POST /v1/tokenize-text`), in
477
+ * milliseconds: 60 s. The call is a small text-only request; the engine's
478
+ * `countTokens` `timeoutMs` and the call's own signal still apply first.
321
479
  */
322
- declare function classifyXaiError(rawErr: unknown): LlmError;
480
+ declare const XAI_COUNT_TOKENS_TIMEOUT_MS = 60000;
323
481
  interface XaiAdapterOptions {
324
482
  /**
325
483
  * Inject a pre-built client (real or fake).
@@ -329,24 +487,31 @@ interface XaiAdapterOptions {
329
487
  */
330
488
  client?: XaiClientLike;
331
489
  /**
332
- * @internal Testing-only.
333
- *
334
- * Override the default `buildXaiClient` factory. Allows unit tests to
335
- * simulate construction failures without importing the real `openai` SDK.
336
- * Never set this in production code. Mirrors `GeminiAdapterOptions._clientFactory`.
490
+ * HTTP transport (`fetch`, `fetchOptions`, `idleTimeoutMs`) for the SDK client
491
+ * the adapter builds: a proxy, mTLS or egress policy, or an undici `fetch` with
492
+ * an `Agent({ headersTimeout, bodyTimeout })` dispatcher. Calls stream
493
+ * internally (ADR-040), so a reasoning call no longer needs it to run past
494
+ * 300 s; a tool-using call expected to run past 300 s without any streamed
495
+ * event still does (untested, see the package README). `idleTimeoutMs` ends a
496
+ * stream that sends no bytes for that long (off by default). `fetch` must return
497
+ * the request's `text/event-stream` response unchanged. `fetch` and
498
+ * `fetchOptions` also carry `countTokens` (`POST /v1/tokenize-text`). Validated
499
+ * and copied when the adapter is created. Cannot be combined with `client` (an injected client owns its own
500
+ * transport).
337
501
  */
338
- _clientFactory?: (auth: AuthMaterial) => XaiClientLike | Promise<XaiClientLike>;
502
+ transport?: XaiTransport;
339
503
  /**
340
- * @internal Testing-only.
341
- *
342
- * Override `fetch` for `POST /v1/tokenize-text` (not on the openai SDK).
504
+ * Deadline of one `countTokens` call in milliseconds (an integer from 1 to
505
+ * {@link XAI_MAX_TIMEOUT_MS}); default {@link XAI_COUNT_TOKENS_TIMEOUT_MS}. A
506
+ * call still open then fails with a retryable `timeout` error.
343
507
  */
344
- _fetch?: typeof fetch;
508
+ countTokensTimeoutMs?: number;
345
509
  }
346
510
  /**
347
511
  * Create an xAI Grok provider adapter (Responses API).
348
512
  *
349
513
  * @param opts.client - Optional pre-built client (e.g. for testing).
514
+ * @param opts.transport - Optional `fetch` + `fetchOptions` for the built client.
350
515
  */
351
516
  declare function xaiAdapter(opts?: XaiAdapterOptions): ProviderAdapter;
352
517
 
@@ -371,6 +536,12 @@ declare const XAI_FILE_TTL_MAX_SECONDS = 2592000;
371
536
  declare const XAI_FILE_MAX_BYTES: number;
372
537
  /** Default Files API base (includes `/v1`). */
373
538
  declare const XAI_FILES_DEFAULT_BASE_URL = "https://api.x.ai/v1";
539
+ /**
540
+ * Default deadline of one Files API call (headers and body), in milliseconds:
541
+ * 60 s. A store with an `AbortSignal` of its own still honours it; a very large
542
+ * upload on a slow link needs a larger `timeoutMs` in {@link XaiFileStoreOptions}.
543
+ */
544
+ declare const XAI_FILES_DEFAULT_TIMEOUT_MS = 60000;
374
545
  /** A handle to a file stored in the xAI Files API. */
375
546
  interface XaiFileHandle {
376
547
  /** File id, e.g. `"file_a128090d-…"`. Use as `FileRefPart.fileId`. */
@@ -431,6 +602,12 @@ interface XaiFileStoreOptions {
431
602
  baseUrl?: string;
432
603
  /** Injectable fetch for tests. Default: global `fetch`. */
433
604
  fetch?: typeof fetch;
605
+ /**
606
+ * Deadline of each call (response headers and body) in milliseconds. A call
607
+ * that is still open then fails with a retryable `timeout` error. An integer
608
+ * from 1 to {@link XAI_MAX_TIMEOUT_MS}; default {@link XAI_FILES_DEFAULT_TIMEOUT_MS}.
609
+ */
610
+ timeoutMs?: number;
434
611
  /**
435
612
  * Delete failures that are NOT already-gone (404).
436
613
  * Default: `logger.error` or `console.error` with a redacted message.
@@ -450,6 +627,7 @@ declare class XaiFileStore {
450
627
  private readonly apiKey;
451
628
  private readonly baseUrl;
452
629
  private readonly fetchImpl;
630
+ private readonly timeoutMs;
453
631
  private readonly onDeleteError;
454
632
  private readonly logger;
455
633
  constructor(opts: XaiFileStoreOptions);
@@ -457,6 +635,12 @@ declare class XaiFileStore {
457
635
  private filesUrl;
458
636
  /** Build RequestInit without writing `signal: undefined` (exactOptionalPropertyTypes). */
459
637
  private requestInit;
638
+ /**
639
+ * Runs one call under the store's deadline: `run` gets a signal that aborts
640
+ * when the caller's does or when `timeoutMs` passes (headers and body read
641
+ * both count), and the timer is cleared however the call ends.
642
+ */
643
+ private bounded;
460
644
  /**
461
645
  * Upload bytes to xAI Files. Returns immediately with metadata (no poll).
462
646
  *
@@ -621,6 +805,19 @@ declare const Grok45ConfigSchema: z.ZodObject<{
621
805
  type: z.ZodLiteral<"web_search">;
622
806
  }, z.core.$strict>]>], null>]>>;
623
807
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
808
+ toolChoice: z.ZodOptional<z.ZodEnum<{
809
+ auto: "auto";
810
+ required: "required";
811
+ none: "none";
812
+ }>>;
813
+ maxTurns: z.ZodOptional<z.ZodNumber>;
814
+ searchBudget: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
815
+ maxWebSearchCalls: z.ZodNumber;
816
+ maxXItems: z.ZodOptional<z.ZodNumber>;
817
+ }, z.core.$strict>, z.ZodObject<{
818
+ maxWebSearchCalls: z.ZodOptional<z.ZodNumber>;
819
+ maxXItems: z.ZodNumber;
820
+ }, z.core.$strict>]>>;
624
821
  }, z.core.$strict>>;
625
822
  }, z.core.$strict>>;
626
823
  }, z.core.$strict>;
@@ -758,6 +955,19 @@ declare const Grok46ConfigSchema: z.ZodObject<{
758
955
  type: z.ZodLiteral<"web_search">;
759
956
  }, z.core.$strict>]>], null>]>>;
760
957
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
958
+ toolChoice: z.ZodOptional<z.ZodEnum<{
959
+ auto: "auto";
960
+ required: "required";
961
+ none: "none";
962
+ }>>;
963
+ maxTurns: z.ZodOptional<z.ZodNumber>;
964
+ searchBudget: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
965
+ maxWebSearchCalls: z.ZodNumber;
966
+ maxXItems: z.ZodOptional<z.ZodNumber>;
967
+ }, z.core.$strict>, z.ZodObject<{
968
+ maxWebSearchCalls: z.ZodOptional<z.ZodNumber>;
969
+ maxXItems: z.ZodNumber;
970
+ }, z.core.$strict>]>>;
761
971
  }, z.core.$strict>>;
762
972
  }, z.core.$strict>>;
763
973
  }, z.core.$strict>;
@@ -768,8 +978,8 @@ declare const Grok46ConfigSchema: z.ZodObject<{
768
978
  * Same Responses-API surface as grok-4.6: `reasoning.effort` of
769
979
  * `'low' | 'medium' | 'high' | 'xhigh'` and `serviceTier: 'priority'`.
770
980
  * Shaped from the grok-4.6 contract. The 2026-09-25 priority success and
771
- * effort-none rejection and P-X3 encrypted-reasoning multi-turn replay are
772
- * fixture-backed. `'none'` stays rejected.
981
+ * effort-none rejection, and the encrypted-reasoning multi-turn replay captured
982
+ * live on 2026-09-26, are fixture-backed. `'none'` stays rejected.
773
983
  * Unknown tiers (`flex`, `standard`, `batch`) are rejected.
774
984
  *
775
985
  * @module
@@ -896,6 +1106,19 @@ declare const Grok47ConfigSchema: z.ZodObject<{
896
1106
  type: z.ZodLiteral<"web_search">;
897
1107
  }, z.core.$strict>]>], null>]>>;
898
1108
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
1109
+ toolChoice: z.ZodOptional<z.ZodEnum<{
1110
+ auto: "auto";
1111
+ required: "required";
1112
+ none: "none";
1113
+ }>>;
1114
+ maxTurns: z.ZodOptional<z.ZodNumber>;
1115
+ searchBudget: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
1116
+ maxWebSearchCalls: z.ZodNumber;
1117
+ maxXItems: z.ZodOptional<z.ZodNumber>;
1118
+ }, z.core.$strict>, z.ZodObject<{
1119
+ maxWebSearchCalls: z.ZodOptional<z.ZodNumber>;
1120
+ maxXItems: z.ZodNumber;
1121
+ }, z.core.$strict>]>>;
899
1122
  }, z.core.$strict>>;
900
1123
  }, z.core.$strict>>;
901
1124
  }, z.core.$strict>;
@@ -970,7 +1193,7 @@ declare const xaiPricingVersion: "xai-2026-09-25";
970
1193
  * - `x_users_fetched`: $10 / 1,000 profiles (per item, since 2026-09-21).
971
1194
  *
972
1195
  * The per-call `x_search_calls` rate is gone. Attachment search stays
973
- * unpriced until a live probe pins the counter name (P-X2); a file-ref call
1196
+ * unpriced until a live probe pins the counter name (blocked, see BACKLOG.md); a file-ref call
974
1197
  * is estimated, not billed at an invented counter.
975
1198
  */
976
1199
  declare const XAI_TOOL_RATE_MICRO_USD: {
@@ -999,9 +1222,11 @@ interface XaiModelRates {
999
1222
  /**
1000
1223
  * Multiplier for Responses `service_tier: "priority"`. Absent = this
1001
1224
  * model does not admit priority (unpriced). Uncached standard-list 2×
1002
- * is confirmed by fixture `12-grok-4-6-xhigh-priority.json` ticks;
1003
- * cached and `gt200k` legs follow the official 2×-after-cache-discount
1004
- * docs rule (that fixture has cached=0 and input < 200k).
1225
+ * is confirmed by fixture `12-grok-4-6-xhigh-priority.json` ticks; the
1226
+ * cached leg (2× its standard rate) by fixture `35-priority-warm-cache.json`
1227
+ * (warm-cache priority calls on all three models). The `gt200k` leg follows
1228
+ * the official 2×-after-cache-discount docs rule: no priority capture reaches
1229
+ * 200k input tokens.
1005
1230
  */
1006
1231
  priorityFactor?: number;
1007
1232
  }
@@ -1032,12 +1257,19 @@ declare const XAI_PRICING: Readonly<Record<string, XaiModelRates>>;
1032
1257
  * nearest integer micro-USD.
1033
1258
  * 6. `microUsd` is the sum of the four components — guarantees
1034
1259
  * `details.input + details.cached + details.output + details.tools === microUsd`.
1035
- * 7. Tool lanes: `web_search_calls` per call; x_search is
1260
+ * 7. `cost_in_usd_ticks` (1 tick = 1e-10 USD) is converted to µUSD with the same
1261
+ * rounding and reported as `Cost.providerReported`; `microUsd` stays this
1262
+ * snapshot's price. The engine warns when the two totals drift.
1263
+ * 8. A non-zero server-tool counter that xAI bills per use (or that is unknown)
1264
+ * and this snapshot has no rate for ({@link unpricedXaiToolCounters}, driven
1265
+ * by {@link XAI_SERVER_TOOL_COUNTERS}) makes the call `'estimated'`. Token-only
1266
+ * tools (`mcp_calls`) do not.
1267
+ * 9. Tool lanes: `web_search_calls` per call; x_search is
1036
1268
  * `x_posts_fetched` × $5/1k + `x_users_fetched` × $10/1k. A missing
1037
1269
  * item counter leaves the call unpriced; the provider's billed ticks remain
1038
- * in `usage.details` for reconciliation outside this rate snapshot.
1270
+ * in `usage.details` and, as `Cost.providerReported`, on the returned cost.
1039
1271
  * File-ref still sets `attachment_search_unpinned` and the call is
1040
- * estimated — the counter name is not pinned (P-X2).
1272
+ * estimated — the counter name is not pinned.
1041
1273
  */
1042
1274
  declare function computeXaiCost(model: string, usage: Usage, tier?: string): Cost;
1043
1275
  /**
@@ -1057,8 +1289,8 @@ declare function xaiPricingSource(): PricingSource;
1057
1289
  /**
1058
1290
  * `xaiProvider` — {@link ProviderPlugin} factory for @gullabs/xai.
1059
1291
  *
1060
- * Bundles the xAI Grok adapter, the `grok-4.5` / `grok-4.6` model
1061
- * descriptors, and the xai pricing source into a single plugin for
1292
+ * Bundles the xAI Grok adapter, the `grok-4.5` / `grok-4.6` / `grok-4.7`
1293
+ * model descriptors, and the xai pricing source into a single plugin for
1062
1294
  * {@link composeProviders}.
1063
1295
  *
1064
1296
  * @module
@@ -1068,8 +1300,8 @@ declare function xaiPricingSource(): PricingSource;
1068
1300
  * Create a {@link ProviderPlugin} for the xAI Grok provider.
1069
1301
  *
1070
1302
  * @param opts - Forwarded to {@link xaiAdapter}.
1071
- * @returns A plugin bundling the xAI adapter, the `grok-4.5` / `grok-4.6`
1072
- * model descriptors, and the built-in xai pricing source.
1303
+ * @returns A plugin bundling the xAI adapter, the `grok-4.5` / `grok-4.6` /
1304
+ * `grok-4.7` model descriptors, and the built-in xai pricing source.
1073
1305
  *
1074
1306
  * @example
1075
1307
  * ```ts
@@ -1083,4 +1315,4 @@ declare function xaiPricingSource(): PricingSource;
1083
1315
  */
1084
1316
  declare function xaiProvider(opts?: XaiAdapterOptions): ProviderPlugin;
1085
1317
 
1086
- export { type FileDeleteOptions, 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, type XaiAdapterOptions, type XaiClientLike, type XaiFileHandle, type XaiFileListOptions, type XaiFileListResult, XaiFileStore, type XaiFileStoreOptions, type XaiFileUploadInput, type XaiInputContentPart, type XaiInputFilePart, type XaiInputImagePart, type XaiInputItem, type XaiInputTextPart, type XaiMessageOutputItem, type XaiModelRates, type XaiOutputItem, type XaiOutputTextPart, type XaiProviderOptions, type XaiReasoningOutputItem, type XaiReasoningSummaryPart, type XaiReplayState, type XaiRequestInputItem, type XaiResponseCreateParams, type XaiResponseShape, type XaiTextFormat, type XaiUsageShape, type XaiWebSearchTool, type XaiXSearchTool, buildXaiClient, classifyXaiError, computeXaiCost, grok45ModelDescriptor, grok46ModelDescriptor, grok47ModelDescriptor, requireApiKey, xaiAdapter, xaiModelDescriptors, xaiPricingSource, xaiPricingVersion, xaiProvider, xaiRegistry };
1318
+ export { type FileDeleteOptions, Grok45ConfigSchema, Grok46ConfigSchema, Grok47ConfigSchema, XAI_COUNT_TOKENS_TIMEOUT_MS, XAI_DEFAULT_TIMEOUT_MS, XAI_FILES_DEFAULT_BASE_URL, XAI_FILES_DEFAULT_TIMEOUT_MS, XAI_FILE_MAX_BYTES, XAI_FILE_TTL_MAX_SECONDS, XAI_FILE_TTL_MIN_SECONDS, XAI_PRICING, XAI_TIMEOUT_BUFFER_MS, XAI_TOOL_RATE_MICRO_USD, type XaiAdapterOptions, type XaiClientLike, type XaiFileHandle, type XaiFileListOptions, type XaiFileListResult, XaiFileStore, type XaiFileStoreOptions, type XaiFileUploadInput, type XaiInputContentPart, type XaiInputFilePart, type XaiInputImagePart, type XaiInputItem, type XaiInputTextPart, type XaiMessageOutputItem, type XaiModelRates, type XaiOutputItem, type XaiOutputTextPart, type XaiProviderOptions, type XaiReasoningOutputItem, type XaiReasoningSummaryPart, type XaiRefusalPart, type XaiReplayState, type XaiRequestInputItem, type XaiRequestOptions, type XaiResponseCreateParams, type XaiResponseMeta, type XaiResponseShape, type XaiSdkDeadline, type XaiTextFormat, type XaiTransport, type XaiUsageShape, type XaiWebSearchTool, type XaiXSearchTool, buildXaiClient, classifyXaiError, computeXaiCost, grok45ModelDescriptor, grok46ModelDescriptor, grok47ModelDescriptor, requireApiKey, xaiAdapter, xaiModelDescriptors, xaiPricingSource, xaiPricingVersion, xaiProvider, xaiRegistry };