@warlock.js/ai-xai 5.30.0 → 5.31.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/CHANGELOG.md +16 -0
- package/README.md +12 -12
- package/esm/config.type.d.mts +10 -0
- package/esm/config.type.d.mts.map +1 -1
- package/llms-full.txt +53 -24
- package/llms.txt +1 -1
- package/package.json +4 -4
- package/skills/setup-xai/SKILL.md +53 -24
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to `@warlock.js/ai-xai` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.31.0 - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- An adapter contract test verifies that aborting `signal` rejects `complete()` and `stream()` on the model and cancels the HTTP request.
|
|
12
|
+
- `XaiModelConfig.promptCacheKey` is sent as `prompt_cache_key` (xAI routes it to `x-grok-conv-id`), so requests sharing a prefix reuse the same cache.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Chat calls inherit `providerOptions.openai.body` from the OpenAI adapter, including its protected fields and one-level plain-object merge. Use only this provider's accepted fields when sharing fallback options. Native `countTokens` remains absent; `sdk.count(text)` is an offline estimate.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- The provider-body and token-estimate guidance renders as prose instead of being swallowed by a stray code fence.
|
|
21
|
+
|
|
7
22
|
## 5.30.0 - 2026-10-16
|
|
8
23
|
|
|
9
24
|
### Changed
|
|
@@ -81,6 +96,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
81
96
|
### Changed
|
|
82
97
|
|
|
83
98
|
- Lockstep release maintenance and dependency refresh.
|
|
99
|
+
|
|
84
100
|
## 5.20.0 - 2026-09-24
|
|
85
101
|
|
|
86
102
|
### Changed
|
package/README.md
CHANGED
|
@@ -51,22 +51,22 @@ XaiModelConfig {
|
|
|
51
51
|
|
|
52
52
|
Capabilities are inferred from the Grok model **name** (via `inferVisionCapability` / `inferReasoningCapability`, matched as a prefix so dated / `-latest` / `-fast` / `-beta` variants are covered) and injected as explicit flags before delegating — an explicit value always wins.
|
|
53
53
|
|
|
54
|
-
| Model | `vision` | `reasoning`
|
|
55
|
-
| --------------- | -------- |
|
|
56
|
-
| `grok-4` | true | true (reasoning-first)
|
|
57
|
-
| `grok-3` | false | false
|
|
54
|
+
| Model | `vision` | `reasoning` |
|
|
55
|
+
| --------------- | -------- | -------------------------- |
|
|
56
|
+
| `grok-4` | true | true (reasoning-first) |
|
|
57
|
+
| `grok-3` | false | false |
|
|
58
58
|
| `grok-3-mini` | false | true (the "think" variant) |
|
|
59
|
-
| `grok-2-vision` | true | false
|
|
60
|
-
| `grok-2` | false | false
|
|
59
|
+
| `grok-2-vision` | true | false |
|
|
60
|
+
| `grok-2` | false | false |
|
|
61
61
|
|
|
62
62
|
- `structuredOutput` / `promptCaching` and the image / PDF / audio wire mapping all come from the wrapped OpenAI adapter unchanged.
|
|
63
63
|
- `XAI_CHAT_MODELS`, `XAI_VISION_MODEL_PREFIXES`, and `XAI_REASONING_MODEL_PREFIXES` are exported for menus, validation, and docs.
|
|
64
64
|
|
|
65
65
|
```ts
|
|
66
|
-
xai.model({ name: "grok-4" });
|
|
67
|
-
xai.model({ name: "grok-3-mini" });
|
|
68
|
-
xai.model({ name: "grok-2-vision" });
|
|
69
|
-
xai.model({ name: "grok-3", vision: true });
|
|
66
|
+
xai.model({ name: "grok-4" }); // vision + reasoning auto-true
|
|
67
|
+
xai.model({ name: "grok-3-mini" }); // reasoning auto-true, vision false
|
|
68
|
+
xai.model({ name: "grok-2-vision" }); // vision auto-true
|
|
69
|
+
xai.model({ name: "grok-3", vision: true }); // explicit capability override
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
> Model availability changes over time — pass any current Grok id through `.model({ name })`; the prefix inference covers dated / `-latest` variants. Don't assume a model exists; check xAI's docs.
|
|
@@ -74,8 +74,8 @@ xai.model({ name: "grok-3", vision: true }); // explicit capability override
|
|
|
74
74
|
## Reasoning effort
|
|
75
75
|
|
|
76
76
|
```ts
|
|
77
|
-
const model = xai.model({ name: "grok-4" });
|
|
78
|
-
await model.complete(messages, { reasoning: { effort: "high" } });
|
|
77
|
+
const model = xai.model({ name: "grok-4" }); // reasoning auto-true
|
|
78
|
+
await model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
`reasoning.effort` (`"low" | "medium" | "high"`) maps verbatim to the OpenAI-compatible `reasoning_effort` param and is dropped for a non-reasoning model (e.g. `grok-3`).
|
package/esm/config.type.d.mts
CHANGED
|
@@ -77,6 +77,16 @@ type XaiModelConfig = ModelConfig & {
|
|
|
77
77
|
* `json_schema` — the agent then re-injects a soft schema hint.
|
|
78
78
|
*/
|
|
79
79
|
structuredOutput?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Prompt-cache routing key, sent as `prompt_cache_key` so requests that
|
|
82
|
+
* share a prefix land on the same xAI cache. Use a stable value per
|
|
83
|
+
* conversation or tenant. Sent only while the SDK keeps its default
|
|
84
|
+
* provider label.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* model({ name: "grok-4.3", promptCacheKey: `conversation:${conversationId}` });
|
|
88
|
+
*/
|
|
89
|
+
promptCacheKey?: string;
|
|
80
90
|
};
|
|
81
91
|
/**
|
|
82
92
|
* Per-embedder configuration for `XaiSDK.embedder()`. Mirrors the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.type.d.mts","names":[],"sources":["../../../../../../../packages/ai-xai/src/config.type.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"config.type.d.mts","names":[],"sources":["../../../../../../../packages/ai-xai/src/config.type.ts"],"mappings":";;;;;;AAmCA;;;;AAA0C;AAkB1C;;;;;;;;;;AAmCgB;AAehB;;;;AAA8C;AAa9C;;;;AAA6C;;;;;KAjFjC,YAAA,GAAe,eAAe;;;;;;;;;;;;;;;;;KAkB9B,cAAA,GAAiB,WAAW;;;;;;;;EAQtC,MAAA;;;;;;;;;EASA,SAAA;;;;;;;;EAQA,gBAAA;;;;;;;;;;EAUA,cAAA;AAAA;;;;;;;;;;;;;KAeU,iBAAA,GAAoB,cAAc;;;;;;;;;;;;KAalC,cAAA,GAAiB,gBAAgB"}
|
package/llms-full.txt
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
name: setup-xai
|
|
11
|
-
description: 'Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI''s own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.'
|
|
11
|
+
description: 'Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI''s own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, `promptCacheKey`, `prompt_cache_key`, xai pricing, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.'
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# `@warlock.js/ai-xai`
|
|
@@ -32,11 +32,11 @@ const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });
|
|
|
32
32
|
## Producing a model
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
|
-
xai.model({ name: "grok-4" })
|
|
36
|
-
xai.model({ name: "grok-3-mini" })
|
|
37
|
-
xai.model({ name: "grok-2-vision" })
|
|
38
|
-
xai.model({ name: "grok-4", temperature: 0.2 })
|
|
39
|
-
xai.model({ name: "grok-3", vision: true })
|
|
35
|
+
xai.model({ name: "grok-4" }); // vision + reasoning auto-true
|
|
36
|
+
xai.model({ name: "grok-3-mini" }); // reasoning auto-true, vision false
|
|
37
|
+
xai.model({ name: "grok-2-vision" }); // vision auto-true
|
|
38
|
+
xai.model({ name: "grok-4", temperature: 0.2 }); // sampling controls
|
|
39
|
+
xai.model({ name: "grok-3", vision: true }); // explicit capability override
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Returns a `ModelContract` you pass straight into `ai.agent({ model })`.
|
|
@@ -45,13 +45,13 @@ Returns a `ModelContract` you pass straight into `ai.agent({ model })`.
|
|
|
45
45
|
|
|
46
46
|
This adapter ships xAI's OWN name lists (Grok ids don't match OpenAI's `gpt-*` / `o*` prefixes). Capabilities are injected per model before delegating; an explicit value always wins over inference.
|
|
47
47
|
|
|
48
|
-
| Model
|
|
49
|
-
|
|
|
50
|
-
| `grok-4`
|
|
51
|
-
| `grok-3`
|
|
52
|
-
| `grok-3-mini`
|
|
53
|
-
| `grok-2-vision` | true
|
|
54
|
-
| `grok-2`
|
|
48
|
+
| Model | `vision` | `reasoning` |
|
|
49
|
+
| --------------- | -------- | -------------------------- |
|
|
50
|
+
| `grok-4` | true | true (reasoning-first) |
|
|
51
|
+
| `grok-3` | false | false |
|
|
52
|
+
| `grok-3-mini` | false | true (the "think" variant) |
|
|
53
|
+
| `grok-2-vision` | true | false |
|
|
54
|
+
| `grok-2` | false | false |
|
|
55
55
|
|
|
56
56
|
- `vision` — inferred `true` for the `grok-4` and `grok-2-vision` prefixes; `false` otherwise.
|
|
57
57
|
- `reasoning` — inferred `true` for `grok-4` and `grok-3-mini`; drives whether `reasoning.effort` is forwarded as `reasoning_effort` on the wire.
|
|
@@ -64,8 +64,8 @@ This adapter ships xAI's OWN name lists (Grok ids don't match OpenAI's `gpt-*` /
|
|
|
64
64
|
## Reasoning (grok-4 / grok-3-mini)
|
|
65
65
|
|
|
66
66
|
```ts
|
|
67
|
-
const model = xai.model({ name: "grok-4" });
|
|
68
|
-
await model.complete(messages, { reasoning: { effort: "high" } });
|
|
67
|
+
const model = xai.model({ name: "grok-4" }); // reasoning auto-true
|
|
68
|
+
await model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
`reasoning.effort` (`"low" | "medium" | "high"`) maps verbatim to the OpenAI-compatible `reasoning_effort` param. When `capabilities.reasoning` is `false` (e.g. `grok-3`), the option is dropped — the adapter never forwards it. Pin `reasoning: true` to force it for a custom/gateway id.
|
|
@@ -92,26 +92,42 @@ xAI does **not** currently expose a public embeddings endpoint. `embedder()` is
|
|
|
92
92
|
|
|
93
93
|
## Pricing — per-model registry
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
xAI ships **no built-in price table**: every Grok model on https://docs.x.ai/developers/pricing (checked 2026-10-17) bills all tokens at a higher long-context rate once the prompt reaches 200k tokens, which a flat `ModelPricing` cannot express. Pass the rates you use (USD per 1,000,000 tokens; `ModelPricing`: `input`, `output`, optional `cachedInput`). xAI has no cache-write charge. Resolution: per-model `pricing` > SDK registry > `undefined` (no cost computed).
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
|
+
import { ai, totalCost } from "@warlock.js/ai";
|
|
99
|
+
import { XaiSDK } from "@warlock.js/ai-xai";
|
|
100
|
+
|
|
98
101
|
const xai = new XaiSDK({
|
|
99
|
-
apiKey,
|
|
102
|
+
apiKey: process.env.XAI_API_KEY ?? "",
|
|
100
103
|
pricing: {
|
|
101
|
-
|
|
102
|
-
"grok-3
|
|
104
|
+
// Below-200k rates from xAI's pricing page; long prompts cost more.
|
|
105
|
+
"grok-4.3": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
103
106
|
},
|
|
104
107
|
});
|
|
105
108
|
|
|
106
|
-
const { usage } = await ai.agent({ model: xai.model({ name: "grok-4" }) }).execute("hi");
|
|
107
|
-
usage.cost; //
|
|
109
|
+
const { usage } = await ai.agent({ model: xai.model({ name: "grok-4.3" }) }).execute("hi");
|
|
110
|
+
console.log(totalCost(usage.cost)); // undefined when unpriced
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`usage` follows OpenAI semantics (`prompt_tokens` includes the cached tokens, `inputIncludesCache: true`), and `usage.cost` is attached to every `model.complete()` / streaming `done` once the model is priced.
|
|
114
|
+
|
|
115
|
+
## Prompt caching
|
|
116
|
+
|
|
117
|
+
xAI's Chat Completions accepts `prompt_cache_key`, routed as the `x-grok-conv-id` cache key (https://docs.x.ai/developers/advanced-api-usage/prompt-caching/maximizing-cache-hits). Set `promptCacheKey` on the model — sent while the SDK keeps its default `"xai"` provider label — to keep a conversation's requests on the same cache:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { XaiSDK } from "@warlock.js/ai-xai";
|
|
121
|
+
|
|
122
|
+
const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY ?? "" });
|
|
123
|
+
const model = xai.model({ name: "grok-4.3", promptCacheKey: "conversation:42" });
|
|
108
124
|
```
|
|
109
125
|
|
|
110
|
-
|
|
126
|
+
OpenAI's `prompt_cache_retention` and explicit breakpoints are never sent to xAI.
|
|
111
127
|
|
|
112
128
|
## Errors
|
|
113
129
|
|
|
114
|
-
Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError` hierarchy by the wrapped adapter's error wrapper (dispatch keys on `APIError.status + code`). See the `handle-ai-errors` topic of the `warlock-js-ai` skill.
|
|
130
|
+
Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError` hierarchy by the wrapped adapter's error wrapper (dispatch keys on `APIError.status + code`). See the `handle-ai-errors` topic of the `warlock-js-ai` skill. HTTP 503 (and OpenAI's `server_is_overloaded` code) maps to `ProviderOverloadedError` (`code: "PROVIDER_OVERLOADED"`, `retryable: true`); every wrapped error carries `status`, `retryable` and `billed` (`false` for 401 / 402 / 403, otherwise `"unknown"`).
|
|
115
131
|
|
|
116
132
|
## When NOT to use this skill
|
|
117
133
|
|
|
@@ -123,6 +139,19 @@ Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError
|
|
|
123
139
|
- The `setup-openai` topic of the `warlock-js-ai-openai` skill — the wrapped adapter; full wire / streaming / structured-output / multipart surface
|
|
124
140
|
- The `run-ai-agent` topic of the `warlock-js-ai` skill — passing the model into `ai.agent({...})`
|
|
125
141
|
- The `pick-ai-provider` topic of the `warlock-js-ai` skill — adapter comparison
|
|
126
|
-
|
|
142
|
+
|
|
143
|
+
## Provider body options and token estimates
|
|
144
|
+
|
|
145
|
+
This adapter delegates Chat Completions to the OpenAI adapter, so
|
|
146
|
+
`providerOptions.openai.body` adds native Chat request fields. Other provider
|
|
147
|
+
keys are ignored. Plain-object fields merge one level deep with neutral options;
|
|
148
|
+
caller-provided keys win, while arrays, scalars and `null` replace the field.
|
|
149
|
+
The OpenAI adapter's protected conversation, tool and transport fields remain
|
|
150
|
+
protected here too. Send only fields supported by this provider; do not reuse
|
|
151
|
+
OpenAI-only bodies across a mixed-provider fallback chain.
|
|
152
|
+
|
|
153
|
+
Models from this adapter have no native `countTokens` method. Check
|
|
154
|
+
`model.countTokens` before using an optional native counting capability;
|
|
155
|
+
`sdk.count(text)` is a separate offline estimate.
|
|
127
156
|
|
|
128
157
|
|
package/llms.txt
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
|
|
7
7
|
## Skills
|
|
8
8
|
|
|
9
|
-
- [setup-xai](@warlock.js/ai-xai/setup-xai/SKILL.md): Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI's own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.
|
|
9
|
+
- [setup-xai](@warlock.js/ai-xai/setup-xai/SKILL.md): Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI's own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, `promptCacheKey`, `prompt_cache_key`, xai pricing, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.
|
package/package.json
CHANGED
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
"directory": "packages/ai-xai"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@warlock.js/ai-openai": "5.
|
|
19
|
-
"@warlock.js/logger": "5.
|
|
18
|
+
"@warlock.js/ai-openai": "5.31.0",
|
|
19
|
+
"@warlock.js/logger": "5.31.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@warlock.js/ai": "5.
|
|
22
|
+
"@warlock.js/ai": "5.31.0"
|
|
23
23
|
},
|
|
24
|
-
"version": "5.
|
|
24
|
+
"version": "5.31.0",
|
|
25
25
|
"main": "./cjs/index.cjs",
|
|
26
26
|
"module": "./esm/index.mjs",
|
|
27
27
|
"types": "./esm/index.d.mts",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: setup-xai
|
|
3
|
-
description: 'Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI''s own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.'
|
|
3
|
+
description: 'Wire @warlock.js/ai-xai — new XaiSDK({apiKey, baseURL?, provider?, pricing?}) for xAI Grok, .model({name, vision?, reasoning?, structuredOutput?}) for a ModelContract, .embedder({name, dimensions?}) and .image({name, pricing?}) delegated to the OpenAI-compatible adapter. Thin wrapper over OpenAISDK: uses the xAI OpenAI-compatible endpoint (https://api.x.ai/v1) and injects xAI''s own vision/reasoning inference so Grok names resolve to the right capabilities. Triggers: `XaiSDK`, `grok`, `grok-4`, `grok-3`, `grok-3-mini`, `grok-2-vision`, `.model`, `x.ai`, `api.x.ai`, `XAI_API_KEY`, `reasoning_effort` on Grok, `promptCacheKey`, `prompt_cache_key`, xai pricing, "wire xai/grok into a warlock agent", "configure grok-4", "use grok reasoning effort", "send an image to grok-4 / grok-2-vision"; typical import `import { XaiSDK } from "@warlock.js/ai-xai"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — the `setup-openai` topic of the `warlock-js-ai-openai` skill; adapter comparison — the `pick-ai-provider` topic of the `warlock-js-ai` skill; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# `@warlock.js/ai-xai`
|
|
@@ -24,11 +24,11 @@ const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });
|
|
|
24
24
|
## Producing a model
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
|
-
xai.model({ name: "grok-4" })
|
|
28
|
-
xai.model({ name: "grok-3-mini" })
|
|
29
|
-
xai.model({ name: "grok-2-vision" })
|
|
30
|
-
xai.model({ name: "grok-4", temperature: 0.2 })
|
|
31
|
-
xai.model({ name: "grok-3", vision: true })
|
|
27
|
+
xai.model({ name: "grok-4" }); // vision + reasoning auto-true
|
|
28
|
+
xai.model({ name: "grok-3-mini" }); // reasoning auto-true, vision false
|
|
29
|
+
xai.model({ name: "grok-2-vision" }); // vision auto-true
|
|
30
|
+
xai.model({ name: "grok-4", temperature: 0.2 }); // sampling controls
|
|
31
|
+
xai.model({ name: "grok-3", vision: true }); // explicit capability override
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Returns a `ModelContract` you pass straight into `ai.agent({ model })`.
|
|
@@ -37,13 +37,13 @@ Returns a `ModelContract` you pass straight into `ai.agent({ model })`.
|
|
|
37
37
|
|
|
38
38
|
This adapter ships xAI's OWN name lists (Grok ids don't match OpenAI's `gpt-*` / `o*` prefixes). Capabilities are injected per model before delegating; an explicit value always wins over inference.
|
|
39
39
|
|
|
40
|
-
| Model
|
|
41
|
-
|
|
|
42
|
-
| `grok-4`
|
|
43
|
-
| `grok-3`
|
|
44
|
-
| `grok-3-mini`
|
|
45
|
-
| `grok-2-vision` | true
|
|
46
|
-
| `grok-2`
|
|
40
|
+
| Model | `vision` | `reasoning` |
|
|
41
|
+
| --------------- | -------- | -------------------------- |
|
|
42
|
+
| `grok-4` | true | true (reasoning-first) |
|
|
43
|
+
| `grok-3` | false | false |
|
|
44
|
+
| `grok-3-mini` | false | true (the "think" variant) |
|
|
45
|
+
| `grok-2-vision` | true | false |
|
|
46
|
+
| `grok-2` | false | false |
|
|
47
47
|
|
|
48
48
|
- `vision` — inferred `true` for the `grok-4` and `grok-2-vision` prefixes; `false` otherwise.
|
|
49
49
|
- `reasoning` — inferred `true` for `grok-4` and `grok-3-mini`; drives whether `reasoning.effort` is forwarded as `reasoning_effort` on the wire.
|
|
@@ -56,8 +56,8 @@ This adapter ships xAI's OWN name lists (Grok ids don't match OpenAI's `gpt-*` /
|
|
|
56
56
|
## Reasoning (grok-4 / grok-3-mini)
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
|
-
const model = xai.model({ name: "grok-4" });
|
|
60
|
-
await model.complete(messages, { reasoning: { effort: "high" } });
|
|
59
|
+
const model = xai.model({ name: "grok-4" }); // reasoning auto-true
|
|
60
|
+
await model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
`reasoning.effort` (`"low" | "medium" | "high"`) maps verbatim to the OpenAI-compatible `reasoning_effort` param. When `capabilities.reasoning` is `false` (e.g. `grok-3`), the option is dropped — the adapter never forwards it. Pin `reasoning: true` to force it for a custom/gateway id.
|
|
@@ -84,26 +84,42 @@ xAI does **not** currently expose a public embeddings endpoint. `embedder()` is
|
|
|
84
84
|
|
|
85
85
|
## Pricing — per-model registry
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
xAI ships **no built-in price table**: every Grok model on https://docs.x.ai/developers/pricing (checked 2026-10-17) bills all tokens at a higher long-context rate once the prompt reaches 200k tokens, which a flat `ModelPricing` cannot express. Pass the rates you use (USD per 1,000,000 tokens; `ModelPricing`: `input`, `output`, optional `cachedInput`). xAI has no cache-write charge. Resolution: per-model `pricing` > SDK registry > `undefined` (no cost computed).
|
|
88
88
|
|
|
89
89
|
```ts
|
|
90
|
+
import { ai, totalCost } from "@warlock.js/ai";
|
|
91
|
+
import { XaiSDK } from "@warlock.js/ai-xai";
|
|
92
|
+
|
|
90
93
|
const xai = new XaiSDK({
|
|
91
|
-
apiKey,
|
|
94
|
+
apiKey: process.env.XAI_API_KEY ?? "",
|
|
92
95
|
pricing: {
|
|
93
|
-
|
|
94
|
-
"grok-3
|
|
96
|
+
// Below-200k rates from xAI's pricing page; long prompts cost more.
|
|
97
|
+
"grok-4.3": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
95
98
|
},
|
|
96
99
|
});
|
|
97
100
|
|
|
98
|
-
const { usage } = await ai.agent({ model: xai.model({ name: "grok-4" }) }).execute("hi");
|
|
99
|
-
usage.cost; //
|
|
101
|
+
const { usage } = await ai.agent({ model: xai.model({ name: "grok-4.3" }) }).execute("hi");
|
|
102
|
+
console.log(totalCost(usage.cost)); // undefined when unpriced
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`usage` follows OpenAI semantics (`prompt_tokens` includes the cached tokens, `inputIncludesCache: true`), and `usage.cost` is attached to every `model.complete()` / streaming `done` once the model is priced.
|
|
106
|
+
|
|
107
|
+
## Prompt caching
|
|
108
|
+
|
|
109
|
+
xAI's Chat Completions accepts `prompt_cache_key`, routed as the `x-grok-conv-id` cache key (https://docs.x.ai/developers/advanced-api-usage/prompt-caching/maximizing-cache-hits). Set `promptCacheKey` on the model — sent while the SDK keeps its default `"xai"` provider label — to keep a conversation's requests on the same cache:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { XaiSDK } from "@warlock.js/ai-xai";
|
|
113
|
+
|
|
114
|
+
const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY ?? "" });
|
|
115
|
+
const model = xai.model({ name: "grok-4.3", promptCacheKey: "conversation:42" });
|
|
100
116
|
```
|
|
101
117
|
|
|
102
|
-
|
|
118
|
+
OpenAI's `prompt_cache_retention` and explicit breakpoints are never sent to xAI.
|
|
103
119
|
|
|
104
120
|
## Errors
|
|
105
121
|
|
|
106
|
-
Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError` hierarchy by the wrapped adapter's error wrapper (dispatch keys on `APIError.status + code`). See the `handle-ai-errors` topic of the `warlock-js-ai` skill.
|
|
122
|
+
Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError` hierarchy by the wrapped adapter's error wrapper (dispatch keys on `APIError.status + code`). See the `handle-ai-errors` topic of the `warlock-js-ai` skill. HTTP 503 (and OpenAI's `server_is_overloaded` code) maps to `ProviderOverloadedError` (`code: "PROVIDER_OVERLOADED"`, `retryable: true`); every wrapped error carries `status`, `retryable` and `billed` (`false` for 401 / 402 / 403, otherwise `"unknown"`).
|
|
107
123
|
|
|
108
124
|
## When NOT to use this skill
|
|
109
125
|
|
|
@@ -115,4 +131,17 @@ Raw xAI / OpenAI-SDK errors are wrapped into the typed `@warlock.js/ai` `AIError
|
|
|
115
131
|
- The `setup-openai` topic of the `warlock-js-ai-openai` skill — the wrapped adapter; full wire / streaming / structured-output / multipart surface
|
|
116
132
|
- The `run-ai-agent` topic of the `warlock-js-ai` skill — passing the model into `ai.agent({...})`
|
|
117
133
|
- The `pick-ai-provider` topic of the `warlock-js-ai` skill — adapter comparison
|
|
118
|
-
|
|
134
|
+
|
|
135
|
+
## Provider body options and token estimates
|
|
136
|
+
|
|
137
|
+
This adapter delegates Chat Completions to the OpenAI adapter, so
|
|
138
|
+
`providerOptions.openai.body` adds native Chat request fields. Other provider
|
|
139
|
+
keys are ignored. Plain-object fields merge one level deep with neutral options;
|
|
140
|
+
caller-provided keys win, while arrays, scalars and `null` replace the field.
|
|
141
|
+
The OpenAI adapter's protected conversation, tool and transport fields remain
|
|
142
|
+
protected here too. Send only fields supported by this provider; do not reuse
|
|
143
|
+
OpenAI-only bodies across a mixed-provider fallback chain.
|
|
144
|
+
|
|
145
|
+
Models from this adapter have no native `countTokens` method. Check
|
|
146
|
+
`model.countTokens` before using an optional native counting capability;
|
|
147
|
+
`sdk.count(text)` is a separate offline estimate.
|