@warlock.js/ai-xai 4.6.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.
@@ -0,0 +1,96 @@
1
+ //#region ../@warlock.js/ai-xai/src/known-models.ts
2
+ /**
3
+ * Capability inference for xAI Grok model ids.
4
+ *
5
+ * xAI speaks the OpenAI Chat Completions protocol, so the wire-level
6
+ * adapter is `OpenAISDK`. But Grok model names (`grok-4`,
7
+ * `grok-2-vision`, …) don't match OpenAI's `gpt-*` / `o*` prefixes, so
8
+ * OpenAI's own inference lists would mis-classify every Grok model as
9
+ * non-vision / non-reasoning. This module supplies xAI's OWN name lists
10
+ * and the `XaiSDK` wrapper injects the resulting capability flags into
11
+ * each `OpenAIModelConfig` before delegating, so the right capabilities
12
+ * are set even though the names aren't OpenAI names.
13
+ *
14
+ * All lists are matched as a prefix so dated / `-latest` / `-fast`
15
+ * variants (`grok-4-0709`, `grok-2-vision-latest`,
16
+ * `grok-3-mini-beta`) are covered without enumerating every release
17
+ * tag. Devs can always override per-model via
18
+ * `xai.model({ name, vision: true | false, reasoning: true | false })`
19
+ * — explicit config wins over inference in either direction.
20
+ */
21
+ /**
22
+ * Model-name prefixes for Grok families that accept image input
23
+ * (vision) on the OpenAI-compatible Chat Completions endpoint.
24
+ *
25
+ * - `grok-4` is natively multimodal (text + image input).
26
+ * - `grok-2-vision` is the dedicated image-understanding Grok 2 model.
27
+ *
28
+ * Text-only families (`grok-3`, `grok-3-mini`, the base `grok-2`
29
+ * text model) are intentionally excluded so passing an image
30
+ * attachment to them surfaces a clear, agent-side capability error
31
+ * rather than an opaque xAI 400.
32
+ */
33
+ const XAI_VISION_MODEL_PREFIXES = ["grok-4", "grok-2-vision"];
34
+ /**
35
+ * Model-name prefixes for Grok families that expose internal reasoning
36
+ * and accept reasoning controls (e.g. `reasoning_effort`) on the
37
+ * OpenAI-compatible Chat Completions endpoint.
38
+ *
39
+ * - `grok-4` is a reasoning-first model (it always reasons).
40
+ * - `grok-3-mini` is the "think" variant of Grok 3 and reasons; the
41
+ * full-size `grok-3` does not, so it is deliberately NOT covered by
42
+ * the `grok-3-mini` prefix.
43
+ */
44
+ const XAI_REASONING_MODEL_PREFIXES = ["grok-4", "grok-3-mini"];
45
+ /**
46
+ * A convenience list of the current public Grok chat model ids, handy
47
+ * for menus, validation, and docs. Not exhaustive of every dated alias
48
+ * xAI publishes — pass any id through `xai.model({ name })`; the prefix
49
+ * inference above handles dated / `-latest` variants.
50
+ *
51
+ * @example
52
+ * XAI_CHAT_MODELS.includes("grok-4"); // → true
53
+ */
54
+ const XAI_CHAT_MODELS = [
55
+ "grok-4",
56
+ "grok-3",
57
+ "grok-3-mini",
58
+ "grok-2-vision",
59
+ "grok-2"
60
+ ];
61
+ /**
62
+ * Infer whether a given Grok model id supports vision based on xAI's
63
+ * known-prefix list. Unknown ids default to `false` so that passing an
64
+ * image attachment to an unsupported model surfaces a clear,
65
+ * agent-side capability error instead of an opaque xAI 400.
66
+ *
67
+ * @example
68
+ * inferVisionCapability("grok-4"); // → true
69
+ * inferVisionCapability("grok-2-vision-latest"); // → true
70
+ * inferVisionCapability("grok-3"); // → false
71
+ * inferVisionCapability("grok-3-mini"); // → false
72
+ */
73
+ function inferVisionCapability(modelId) {
74
+ const normalized = modelId.toLowerCase();
75
+ return XAI_VISION_MODEL_PREFIXES.some((prefix) => normalized.startsWith(prefix));
76
+ }
77
+ /**
78
+ * Infer whether a given Grok model id is a reasoning model based on
79
+ * xAI's known-prefix list. Unknown ids default to `false` so the
80
+ * adapter never forwards an unsupported reasoning param to a
81
+ * non-reasoning model.
82
+ *
83
+ * @example
84
+ * inferReasoningCapability("grok-4"); // → true
85
+ * inferReasoningCapability("grok-3-mini"); // → true
86
+ * inferReasoningCapability("grok-3"); // → false
87
+ * inferReasoningCapability("grok-2-vision"); // → false
88
+ */
89
+ function inferReasoningCapability(modelId) {
90
+ const normalized = modelId.toLowerCase();
91
+ return XAI_REASONING_MODEL_PREFIXES.some((prefix) => normalized.startsWith(prefix));
92
+ }
93
+
94
+ //#endregion
95
+ export { XAI_CHAT_MODELS, XAI_REASONING_MODEL_PREFIXES, XAI_VISION_MODEL_PREFIXES, inferReasoningCapability, inferVisionCapability };
96
+ //# sourceMappingURL=known-models.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"known-models.mjs","names":[],"sources":["../../../../../../@warlock.js/ai-xai/src/known-models.ts"],"sourcesContent":["/**\n * Capability inference for xAI Grok model ids.\n *\n * xAI speaks the OpenAI Chat Completions protocol, so the wire-level\n * adapter is `OpenAISDK`. But Grok model names (`grok-4`,\n * `grok-2-vision`, …) don't match OpenAI's `gpt-*` / `o*` prefixes, so\n * OpenAI's own inference lists would mis-classify every Grok model as\n * non-vision / non-reasoning. This module supplies xAI's OWN name lists\n * and the `XaiSDK` wrapper injects the resulting capability flags into\n * each `OpenAIModelConfig` before delegating, so the right capabilities\n * are set even though the names aren't OpenAI names.\n *\n * All lists are matched as a prefix so dated / `-latest` / `-fast`\n * variants (`grok-4-0709`, `grok-2-vision-latest`,\n * `grok-3-mini-beta`) are covered without enumerating every release\n * tag. Devs can always override per-model via\n * `xai.model({ name, vision: true | false, reasoning: true | false })`\n * — explicit config wins over inference in either direction.\n */\n\n/**\n * Model-name prefixes for Grok families that accept image input\n * (vision) on the OpenAI-compatible Chat Completions endpoint.\n *\n * - `grok-4` is natively multimodal (text + image input).\n * - `grok-2-vision` is the dedicated image-understanding Grok 2 model.\n *\n * Text-only families (`grok-3`, `grok-3-mini`, the base `grok-2`\n * text model) are intentionally excluded so passing an image\n * attachment to them surfaces a clear, agent-side capability error\n * rather than an opaque xAI 400.\n */\nexport const XAI_VISION_MODEL_PREFIXES = [\"grok-4\", \"grok-2-vision\"] as const;\n\n/**\n * Model-name prefixes for Grok families that expose internal reasoning\n * and accept reasoning controls (e.g. `reasoning_effort`) on the\n * OpenAI-compatible Chat Completions endpoint.\n *\n * - `grok-4` is a reasoning-first model (it always reasons).\n * - `grok-3-mini` is the \"think\" variant of Grok 3 and reasons; the\n * full-size `grok-3` does not, so it is deliberately NOT covered by\n * the `grok-3-mini` prefix.\n */\nexport const XAI_REASONING_MODEL_PREFIXES = [\"grok-4\", \"grok-3-mini\"] as const;\n\n/**\n * A convenience list of the current public Grok chat model ids, handy\n * for menus, validation, and docs. Not exhaustive of every dated alias\n * xAI publishes — pass any id through `xai.model({ name })`; the prefix\n * inference above handles dated / `-latest` variants.\n *\n * @example\n * XAI_CHAT_MODELS.includes(\"grok-4\"); // → true\n */\nexport const XAI_CHAT_MODELS = [\n \"grok-4\",\n \"grok-3\",\n \"grok-3-mini\",\n \"grok-2-vision\",\n \"grok-2\",\n] as const;\n\n/**\n * Infer whether a given Grok model id supports vision based on xAI's\n * known-prefix list. Unknown ids default to `false` so that passing an\n * image attachment to an unsupported model surfaces a clear,\n * agent-side capability error instead of an opaque xAI 400.\n *\n * @example\n * inferVisionCapability(\"grok-4\"); // → true\n * inferVisionCapability(\"grok-2-vision-latest\"); // → true\n * inferVisionCapability(\"grok-3\"); // → false\n * inferVisionCapability(\"grok-3-mini\"); // → false\n */\nexport function inferVisionCapability(modelId: string): boolean {\n const normalized = modelId.toLowerCase();\n\n return XAI_VISION_MODEL_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n}\n\n/**\n * Infer whether a given Grok model id is a reasoning model based on\n * xAI's known-prefix list. Unknown ids default to `false` so the\n * adapter never forwards an unsupported reasoning param to a\n * non-reasoning model.\n *\n * @example\n * inferReasoningCapability(\"grok-4\"); // → true\n * inferReasoningCapability(\"grok-3-mini\"); // → true\n * inferReasoningCapability(\"grok-3\"); // → false\n * inferReasoningCapability(\"grok-2-vision\"); // → false\n */\nexport function inferReasoningCapability(modelId: string): boolean {\n const normalized = modelId.toLowerCase();\n\n return XAI_REASONING_MODEL_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,4BAA4B,CAAC,UAAU,eAAe;;;;;;;;;;;AAYnE,MAAa,+BAA+B,CAAC,UAAU,aAAa;;;;;;;;;;AAWpE,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;AACF;;;;;;;;;;;;;AAcA,SAAgB,sBAAsB,SAA0B;CAC9D,MAAM,aAAa,QAAQ,YAAY;CAEvC,OAAO,0BAA0B,MAAM,WAAW,WAAW,WAAW,MAAM,CAAC;AACjF;;;;;;;;;;;;;AAcA,SAAgB,yBAAyB,SAA0B;CACjE,MAAM,aAAa,QAAQ,YAAY;CAEvC,OAAO,6BAA6B,MAAM,WAAW,WAAW,WAAW,MAAM,CAAC;AACpF"}
package/esm/sdk.d.mts ADDED
@@ -0,0 +1,108 @@
1
+ import { XaiEmbedderConfig, XaiImageConfig, XaiModelConfig, XaiSDKConfig } from "./config.type.mjs";
2
+ import { EmbedderContract, ImageModelContract, ModelContract, SDKAdapterContract } from "@warlock.js/ai";
3
+
4
+ //#region ../@warlock.js/ai-xai/src/sdk.d.ts
5
+ /**
6
+ * xAI Grok-backed implementation of `SDKAdapterContract`.
7
+ *
8
+ * **Role.** The package entry point for xAI's Grok models. xAI speaks
9
+ * the OpenAI Chat Completions protocol, so `XaiSDK` is a *thin wrapper*
10
+ * over the already-battle-tested {@link OpenAISDK} from
11
+ * `@warlock.js/ai-openai` — NOT a reimplementation. It constructs one
12
+ * internal `OpenAISDK` pointed at xAI's `baseURL` and labeled
13
+ * `provider: "xai"`, then delegates `model()` / `embedder()` /
14
+ * `image()` / `count()` to it. Construct one SDK per account and reuse
15
+ * it everywhere.
16
+ *
17
+ * **Responsibility.**
18
+ * - Owns: the xAI defaults (`baseURL` → `https://api.x.ai/v1`,
19
+ * `provider` → `"xai"`) and this provider's OWN capability inference.
20
+ * Grok model names (`grok-4`, `grok-2-vision`, …) don't match
21
+ * OpenAI's `gpt-*` / `o*` prefixes, so before delegating `model()`
22
+ * the wrapper injects the `vision` / `reasoning` flags inferred from
23
+ * xAI's name lists (see `known-models.ts`). Because explicit config
24
+ * wins over OpenAI's inference inside `OpenAIModel`, the produced
25
+ * `ModelContract` carries the correct Grok capabilities.
26
+ * - Does NOT own: the wire protocol, request/response mapping,
27
+ * streaming, tool-call accumulation, error wrapping, or pricing
28
+ * resolution — all of that is the wrapped `OpenAISDK`'s job and is
29
+ * reused verbatim.
30
+ *
31
+ * Modeled as a class (see §4.2 of code-style.md — "long-lived state
32
+ * across many calls"): it holds one live `OpenAISDK` (which in turn
33
+ * holds one live `OpenAI` client), fronted by FP usage like the other
34
+ * adapters.
35
+ *
36
+ * @example
37
+ * const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });
38
+ * const model = xai.model({ name: "grok-4", temperature: 0.7 });
39
+ * const myAgent = ai.agent({ model });
40
+ *
41
+ * @example
42
+ * // Compose into an `ai.xai` namespace for ergonomic agent wiring.
43
+ * const ai = { agent, tool, systemPrompt, xai: new XaiSDK({ apiKey }) };
44
+ * const fast = ai.agent({ model: ai.xai.model({ name: "grok-3-mini" }) });
45
+ */
46
+ declare class XaiSDK implements SDKAdapterContract {
47
+ /**
48
+ * The wrapped OpenAI-compatible adapter doing the actual wire work.
49
+ * Constructed once with xAI's `baseURL` + `provider` and the caller's
50
+ * `apiKey` / client options, then reused for every produced model,
51
+ * embedder, and image model.
52
+ */
53
+ private readonly openai;
54
+ /**
55
+ * Optional SDK-level pricing registry, kept so `model()` can resolve
56
+ * a per-model entry while still applying this provider's default
57
+ * capability inference. The wrapped `OpenAISDK` also resolves
58
+ * pricing, but we surface it here for parity and to keep the default
59
+ * baseURL/provider injection in one place.
60
+ */
61
+ private readonly pricing?;
62
+ constructor(config: XaiSDKConfig);
63
+ /**
64
+ * Build a `ModelContract` for a Grok model. Delegates to the wrapped
65
+ * `OpenAISDK.model()` after injecting this provider's OWN capability
66
+ * inference: `vision` and `reasoning` are resolved from xAI's
67
+ * name-prefix lists (see `known-models.ts`) unless the caller set them
68
+ * explicitly. Because explicit config wins over OpenAI's inference
69
+ * inside `OpenAIModel`, the returned model self-identifies as
70
+ * `provider: "xai"` and carries Grok's real capabilities even though
71
+ * the model name isn't an OpenAI name.
72
+ *
73
+ * Pricing resolution is left to the wrapped adapter: per-model
74
+ * `config.pricing` wins, otherwise the SDK-level registry entry keyed
75
+ * by `config.name`, otherwise `undefined` (no cost computed).
76
+ *
77
+ * @example
78
+ * xai.model({ name: "grok-4" }); // vision + reasoning auto-true
79
+ * xai.model({ name: "grok-3-mini" }); // reasoning auto-true, vision false
80
+ */
81
+ model(config: XaiModelConfig): ModelContract;
82
+ /**
83
+ * Rough token-count estimate. Delegates straight to the wrapped
84
+ * `OpenAISDK.count()` (the shared character-heuristic from the core
85
+ * package — offline, good for budgeting/quota guards, not billing).
86
+ */
87
+ count(text: string, model?: string): Promise<number>;
88
+ /**
89
+ * Build an `EmbedderContract` by delegating to the wrapped
90
+ * `OpenAISDK.embedder()`.
91
+ *
92
+ * NOTE: xAI does not currently expose a public embeddings endpoint, so
93
+ * this is wired for protocol parity but a call to `embed()` /
94
+ * `embedMany()` will fail upstream. Point an embedder at a dedicated
95
+ * embeddings provider (e.g. `@warlock.js/ai-openai`) for vectors.
96
+ */
97
+ embedder(config: XaiEmbedderConfig): EmbedderContract;
98
+ /**
99
+ * Build an `ImageModelContract` by delegating to the wrapped
100
+ * `OpenAISDK.image()` for use with `ai.image({ model, prompt })`.
101
+ * Pricing resolution mirrors `model()` (per-model `pricing` > SDK
102
+ * registry > `undefined`).
103
+ */
104
+ image(config: XaiImageConfig): ImageModelContract;
105
+ }
106
+ //#endregion
107
+ export { XaiSDK };
108
+ //# sourceMappingURL=sdk.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.mts","names":[],"sources":["../../../../../../@warlock.js/ai-xai/src/sdk.ts"],"mappings":";;;;;;AAuEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0F0D;;cA1F7C,MAAA,YAAkB,kBAAA;;;;;;;mBAOZ,MAAA;;;;;;;;mBASA,OAAA;cAEE,MAAA,EAAQ,YAAA;;;;;;;;;;;;;;;;;;;EAiCpB,KAAA,CAAM,MAAA,EAAQ,cAAA,GAAiB,aAAA;;;;;;EAgBzB,KAAA,CAAM,IAAA,UAAc,KAAA,YAAiB,OAAA;;;;;;;;;;EAa3C,QAAA,CAAS,MAAA,EAAQ,iBAAA,GAAoB,gBAAA;;;;;;;EAUrC,KAAA,CAAM,MAAA,EAAQ,cAAA,GAAiB,kBAAA;AAAA"}
package/esm/sdk.mjs ADDED
@@ -0,0 +1,126 @@
1
+ import { inferReasoningCapability, inferVisionCapability } from "./known-models.mjs";
2
+ import { OpenAISDK } from "@warlock.js/ai-openai";
3
+
4
+ //#region ../@warlock.js/ai-xai/src/sdk.ts
5
+ /**
6
+ * The xAI OpenAI-compatible base URL. xAI exposes Chat Completions at
7
+ * `POST /v1/chat/completions` on this host, so the whole adapter rides
8
+ * on the OpenAI wire protocol.
9
+ */
10
+ const XAI_BASE_URL = "https://api.x.ai/v1";
11
+ /**
12
+ * The default `provider` label stamped on every model this SDK
13
+ * produces. Surfaces on `ModelContract.provider`, `AgentReport.model`,
14
+ * logs, and any provider-aware middleware.
15
+ */
16
+ const XAI_PROVIDER = "xai";
17
+ /**
18
+ * xAI Grok-backed implementation of `SDKAdapterContract`.
19
+ *
20
+ * **Role.** The package entry point for xAI's Grok models. xAI speaks
21
+ * the OpenAI Chat Completions protocol, so `XaiSDK` is a *thin wrapper*
22
+ * over the already-battle-tested {@link OpenAISDK} from
23
+ * `@warlock.js/ai-openai` — NOT a reimplementation. It constructs one
24
+ * internal `OpenAISDK` pointed at xAI's `baseURL` and labeled
25
+ * `provider: "xai"`, then delegates `model()` / `embedder()` /
26
+ * `image()` / `count()` to it. Construct one SDK per account and reuse
27
+ * it everywhere.
28
+ *
29
+ * **Responsibility.**
30
+ * - Owns: the xAI defaults (`baseURL` → `https://api.x.ai/v1`,
31
+ * `provider` → `"xai"`) and this provider's OWN capability inference.
32
+ * Grok model names (`grok-4`, `grok-2-vision`, …) don't match
33
+ * OpenAI's `gpt-*` / `o*` prefixes, so before delegating `model()`
34
+ * the wrapper injects the `vision` / `reasoning` flags inferred from
35
+ * xAI's name lists (see `known-models.ts`). Because explicit config
36
+ * wins over OpenAI's inference inside `OpenAIModel`, the produced
37
+ * `ModelContract` carries the correct Grok capabilities.
38
+ * - Does NOT own: the wire protocol, request/response mapping,
39
+ * streaming, tool-call accumulation, error wrapping, or pricing
40
+ * resolution — all of that is the wrapped `OpenAISDK`'s job and is
41
+ * reused verbatim.
42
+ *
43
+ * Modeled as a class (see §4.2 of code-style.md — "long-lived state
44
+ * across many calls"): it holds one live `OpenAISDK` (which in turn
45
+ * holds one live `OpenAI` client), fronted by FP usage like the other
46
+ * adapters.
47
+ *
48
+ * @example
49
+ * const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });
50
+ * const model = xai.model({ name: "grok-4", temperature: 0.7 });
51
+ * const myAgent = ai.agent({ model });
52
+ *
53
+ * @example
54
+ * // Compose into an `ai.xai` namespace for ergonomic agent wiring.
55
+ * const ai = { agent, tool, systemPrompt, xai: new XaiSDK({ apiKey }) };
56
+ * const fast = ai.agent({ model: ai.xai.model({ name: "grok-3-mini" }) });
57
+ */
58
+ var XaiSDK = class {
59
+ constructor(config) {
60
+ const { baseURL, provider, ...rest } = config;
61
+ this.openai = new OpenAISDK({
62
+ ...rest,
63
+ baseURL: baseURL ?? XAI_BASE_URL,
64
+ provider: provider ?? XAI_PROVIDER
65
+ });
66
+ this.pricing = config.pricing;
67
+ }
68
+ /**
69
+ * Build a `ModelContract` for a Grok model. Delegates to the wrapped
70
+ * `OpenAISDK.model()` after injecting this provider's OWN capability
71
+ * inference: `vision` and `reasoning` are resolved from xAI's
72
+ * name-prefix lists (see `known-models.ts`) unless the caller set them
73
+ * explicitly. Because explicit config wins over OpenAI's inference
74
+ * inside `OpenAIModel`, the returned model self-identifies as
75
+ * `provider: "xai"` and carries Grok's real capabilities even though
76
+ * the model name isn't an OpenAI name.
77
+ *
78
+ * Pricing resolution is left to the wrapped adapter: per-model
79
+ * `config.pricing` wins, otherwise the SDK-level registry entry keyed
80
+ * by `config.name`, otherwise `undefined` (no cost computed).
81
+ *
82
+ * @example
83
+ * xai.model({ name: "grok-4" }); // vision + reasoning auto-true
84
+ * xai.model({ name: "grok-3-mini" }); // reasoning auto-true, vision false
85
+ */
86
+ model(config) {
87
+ return this.openai.model({
88
+ ...config,
89
+ vision: config.vision ?? inferVisionCapability(config.name),
90
+ reasoning: config.reasoning ?? inferReasoningCapability(config.name)
91
+ });
92
+ }
93
+ /**
94
+ * Rough token-count estimate. Delegates straight to the wrapped
95
+ * `OpenAISDK.count()` (the shared character-heuristic from the core
96
+ * package — offline, good for budgeting/quota guards, not billing).
97
+ */
98
+ async count(text, model) {
99
+ return this.openai.count(text, model);
100
+ }
101
+ /**
102
+ * Build an `EmbedderContract` by delegating to the wrapped
103
+ * `OpenAISDK.embedder()`.
104
+ *
105
+ * NOTE: xAI does not currently expose a public embeddings endpoint, so
106
+ * this is wired for protocol parity but a call to `embed()` /
107
+ * `embedMany()` will fail upstream. Point an embedder at a dedicated
108
+ * embeddings provider (e.g. `@warlock.js/ai-openai`) for vectors.
109
+ */
110
+ embedder(config) {
111
+ return this.openai.embedder(config);
112
+ }
113
+ /**
114
+ * Build an `ImageModelContract` by delegating to the wrapped
115
+ * `OpenAISDK.image()` for use with `ai.image({ model, prompt })`.
116
+ * Pricing resolution mirrors `model()` (per-model `pricing` > SDK
117
+ * registry > `undefined`).
118
+ */
119
+ image(config) {
120
+ return this.openai.image(config);
121
+ }
122
+ };
123
+
124
+ //#endregion
125
+ export { XaiSDK };
126
+ //# sourceMappingURL=sdk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.mjs","names":[],"sources":["../../../../../../@warlock.js/ai-xai/src/sdk.ts"],"sourcesContent":["import type {\n EmbedderContract,\n ImageModelContract,\n ModelContract,\n ModelPricing,\n SDKAdapterContract,\n} from \"@warlock.js/ai\";\nimport { OpenAISDK } from \"@warlock.js/ai-openai\";\nimport type {\n XaiEmbedderConfig,\n XaiImageConfig,\n XaiModelConfig,\n XaiSDKConfig,\n} from \"./config.type\";\nimport { inferReasoningCapability, inferVisionCapability } from \"./known-models\";\n\n/**\n * The xAI OpenAI-compatible base URL. xAI exposes Chat Completions at\n * `POST /v1/chat/completions` on this host, so the whole adapter rides\n * on the OpenAI wire protocol.\n */\nconst XAI_BASE_URL = \"https://api.x.ai/v1\";\n\n/**\n * The default `provider` label stamped on every model this SDK\n * produces. Surfaces on `ModelContract.provider`, `AgentReport.model`,\n * logs, and any provider-aware middleware.\n */\nconst XAI_PROVIDER = \"xai\";\n\n/**\n * xAI Grok-backed implementation of `SDKAdapterContract`.\n *\n * **Role.** The package entry point for xAI's Grok models. xAI speaks\n * the OpenAI Chat Completions protocol, so `XaiSDK` is a *thin wrapper*\n * over the already-battle-tested {@link OpenAISDK} from\n * `@warlock.js/ai-openai` — NOT a reimplementation. It constructs one\n * internal `OpenAISDK` pointed at xAI's `baseURL` and labeled\n * `provider: \"xai\"`, then delegates `model()` / `embedder()` /\n * `image()` / `count()` to it. Construct one SDK per account and reuse\n * it everywhere.\n *\n * **Responsibility.**\n * - Owns: the xAI defaults (`baseURL` → `https://api.x.ai/v1`,\n * `provider` → `\"xai\"`) and this provider's OWN capability inference.\n * Grok model names (`grok-4`, `grok-2-vision`, …) don't match\n * OpenAI's `gpt-*` / `o*` prefixes, so before delegating `model()`\n * the wrapper injects the `vision` / `reasoning` flags inferred from\n * xAI's name lists (see `known-models.ts`). Because explicit config\n * wins over OpenAI's inference inside `OpenAIModel`, the produced\n * `ModelContract` carries the correct Grok capabilities.\n * - Does NOT own: the wire protocol, request/response mapping,\n * streaming, tool-call accumulation, error wrapping, or pricing\n * resolution — all of that is the wrapped `OpenAISDK`'s job and is\n * reused verbatim.\n *\n * Modeled as a class (see §4.2 of code-style.md — \"long-lived state\n * across many calls\"): it holds one live `OpenAISDK` (which in turn\n * holds one live `OpenAI` client), fronted by FP usage like the other\n * adapters.\n *\n * @example\n * const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });\n * const model = xai.model({ name: \"grok-4\", temperature: 0.7 });\n * const myAgent = ai.agent({ model });\n *\n * @example\n * // Compose into an `ai.xai` namespace for ergonomic agent wiring.\n * const ai = { agent, tool, systemPrompt, xai: new XaiSDK({ apiKey }) };\n * const fast = ai.agent({ model: ai.xai.model({ name: \"grok-3-mini\" }) });\n */\nexport class XaiSDK implements SDKAdapterContract {\n /**\n * The wrapped OpenAI-compatible adapter doing the actual wire work.\n * Constructed once with xAI's `baseURL` + `provider` and the caller's\n * `apiKey` / client options, then reused for every produced model,\n * embedder, and image model.\n */\n private readonly openai: OpenAISDK;\n\n /**\n * Optional SDK-level pricing registry, kept so `model()` can resolve\n * a per-model entry while still applying this provider's default\n * capability inference. The wrapped `OpenAISDK` also resolves\n * pricing, but we surface it here for parity and to keep the default\n * baseURL/provider injection in one place.\n */\n private readonly pricing?: Record<string, ModelPricing>;\n\n public constructor(config: XaiSDKConfig) {\n const { baseURL, provider, ...rest } = config;\n\n // Inject xAI's defaults — `baseURL` → the xAI OpenAI-compatible\n // endpoint, `provider` → \"xai\" — while still letting the caller\n // override either (e.g. a corporate proxy or a relabeled gateway).\n this.openai = new OpenAISDK({\n ...rest,\n baseURL: baseURL ?? XAI_BASE_URL,\n provider: provider ?? XAI_PROVIDER,\n });\n\n this.pricing = config.pricing;\n }\n\n /**\n * Build a `ModelContract` for a Grok model. Delegates to the wrapped\n * `OpenAISDK.model()` after injecting this provider's OWN capability\n * inference: `vision` and `reasoning` are resolved from xAI's\n * name-prefix lists (see `known-models.ts`) unless the caller set them\n * explicitly. Because explicit config wins over OpenAI's inference\n * inside `OpenAIModel`, the returned model self-identifies as\n * `provider: \"xai\"` and carries Grok's real capabilities even though\n * the model name isn't an OpenAI name.\n *\n * Pricing resolution is left to the wrapped adapter: per-model\n * `config.pricing` wins, otherwise the SDK-level registry entry keyed\n * by `config.name`, otherwise `undefined` (no cost computed).\n *\n * @example\n * xai.model({ name: \"grok-4\" }); // vision + reasoning auto-true\n * xai.model({ name: \"grok-3-mini\" }); // reasoning auto-true, vision false\n */\n public model(config: XaiModelConfig): ModelContract {\n return this.openai.model({\n ...config,\n // xAI names don't match OpenAI's vision/reasoning prefixes, so we\n // resolve them here and pass explicit flags through — explicit\n // config always wins over the OpenAI adapter's own inference.\n vision: config.vision ?? inferVisionCapability(config.name),\n reasoning: config.reasoning ?? inferReasoningCapability(config.name),\n });\n }\n\n /**\n * Rough token-count estimate. Delegates straight to the wrapped\n * `OpenAISDK.count()` (the shared character-heuristic from the core\n * package — offline, good for budgeting/quota guards, not billing).\n */\n public async count(text: string, model?: string): Promise<number> {\n return this.openai.count(text, model);\n }\n\n /**\n * Build an `EmbedderContract` by delegating to the wrapped\n * `OpenAISDK.embedder()`.\n *\n * NOTE: xAI does not currently expose a public embeddings endpoint, so\n * this is wired for protocol parity but a call to `embed()` /\n * `embedMany()` will fail upstream. Point an embedder at a dedicated\n * embeddings provider (e.g. `@warlock.js/ai-openai`) for vectors.\n */\n public embedder(config: XaiEmbedderConfig): EmbedderContract {\n return this.openai.embedder(config);\n }\n\n /**\n * Build an `ImageModelContract` by delegating to the wrapped\n * `OpenAISDK.image()` for use with `ai.image({ model, prompt })`.\n * Pricing resolution mirrors `model()` (per-model `pricing` > SDK\n * registry > `undefined`).\n */\n public image(config: XaiImageConfig): ImageModelContract {\n return this.openai.image(config);\n }\n}\n"],"mappings":";;;;;;;;;AAqBA,MAAM,eAAe;;;;;;AAOrB,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CrB,IAAa,SAAb,MAAkD;CAkBhD,AAAO,YAAY,QAAsB;EACvC,MAAM,EAAE,SAAS,UAAU,GAAG,SAAS;EAKvC,KAAK,SAAS,IAAI,UAAU;GAC1B,GAAG;GACH,SAAS,WAAW;GACpB,UAAU,YAAY;EACxB,CAAC;EAED,KAAK,UAAU,OAAO;CACxB;;;;;;;;;;;;;;;;;;;CAoBA,AAAO,MAAM,QAAuC;EAClD,OAAO,KAAK,OAAO,MAAM;GACvB,GAAG;GAIH,QAAQ,OAAO,UAAU,sBAAsB,OAAO,IAAI;GAC1D,WAAW,OAAO,aAAa,yBAAyB,OAAO,IAAI;EACrE,CAAC;CACH;;;;;;CAOA,MAAa,MAAM,MAAc,OAAiC;EAChE,OAAO,KAAK,OAAO,MAAM,MAAM,KAAK;CACtC;;;;;;;;;;CAWA,AAAO,SAAS,QAA6C;EAC3D,OAAO,KAAK,OAAO,SAAS,MAAM;CACpC;;;;;;;CAQA,AAAO,MAAM,QAA4C;EACvD,OAAO,KAAK,OAAO,MAAM,MAAM;CACjC;AACF"}
package/llms-full.txt ADDED
@@ -0,0 +1,128 @@
1
+ # Warlock AI Xai — full skills
2
+
3
+ > Package: `@warlock.js/ai-xai`
4
+
5
+ > Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/ai-xai/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
6
+
7
+ ## setup-xai `@warlock.js/ai-xai/setup-xai/SKILL.md`
8
+
9
+ ---
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 — `@warlock.js/ai/run-ai-agent/SKILL.md`; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — `@warlock.js/ai-openai/skills/setup-openai/SKILL.md`; adapter comparison — `@warlock.js/ai/pick-ai-provider/SKILL.md`; competing adapters `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `openai` SDK pointed at x.ai by hand.'
12
+ ---
13
+
14
+ # `@warlock.js/ai-xai`
15
+
16
+ Provider adapter for xAI's **Grok** models. xAI speaks the OpenAI Chat Completions protocol, so `XaiSDK` is a **thin wrapper** over [`OpenAISDK`](../../../ai-openai/skills/setup-openai/SKILL.md) — it does not reimplement the wire layer. It constructs one internal `OpenAISDK` pointed at xAI's `baseURL` and labeled `provider: "xai"`, then delegates `model()` / `embedder()` / `image()` / `count()`, injecting xAI's own capability inference so Grok model names resolve correctly. Pair with `@warlock.js/ai` for the agent / tool / system-prompt surface.
17
+
18
+ ## Construction
19
+
20
+ ```ts
21
+ import { XaiSDK } from "@warlock.js/ai-xai";
22
+
23
+ const xai = new XaiSDK({ apiKey: process.env.XAI_API_KEY! });
24
+ ```
25
+
26
+ - `baseURL` defaults to `https://api.x.ai/v1` (the xAI OpenAI-compatible endpoint). Override only to target a proxy/gateway.
27
+ - `provider` defaults to `"xai"` — flows through to `ModelContract.provider`, `AgentReport.model.provider`, and logs. Set it to relabel a gateway upstream.
28
+ - Every other upstream `ClientOptions` value (`timeout`, `maxRetries`, `defaultHeaders`, `fetch`, …) is forwarded verbatim to the wrapped client.
29
+
30
+ `XaiSDK` is a class (not a factory) — it holds a long-lived wrapped `OpenAISDK` (which holds a long-lived `OpenAI` client). Construct one per account and reuse it.
31
+
32
+ ## Producing a model
33
+
34
+ ```ts
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
+ ```
41
+
42
+ Returns a `ModelContract` you pass straight into `ai.agent({ model })`.
43
+
44
+ ## Models & capabilities — what's auto-set
45
+
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
+
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
+
56
+ - `vision` — inferred `true` for the `grok-4` and `grok-2-vision` prefixes; `false` otherwise.
57
+ - `reasoning` — inferred `true` for `grok-4` and `grok-3-mini`; drives whether `reasoning.effort` is forwarded as `reasoning_effort` on the wire.
58
+ - `structuredOutput` / `promptCaching` and the image/PDF/audio wire mapping all come from the wrapped OpenAI adapter unchanged — see [`setup-openai`](../../../ai-openai/skills/setup-openai/SKILL.md).
59
+
60
+ **Override `vision`, `reasoning`, or `structuredOutput` explicitly** via `.model({ name, vision?, reasoning?, structuredOutput? })`.
61
+
62
+ > Model availability changes over time — pass any current Grok id through `.model({ name })`; the prefix inference covers dated / `-latest` / `-fast` / `-beta` variants. Don't assume a model exists; check xAI's docs.
63
+
64
+ ## Reasoning (grok-4 / grok-3-mini)
65
+
66
+ ```ts
67
+ const model = xai.model({ name: "grok-4" }); // reasoning auto-true
68
+ await model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"
69
+ ```
70
+
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.
72
+
73
+ ## Multipart messages (image input)
74
+
75
+ Image attachments reach the wire only on a vision-capable model (`grok-4`, `grok-2-vision`); the agent's modality gate throws otherwise. Mapping to OpenAI `image_url` parts is identical to the OpenAI adapter — see [`setup-openai`](../../../ai-openai/skills/setup-openai/SKILL.md).
76
+
77
+ ## Uses the OpenAI-compatible endpoint
78
+
79
+ All wire work — request/response mapping, streaming, tool-call accumulation, structured output, usage extraction — is the wrapped `OpenAISDK`'s, unchanged. The wrapper only: (1) sets the xAI `baseURL` + `provider` defaults, and (2) injects xAI's vision/reasoning inference per model. For streaming, structured output, and the full multipart surface, read [`@warlock.js/ai-openai/skills/setup-openai/SKILL.md`](../../../ai-openai/skills/setup-openai/SKILL.md).
80
+
81
+ ## Embeddings — not available on xAI
82
+
83
+ ```ts
84
+ xai.embedder({ name: "text-embedding-3-small" }); // delegates, but xAI has no embeddings API yet
85
+ ```
86
+
87
+ xAI does **not** currently expose a public embeddings endpoint. `embedder()` is wired for protocol parity, but a call to `embed()` / `embedMany()` fails upstream. Point an embedder at a dedicated provider (e.g. `@warlock.js/ai-openai`) for vectors.
88
+
89
+ ## Image generation — delegated guard
90
+
91
+ `image()` delegates to the wrapped OpenAI Images adapter, which only recognizes `gpt-image-*` / `dall-e-*` ids and rejects anything else at construction. xAI's image generation ("Grok Imagine") is a separate, non-OpenAI-Images-compatible surface, so use `@warlock.js/ai-openai`'s `image()` for OpenAI-Images generation.
92
+
93
+ ## Pricing — per-model registry
94
+
95
+ `pricing` is a registry keyed by model name, rates in **USD per 1,000,000 tokens** (`ModelPricing`: `input`, `output`, optional `cachedInput` / `cachedOutput`). Resolution is delegated: per-model `pricing` > SDK registry > `undefined` (no cost computed).
96
+
97
+ ```ts
98
+ const xai = new XaiSDK({
99
+ apiKey,
100
+ pricing: {
101
+ "grok-4": { input: 3, output: 15 },
102
+ "grok-3-mini": { input: 0.3, output: 0.5 },
103
+ },
104
+ });
105
+
106
+ const { usage } = await ai.agent({ model: xai.model({ name: "grok-4" }) }).execute("hi");
107
+ usage.cost; // per-channel USD breakdown of THIS run, or undefined when unpriced
108
+ ```
109
+
110
+ > Pricing numbers above are illustrative placeholders — set the current xAI rates yourself.
111
+
112
+ ## Errors
113
+
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 [`@warlock.js/ai/handle-ai-errors/SKILL.md`](@warlock.js/ai/handle-ai-errors/SKILL.md).
115
+
116
+ ## When NOT to use this skill
117
+
118
+ - Direct calls to the `openai` SDK pointed at `api.x.ai` by hand — without going through `@warlock.js/ai` agents.
119
+ - Non-Grok models — OpenAI: `@warlock.js/ai-openai`. Anthropic: `@warlock.js/ai-anthropic`. Gemini: `@warlock.js/ai-google`. Ollama: `@warlock.js/ai-ollama`.
120
+
121
+ ## See also
122
+
123
+ - [`@warlock.js/ai-openai/skills/setup-openai/SKILL.md`](../../../ai-openai/skills/setup-openai/SKILL.md) — the wrapped adapter; full wire / streaming / structured-output / multipart surface
124
+ - [`@warlock.js/ai/run-ai-agent/SKILL.md`](@warlock.js/ai/run-ai-agent/SKILL.md) — passing the model into `ai.agent({...})`
125
+ - [`@warlock.js/ai/pick-ai-provider/SKILL.md`](@warlock.js/ai/pick-ai-provider/SKILL.md) — adapter comparison
126
+ ```
127
+
128
+
package/llms.txt ADDED
@@ -0,0 +1,9 @@
1
+ # Warlock AI Xai
2
+
3
+ > Package: `@warlock.js/ai-xai`
4
+
5
+ > xAI Grok adapter for @warlock.js/ai
6
+
7
+ ## Skills
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 — `@warlock.js/ai/run-ai-agent/SKILL.md`; the underlying OpenAI-compatible adapter and its full capability/streaming/error surface — `@warlock.js/ai-openai/skills/setup-openai/SKILL.md`; adapter comparison — `@warlock.js/ai/pick-ai-provider/SKILL.md`; 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 ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@warlock.js/ai-xai",
3
+ "description": "xAI Grok adapter for @warlock.js/ai",
4
+ "keywords": [
5
+ "warlock",
6
+ "ai",
7
+ "xai",
8
+ "grok"
9
+ ],
10
+ "author": "Hasan Zohdy",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/warlockjs/ai-xai"
15
+ },
16
+ "dependencies": {
17
+ "@warlock.js/ai-openai": "4.6.0",
18
+ "@warlock.js/logger": "4.6.0"
19
+ },
20
+ "peerDependencies": {
21
+ "@warlock.js/ai": "4.6.0"
22
+ },
23
+ "version": "4.6.0",
24
+ "main": "./cjs/index.cjs",
25
+ "module": "./esm/index.mjs",
26
+ "types": "./esm/index.d.mts",
27
+ "exports": {
28
+ ".": {
29
+ "import": {
30
+ "types": "./esm/index.d.mts",
31
+ "default": "./esm/index.mjs"
32
+ },
33
+ "require": {
34
+ "types": "./esm/index.d.mts",
35
+ "default": "./cjs/index.cjs"
36
+ }
37
+ }
38
+ }
39
+ }