@moxxy/plugin-provider-xai 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Moxxy (moxxy.ai)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ import { grokModels } from './models.js';
2
+ export { grokModels };
3
+ /**
4
+ * xAI (Grok). The xAI API speaks the OpenAI Chat Completions protocol, so this
5
+ * reuses the shared {@link defineOpenAICompatProvider} with the `xai` slug +
6
+ * base URL + Grok catalog forced on (so usage stats, provider events and error
7
+ * context attribute to `xai`, not `openai`).
8
+ */
9
+ export declare const xaiProviderDef: import("@moxxy/sdk").ProviderDef;
10
+ export declare const xaiPlugin: import("@moxxy/sdk").Plugin;
11
+ export default xaiPlugin;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,CAAC;AAKtB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,kCASzB,CAAC;AAEH,eAAO,MAAM,SAAS,6BAIpB,CAAC;AAEH,eAAe,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ import { definePlugin } from '@moxxy/sdk';
2
+ import { defineOpenAICompatProvider } from '@moxxy/plugin-provider-openai';
3
+ import { grokModels } from './models.js';
4
+ export { grokModels };
5
+ const XAI_BASE_URL = 'https://api.x.ai/v1';
6
+ const XAI_DEFAULT_MODEL = 'grok-4';
7
+ /**
8
+ * xAI (Grok). The xAI API speaks the OpenAI Chat Completions protocol, so this
9
+ * reuses the shared {@link defineOpenAICompatProvider} with the `xai` slug +
10
+ * base URL + Grok catalog forced on (so usage stats, provider events and error
11
+ * context attribute to `xai`, not `openai`).
12
+ */
13
+ export const xaiProviderDef = defineOpenAICompatProvider({
14
+ name: 'xai',
15
+ baseURL: XAI_BASE_URL,
16
+ defaultModel: XAI_DEFAULT_MODEL,
17
+ models: grokModels,
18
+ auth: {
19
+ kind: 'apiKey',
20
+ hint: 'xAI API key (starts with `xai-`) from https://console.x.ai',
21
+ },
22
+ });
23
+ export const xaiPlugin = definePlugin({
24
+ name: '@moxxy/plugin-provider-xai',
25
+ version: '0.0.0',
26
+ providers: [xaiProviderDef],
27
+ });
28
+ export default xaiPlugin;
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAC3C,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC;IACvD,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,YAAY;IACrB,YAAY,EAAE,iBAAiB;IAC/B,MAAM,EAAE,UAAU;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,4DAA4D;KACnE;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;IACpC,IAAI,EAAE,4BAA4B;IAClC,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,CAAC,cAAc,CAAC;CAC5B,CAAC,CAAC;AAEH,eAAe,SAAS,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ModelDescriptor } from '@moxxy/sdk';
2
+ /**
3
+ * xAI Grok model catalog, as of 2026-06 (verify against
4
+ * https://docs.x.ai/docs/models). The xAI API is OpenAI-compatible, so these
5
+ * stream through the shared {@link import('@moxxy/plugin-provider-openai').OpenAIProvider}.
6
+ * grok-4.3 is the current flagship with a 1M context; the grok-4 tier is 256k;
7
+ * grok-3 is 131k. Vision is available on the grok-4 family. An unlisted model
8
+ * id still works — it's passed straight through to api.x.ai; the catalog only
9
+ * drives context-window budgets and capability gating.
10
+ *
11
+ * The grok-4 family + grok-3-mini are reasoning models — xAI streams their
12
+ * `reasoning_content` deltas, which the shared OpenAIProvider already surfaces;
13
+ * supportsReasoning gates reasoning_effort + reasoning-stream surfacing on
14
+ * (without it the capability is dead upstream even when the user enables it).
15
+ *
16
+ * supportsDocuments is intentionally NOT set: the xAI API is reached through the
17
+ * OpenAI-compatibility surface, and (like the Gemini compat endpoint) it does
18
+ * not honor the OpenAI `file`/`file_data` content part the shared translate
19
+ * layer emits for `document` blocks. Asserting it would make the desktop ship
20
+ * raw PDF bytes the endpoint rejects/ignores — losing the document with no
21
+ * fallback. Leaving it unset keeps the safe extracted-text path. Images ride
22
+ * `image_url` data URLs (accepted), so supportsImages stays true on the vision
23
+ * tier.
24
+ */
25
+ export declare const grokModels: ReadonlyArray<ModelDescriptor>;
26
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,eAAe,CAYrD,CAAC"}
package/dist/models.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * xAI Grok model catalog, as of 2026-06 (verify against
3
+ * https://docs.x.ai/docs/models). The xAI API is OpenAI-compatible, so these
4
+ * stream through the shared {@link import('@moxxy/plugin-provider-openai').OpenAIProvider}.
5
+ * grok-4.3 is the current flagship with a 1M context; the grok-4 tier is 256k;
6
+ * grok-3 is 131k. Vision is available on the grok-4 family. An unlisted model
7
+ * id still works — it's passed straight through to api.x.ai; the catalog only
8
+ * drives context-window budgets and capability gating.
9
+ *
10
+ * The grok-4 family + grok-3-mini are reasoning models — xAI streams their
11
+ * `reasoning_content` deltas, which the shared OpenAIProvider already surfaces;
12
+ * supportsReasoning gates reasoning_effort + reasoning-stream surfacing on
13
+ * (without it the capability is dead upstream even when the user enables it).
14
+ *
15
+ * supportsDocuments is intentionally NOT set: the xAI API is reached through the
16
+ * OpenAI-compatibility surface, and (like the Gemini compat endpoint) it does
17
+ * not honor the OpenAI `file`/`file_data` content part the shared translate
18
+ * layer emits for `document` blocks. Asserting it would make the desktop ship
19
+ * raw PDF bytes the endpoint rejects/ignores — losing the document with no
20
+ * fallback. Leaving it unset keeps the safe extracted-text path. Images ride
21
+ * `image_url` data URLs (accepted), so supportsImages stays true on the vision
22
+ * tier.
23
+ */
24
+ export const grokModels = [
25
+ // grok-4 family: current frontier. 4.3 is the flagship (1M context). Reasoning + vision.
26
+ { id: 'grok-4.3', contextWindow: 1_000_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
27
+ { id: 'grok-4', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
28
+ { id: 'grok-4-fast', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
29
+ // grok-code-fast-1: agentic-coding specialist (text-only). Reasoning model.
30
+ { id: 'grok-code-fast-1', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsReasoning: true },
31
+ // grok-3 tier: prior generation, still served. Only the -mini variant reasons.
32
+ { id: 'grok-3', contextWindow: 131_072, maxOutputTokens: 32_768, supportsTools: true, supportsStreaming: true },
33
+ { id: 'grok-3-mini', contextWindow: 131_072, maxOutputTokens: 32_768, supportsTools: true, supportsStreaming: true, supportsReasoning: true },
34
+ ];
35
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAmC;IACxD,yFAAyF;IACzF,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAClK,EAAE,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAC9J,EAAE,EAAE,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAEnK,4EAA4E;IAC5E,EAAE,EAAE,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAElJ,+EAA+E;IAC/E,EAAE,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAC/G,EAAE,EAAE,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;CAC9I,CAAC"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@moxxy/plugin-provider-xai",
3
+ "version": "0.21.1",
4
+ "description": "xAI (Grok) LLMProvider plugin for moxxy. Streams the OpenAI-compatible xAI API (https://api.x.ai/v1).",
5
+ "keywords": [
6
+ "moxxy",
7
+ "agent",
8
+ "provider",
9
+ "xai",
10
+ "grok",
11
+ "llm"
12
+ ],
13
+ "homepage": "https://moxxy.ai",
14
+ "bugs": {
15
+ "url": "https://github.com/moxxy-ai/moxxy/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/moxxy-ai/moxxy.git",
20
+ "directory": "packages/plugin-provider-xai"
21
+ },
22
+ "author": "Michal Makowski <michal.makowski97@gmail.com>",
23
+ "license": "MIT",
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "type": "module",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src"
39
+ ],
40
+ "moxxy": {
41
+ "plugin": {
42
+ "entry": "./dist/index.js",
43
+ "kind": "provider"
44
+ }
45
+ },
46
+ "dependencies": {
47
+ "@moxxy/sdk": "0.21.1",
48
+ "@moxxy/plugin-provider-openai": "0.21.1"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.10.0",
52
+ "typescript": "^5.7.3",
53
+ "vitest": "^2.1.8",
54
+ "zod": "^3.24.0",
55
+ "@moxxy/tsconfig": "0.0.0",
56
+ "@moxxy/vitest-preset": "0.0.0"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc -p tsconfig.json",
60
+ "typecheck": "tsc -p tsconfig.json --noEmit",
61
+ "test": "vitest run",
62
+ "clean": "rm -rf dist .turbo"
63
+ }
64
+ }
@@ -0,0 +1,120 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { xaiPlugin, xaiProviderDef, grokModels } from './index.js';
3
+
4
+ describe('@moxxy/plugin-provider-xai', () => {
5
+ it('registers the xai provider', () => {
6
+ expect(xaiPlugin.providers?.map((p) => p.name)).toEqual(['xai']);
7
+ });
8
+
9
+ it('advertises the Grok catalog (including the 1M-context grok-4.3 flagship)', () => {
10
+ expect(xaiProviderDef.models).toEqual(grokModels);
11
+ expect(grokModels.find((m) => m.id === 'grok-4.3')).toMatchObject({ contextWindow: 1_000_000 });
12
+ });
13
+
14
+ it('createClient stamps the xai slug so usage/errors attribute to xAI, not openai', () => {
15
+ const client = xaiProviderDef.createClient({ apiKey: 'xai-test-key' });
16
+ expect(client.name).toBe('xai');
17
+ expect(client.models).toEqual(grokModels);
18
+ });
19
+
20
+ it('exposes an apiKey auth descriptor', () => {
21
+ expect(xaiProviderDef.auth).toMatchObject({ kind: 'apiKey' });
22
+ });
23
+
24
+ it('the reasoning-tier Grok models advertise supportsReasoning', () => {
25
+ // Reasoning gating (reasoning_effort + reasoning-stream surfacing) keys off
26
+ // this flag; absent it, the loop silently drops reasoning config even when
27
+ // the user enables it. The grok-4 family + grok-3-mini are reasoning models.
28
+ const reasoningIds = ['grok-4.3', 'grok-4', 'grok-4-fast', 'grok-code-fast-1', 'grok-3-mini'];
29
+ for (const id of reasoningIds) {
30
+ expect(grokModels.find((m) => m.id === id)?.supportsReasoning, id).toBe(true);
31
+ }
32
+ // The non-mini grok-3 is NOT a reasoning model — keep the flag off so the
33
+ // loop doesn't request reasoning the model won't honor.
34
+ expect(grokModels.find((m) => m.id === 'grok-3')?.supportsReasoning).toBeUndefined();
35
+ });
36
+
37
+ it('every Grok descriptor carries a positive, in-window maxOutputTokens budget', () => {
38
+ // Without maxOutputTokens the context budgeter can't reserve completion
39
+ // space, so a near-full window + large generation gets server-truncated
40
+ // instead of pre-emptively elided.
41
+ for (const m of grokModels) {
42
+ expect(typeof m.maxOutputTokens, `${m.id} maxOutputTokens`).toBe('number');
43
+ expect(m.maxOutputTokens!, `${m.id} maxOutputTokens > 0`).toBeGreaterThan(0);
44
+ expect(m.maxOutputTokens!, `${m.id} maxOutputTokens <= contextWindow`).toBeLessThanOrEqual(m.contextWindow);
45
+ }
46
+ });
47
+
48
+ it('every Grok descriptor is structurally well-formed (positive window, required flags, unique id)', () => {
49
+ // Lock the catalog invariants so a careless future edit can't silently ship
50
+ // a descriptor the SDK budgeter/capability-gating would mis-read.
51
+ const seen = new Set<string>();
52
+ for (const m of grokModels) {
53
+ expect(typeof m.id, 'id is a string').toBe('string');
54
+ expect(m.id.length, `${m.id} id non-empty`).toBeGreaterThan(0);
55
+ expect(seen.has(m.id), `${m.id} is not duplicated`).toBe(false);
56
+ seen.add(m.id);
57
+ expect(typeof m.contextWindow, `${m.id} contextWindow`).toBe('number');
58
+ expect(m.contextWindow, `${m.id} contextWindow > 0`).toBeGreaterThan(0);
59
+ expect(m.supportsTools, `${m.id} supportsTools`).toBe(true);
60
+ expect(m.supportsStreaming, `${m.id} supportsStreaming`).toBe(true);
61
+ }
62
+ });
63
+
64
+ it('no Grok descriptor asserts supportsDocuments (OpenAI-compat endpoint rejects native file parts)', () => {
65
+ // Intentional: the xAI compat surface does not honor the OpenAI `file`/
66
+ // `file_data` content part the shared translate layer emits for `document`
67
+ // blocks. Asserting supportsDocuments would make the desktop ship raw PDF
68
+ // bytes the endpoint drops — losing the doc with no fallback. The safe path
69
+ // is the extracted-text route (supportsDocuments unset → text). Guard the
70
+ // decision so it can't be re-introduced without an explicit, tested choice.
71
+ for (const m of grokModels) {
72
+ expect(m.supportsDocuments, `${m.id} must not assert supportsDocuments`).toBeUndefined();
73
+ }
74
+ });
75
+
76
+ it('createClient degrades to xAI defaults on hostile/wrong-typed config (no smuggled non-string fields)', () => {
77
+ // The registry hands createClient an untyped Record<string, unknown>. A
78
+ // wrong-typed baseURL/defaultModel (object/number) must NOT reach the OpenAI
79
+ // SDK (where a non-string baseURL would throw or silently mis-route); the
80
+ // narrowing drops them so the vendor defaults stand. A string apiKey is
81
+ // present (the SDK constructor requires a non-empty key) — everything else
82
+ // is hostile. The worst case here is degradation to defaults, never a crash.
83
+ const hostile = {
84
+ apiKey: 'xai-test-key',
85
+ baseURL: { evil: true },
86
+ defaultModel: 12345,
87
+ extraJunk: ['should', 'be', 'ignored'],
88
+ } as unknown as Record<string, unknown>;
89
+ const client = xaiProviderDef.createClient(hostile);
90
+ expect(client.name).toBe('xai');
91
+ expect(client.models).toEqual(grokModels);
92
+ });
93
+
94
+ it('refuses an empty config rather than smuggling OPENAI_API_KEY to xai', () => {
95
+ // Worst case: the registry hands us {} (no key) while OPENAI_API_KEY is set in
96
+ // env. The OpenAI SDK ctor would silently fall back to it and ship the user's
97
+ // real OpenAI credential to api.x.ai — createClient MUST refuse, not smuggle.
98
+ const prev = process.env.OPENAI_API_KEY;
99
+ process.env.OPENAI_API_KEY = 'sk-env-fallback-for-test';
100
+ try {
101
+ expect(() => xaiProviderDef.createClient({})).toThrow(/requires an API key/);
102
+ } finally {
103
+ if (prev === undefined) delete process.env.OPENAI_API_KEY;
104
+ else process.env.OPENAI_API_KEY = prev;
105
+ }
106
+ });
107
+
108
+ it('builds a working client when a real apiKey is supplied (no junk smuggled)', () => {
109
+ const client = xaiProviderDef.createClient({ apiKey: 'xai-test-key' });
110
+ expect(client.name).toBe('xai');
111
+ expect(client.models).toEqual(grokModels);
112
+ });
113
+
114
+ it('exposes a validateKey probe (so a bad xAI key is caught before first stream)', () => {
115
+ // defineOpenAICompatProvider wires validateOpenAICompatKey against the xAI
116
+ // base URL unless validate:false. xai relies on the default, so the setup
117
+ // wizard / `moxxy login` can verify the key against api.x.ai/v1/models.
118
+ expect(typeof xaiProviderDef.validateKey).toBe('function');
119
+ });
120
+ });
package/src/index.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { definePlugin } from '@moxxy/sdk';
2
+ import { defineOpenAICompatProvider } from '@moxxy/plugin-provider-openai';
3
+ import { grokModels } from './models.js';
4
+
5
+ export { grokModels };
6
+
7
+ const XAI_BASE_URL = 'https://api.x.ai/v1';
8
+ const XAI_DEFAULT_MODEL = 'grok-4';
9
+
10
+ /**
11
+ * xAI (Grok). The xAI API speaks the OpenAI Chat Completions protocol, so this
12
+ * reuses the shared {@link defineOpenAICompatProvider} with the `xai` slug +
13
+ * base URL + Grok catalog forced on (so usage stats, provider events and error
14
+ * context attribute to `xai`, not `openai`).
15
+ */
16
+ export const xaiProviderDef = defineOpenAICompatProvider({
17
+ name: 'xai',
18
+ baseURL: XAI_BASE_URL,
19
+ defaultModel: XAI_DEFAULT_MODEL,
20
+ models: grokModels,
21
+ auth: {
22
+ kind: 'apiKey',
23
+ hint: 'xAI API key (starts with `xai-`) from https://console.x.ai',
24
+ },
25
+ });
26
+
27
+ export const xaiPlugin = definePlugin({
28
+ name: '@moxxy/plugin-provider-xai',
29
+ version: '0.0.0',
30
+ providers: [xaiProviderDef],
31
+ });
32
+
33
+ export default xaiPlugin;
package/src/models.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type { ModelDescriptor } from '@moxxy/sdk';
2
+
3
+ /**
4
+ * xAI Grok model catalog, as of 2026-06 (verify against
5
+ * https://docs.x.ai/docs/models). The xAI API is OpenAI-compatible, so these
6
+ * stream through the shared {@link import('@moxxy/plugin-provider-openai').OpenAIProvider}.
7
+ * grok-4.3 is the current flagship with a 1M context; the grok-4 tier is 256k;
8
+ * grok-3 is 131k. Vision is available on the grok-4 family. An unlisted model
9
+ * id still works — it's passed straight through to api.x.ai; the catalog only
10
+ * drives context-window budgets and capability gating.
11
+ *
12
+ * The grok-4 family + grok-3-mini are reasoning models — xAI streams their
13
+ * `reasoning_content` deltas, which the shared OpenAIProvider already surfaces;
14
+ * supportsReasoning gates reasoning_effort + reasoning-stream surfacing on
15
+ * (without it the capability is dead upstream even when the user enables it).
16
+ *
17
+ * supportsDocuments is intentionally NOT set: the xAI API is reached through the
18
+ * OpenAI-compatibility surface, and (like the Gemini compat endpoint) it does
19
+ * not honor the OpenAI `file`/`file_data` content part the shared translate
20
+ * layer emits for `document` blocks. Asserting it would make the desktop ship
21
+ * raw PDF bytes the endpoint rejects/ignores — losing the document with no
22
+ * fallback. Leaving it unset keeps the safe extracted-text path. Images ride
23
+ * `image_url` data URLs (accepted), so supportsImages stays true on the vision
24
+ * tier.
25
+ */
26
+ export const grokModels: ReadonlyArray<ModelDescriptor> = [
27
+ // grok-4 family: current frontier. 4.3 is the flagship (1M context). Reasoning + vision.
28
+ { id: 'grok-4.3', contextWindow: 1_000_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
29
+ { id: 'grok-4', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
30
+ { id: 'grok-4-fast', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsImages: true, supportsReasoning: true },
31
+
32
+ // grok-code-fast-1: agentic-coding specialist (text-only). Reasoning model.
33
+ { id: 'grok-code-fast-1', contextWindow: 256_000, maxOutputTokens: 64_000, supportsTools: true, supportsStreaming: true, supportsReasoning: true },
34
+
35
+ // grok-3 tier: prior generation, still served. Only the -mini variant reasons.
36
+ { id: 'grok-3', contextWindow: 131_072, maxOutputTokens: 32_768, supportsTools: true, supportsStreaming: true },
37
+ { id: 'grok-3-mini', contextWindow: 131_072, maxOutputTokens: 32_768, supportsTools: true, supportsStreaming: true, supportsReasoning: true },
38
+ ];