@tanstack/ai-grok 0.6.5 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/adapters/text.d.ts +7 -5
- package/dist/esm/adapters/text.js +34 -23
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/model-meta.d.ts +30 -0
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/tools/index.js +7 -0
- package/dist/esm/tools/index.js.map +1 -0
- package/package.json +6 -2
- package/src/adapters/text.ts +61 -29
- package/src/index.ts +1 -0
- package/src/model-meta.ts +32 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { BaseTextAdapter, StructuredOutputOptions, StructuredOutputResult } from '@tanstack/ai/adapters';
|
|
2
|
-
import { GROK_CHAT_MODELS, ResolveInputModalities, ResolveProviderOptions } from '../model-meta.js';
|
|
3
|
-
import { StreamChunk, TextOptions } from '@tanstack/ai';
|
|
2
|
+
import { GROK_CHAT_MODELS, GrokChatModelToolCapabilitiesByName, ResolveInputModalities, ResolveProviderOptions } from '../model-meta.js';
|
|
3
|
+
import { Modality, StreamChunk, TextOptions } from '@tanstack/ai';
|
|
4
|
+
import { ExternalTextProviderOptions as GrokTextProviderOptions } from '../text/text-provider-options.js';
|
|
4
5
|
import { GrokMessageMetadataByModality } from '../message-types.js';
|
|
5
6
|
import { GrokClientConfig } from '../utils.js';
|
|
7
|
+
type ResolveToolCapabilities<TModel extends string> = TModel extends keyof GrokChatModelToolCapabilitiesByName ? NonNullable<GrokChatModelToolCapabilitiesByName[TModel]> : readonly [];
|
|
6
8
|
/**
|
|
7
9
|
* Configuration for Grok text adapter
|
|
8
10
|
*/
|
|
@@ -18,12 +20,12 @@ export type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../
|
|
|
18
20
|
* Tree-shakeable adapter for Grok chat/text completion functionality.
|
|
19
21
|
* Uses OpenAI-compatible Chat Completions API (not Responses API).
|
|
20
22
|
*/
|
|
21
|
-
export declare class GrokTextAdapter<TModel extends (typeof GROK_CHAT_MODELS)[number]
|
|
23
|
+
export declare class GrokTextAdapter<TModel extends (typeof GROK_CHAT_MODELS)[number], TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>, TToolCapabilities extends ReadonlyArray<string> = ResolveToolCapabilities<TModel>> extends BaseTextAdapter<TModel, TProviderOptions, TInputModalities, GrokMessageMetadataByModality, TToolCapabilities> {
|
|
22
24
|
readonly kind: "text";
|
|
23
25
|
readonly name: "grok";
|
|
24
26
|
private client;
|
|
25
27
|
constructor(config: GrokTextConfig, model: TModel);
|
|
26
|
-
chatStream(options: TextOptions<
|
|
28
|
+
chatStream(options: TextOptions<GrokTextProviderOptions>): AsyncIterable<StreamChunk>;
|
|
27
29
|
/**
|
|
28
30
|
* Generate structured output using Grok's JSON Schema response format.
|
|
29
31
|
* Uses stream: false to get the complete response in one call.
|
|
@@ -36,7 +38,7 @@ export declare class GrokTextAdapter<TModel extends (typeof GROK_CHAT_MODELS)[nu
|
|
|
36
38
|
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
37
39
|
* We apply Grok-specific transformations for structured output compatibility.
|
|
38
40
|
*/
|
|
39
|
-
structuredOutput(options: StructuredOutputOptions<
|
|
41
|
+
structuredOutput(options: StructuredOutputOptions<GrokTextProviderOptions>): Promise<StructuredOutputResult<unknown>>;
|
|
40
42
|
private processGrokStreamChunks;
|
|
41
43
|
/**
|
|
42
44
|
* Maps common options to Grok-specific Chat Completions format
|
|
@@ -3,6 +3,7 @@ import { validateTextProviderOptions } from "../text/text-provider-options.js";
|
|
|
3
3
|
import { makeGrokStructuredOutputCompatible, transformNullsToUndefined } from "../utils/schema-converter.js";
|
|
4
4
|
import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
|
|
5
5
|
import { createGrokClient, generateId, getGrokApiKeyFromEnv } from "../utils/client.js";
|
|
6
|
+
const asChunk = (chunk) => chunk;
|
|
6
7
|
class GrokTextAdapter extends BaseTextAdapter {
|
|
7
8
|
constructor(config, model) {
|
|
8
9
|
super({}, model);
|
|
@@ -14,7 +15,8 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
14
15
|
const requestParams = this.mapTextOptionsToGrok(options);
|
|
15
16
|
const timestamp = Date.now();
|
|
16
17
|
const aguiState = {
|
|
17
|
-
runId: generateId(this.name),
|
|
18
|
+
runId: options.runId ?? generateId(this.name),
|
|
19
|
+
threadId: options.threadId ?? generateId(this.name),
|
|
18
20
|
messageId: generateId(this.name),
|
|
19
21
|
timestamp,
|
|
20
22
|
hasEmittedRunStarted: false
|
|
@@ -29,23 +31,26 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
29
31
|
const err = error;
|
|
30
32
|
if (!aguiState.hasEmittedRunStarted) {
|
|
31
33
|
aguiState.hasEmittedRunStarted = true;
|
|
32
|
-
yield {
|
|
34
|
+
yield asChunk({
|
|
33
35
|
type: "RUN_STARTED",
|
|
34
36
|
runId: aguiState.runId,
|
|
37
|
+
threadId: aguiState.threadId,
|
|
35
38
|
model: options.model,
|
|
36
39
|
timestamp
|
|
37
|
-
};
|
|
40
|
+
});
|
|
38
41
|
}
|
|
39
|
-
yield {
|
|
42
|
+
yield asChunk({
|
|
40
43
|
type: "RUN_ERROR",
|
|
41
44
|
runId: aguiState.runId,
|
|
42
45
|
model: options.model,
|
|
43
46
|
timestamp,
|
|
47
|
+
message: err.message || "Unknown error",
|
|
48
|
+
code: err.code,
|
|
44
49
|
error: {
|
|
45
50
|
message: err.message || "Unknown error",
|
|
46
51
|
code: err.code
|
|
47
52
|
}
|
|
48
|
-
};
|
|
53
|
+
});
|
|
49
54
|
console.error(">>> chatStream: Fatal error during response creation <<<");
|
|
50
55
|
console.error(">>> Error message:", err.message);
|
|
51
56
|
console.error(">>> Error stack:", err.stack);
|
|
@@ -116,12 +121,13 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
116
121
|
if (!choice) continue;
|
|
117
122
|
if (!aguiState.hasEmittedRunStarted) {
|
|
118
123
|
aguiState.hasEmittedRunStarted = true;
|
|
119
|
-
yield {
|
|
124
|
+
yield asChunk({
|
|
120
125
|
type: "RUN_STARTED",
|
|
121
126
|
runId: aguiState.runId,
|
|
127
|
+
threadId: aguiState.threadId,
|
|
122
128
|
model: chunk.model || options.model,
|
|
123
129
|
timestamp
|
|
124
|
-
};
|
|
130
|
+
});
|
|
125
131
|
}
|
|
126
132
|
const delta = choice.delta;
|
|
127
133
|
const deltaContent = delta.content;
|
|
@@ -129,23 +135,23 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
129
135
|
if (deltaContent) {
|
|
130
136
|
if (!hasEmittedTextMessageStart) {
|
|
131
137
|
hasEmittedTextMessageStart = true;
|
|
132
|
-
yield {
|
|
138
|
+
yield asChunk({
|
|
133
139
|
type: "TEXT_MESSAGE_START",
|
|
134
140
|
messageId: aguiState.messageId,
|
|
135
141
|
model: chunk.model || options.model,
|
|
136
142
|
timestamp,
|
|
137
143
|
role: "assistant"
|
|
138
|
-
};
|
|
144
|
+
});
|
|
139
145
|
}
|
|
140
146
|
accumulatedContent += deltaContent;
|
|
141
|
-
yield {
|
|
147
|
+
yield asChunk({
|
|
142
148
|
type: "TEXT_MESSAGE_CONTENT",
|
|
143
149
|
messageId: aguiState.messageId,
|
|
144
150
|
model: chunk.model || options.model,
|
|
145
151
|
timestamp,
|
|
146
152
|
delta: deltaContent,
|
|
147
153
|
content: accumulatedContent
|
|
148
|
-
};
|
|
154
|
+
});
|
|
149
155
|
}
|
|
150
156
|
if (deltaToolCalls) {
|
|
151
157
|
for (const toolCallDelta of deltaToolCalls) {
|
|
@@ -170,23 +176,24 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
170
176
|
}
|
|
171
177
|
if (toolCall.id && toolCall.name && !toolCall.started) {
|
|
172
178
|
toolCall.started = true;
|
|
173
|
-
yield {
|
|
179
|
+
yield asChunk({
|
|
174
180
|
type: "TOOL_CALL_START",
|
|
175
181
|
toolCallId: toolCall.id,
|
|
182
|
+
toolCallName: toolCall.name,
|
|
176
183
|
toolName: toolCall.name,
|
|
177
184
|
model: chunk.model || options.model,
|
|
178
185
|
timestamp,
|
|
179
186
|
index
|
|
180
|
-
};
|
|
187
|
+
});
|
|
181
188
|
}
|
|
182
189
|
if (toolCallDelta.function?.arguments && toolCall.started) {
|
|
183
|
-
yield {
|
|
190
|
+
yield asChunk({
|
|
184
191
|
type: "TOOL_CALL_ARGS",
|
|
185
192
|
toolCallId: toolCall.id,
|
|
186
193
|
model: chunk.model || options.model,
|
|
187
194
|
timestamp,
|
|
188
195
|
delta: toolCallDelta.function.arguments
|
|
189
|
-
};
|
|
196
|
+
});
|
|
190
197
|
}
|
|
191
198
|
}
|
|
192
199
|
}
|
|
@@ -199,28 +206,30 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
199
206
|
} catch {
|
|
200
207
|
parsedInput = {};
|
|
201
208
|
}
|
|
202
|
-
yield {
|
|
209
|
+
yield asChunk({
|
|
203
210
|
type: "TOOL_CALL_END",
|
|
204
211
|
toolCallId: toolCall.id,
|
|
212
|
+
toolCallName: toolCall.name,
|
|
205
213
|
toolName: toolCall.name,
|
|
206
214
|
model: chunk.model || options.model,
|
|
207
215
|
timestamp,
|
|
208
216
|
input: parsedInput
|
|
209
|
-
};
|
|
217
|
+
});
|
|
210
218
|
}
|
|
211
219
|
}
|
|
212
220
|
const computedFinishReason = choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0 ? "tool_calls" : "stop";
|
|
213
221
|
if (hasEmittedTextMessageStart) {
|
|
214
|
-
yield {
|
|
222
|
+
yield asChunk({
|
|
215
223
|
type: "TEXT_MESSAGE_END",
|
|
216
224
|
messageId: aguiState.messageId,
|
|
217
225
|
model: chunk.model || options.model,
|
|
218
226
|
timestamp
|
|
219
|
-
};
|
|
227
|
+
});
|
|
220
228
|
}
|
|
221
|
-
yield {
|
|
229
|
+
yield asChunk({
|
|
222
230
|
type: "RUN_FINISHED",
|
|
223
231
|
runId: aguiState.runId,
|
|
232
|
+
threadId: aguiState.threadId,
|
|
224
233
|
model: chunk.model || options.model,
|
|
225
234
|
timestamp,
|
|
226
235
|
usage: chunk.usage ? {
|
|
@@ -229,22 +238,24 @@ class GrokTextAdapter extends BaseTextAdapter {
|
|
|
229
238
|
totalTokens: chunk.usage.total_tokens || 0
|
|
230
239
|
} : void 0,
|
|
231
240
|
finishReason: computedFinishReason
|
|
232
|
-
};
|
|
241
|
+
});
|
|
233
242
|
}
|
|
234
243
|
}
|
|
235
244
|
} catch (error) {
|
|
236
245
|
const err = error;
|
|
237
246
|
console.log("[Grok Adapter] Stream ended with error:", err.message);
|
|
238
|
-
yield {
|
|
247
|
+
yield asChunk({
|
|
239
248
|
type: "RUN_ERROR",
|
|
240
249
|
runId: aguiState.runId,
|
|
241
250
|
model: options.model,
|
|
242
251
|
timestamp,
|
|
252
|
+
message: err.message || "Unknown error occurred",
|
|
253
|
+
code: err.code,
|
|
243
254
|
error: {
|
|
244
255
|
message: err.message || "Unknown error occurred",
|
|
245
256
|
code: err.code
|
|
246
257
|
}
|
|
247
|
-
};
|
|
258
|
+
});
|
|
248
259
|
}
|
|
249
260
|
}
|
|
250
261
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { validateTextProviderOptions } from '../text/text-provider-options'\nimport { convertToolsToProviderFormat } from '../tools'\nimport {\n createGrokClient,\n generateId,\n getGrokApiKeyFromEnv,\n makeGrokStructuredOutputCompatible,\n transformNullsToUndefined,\n} from '../utils'\nimport type {\n GROK_CHAT_MODELS,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type OpenAI_SDK from 'openai'\nimport type {\n ContentPart,\n ModelMessage,\n StreamChunk,\n TextOptions,\n} from '@tanstack/ai'\nimport type { InternalTextProviderOptions } from '../text/text-provider-options'\nimport type {\n GrokImageMetadata,\n GrokMessageMetadataByModality,\n} from '../message-types'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok text adapter\n */\nexport interface GrokTextConfig extends GrokClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Grok Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Grok chat/text completion functionality.\n * Uses OpenAI-compatible Chat Completions API (not Responses API).\n */\nexport class GrokTextAdapter<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n> extends BaseTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>,\n GrokMessageMetadataByModality\n> {\n readonly kind = 'text' as const\n readonly name = 'grok' as const\n\n private client: OpenAI_SDK\n\n constructor(config: GrokTextConfig, model: TModel) {\n super({}, model)\n this.client = createGrokClient(config)\n }\n\n async *chatStream(\n options: TextOptions<ResolveProviderOptions<TModel>>,\n ): AsyncIterable<StreamChunk> {\n const requestParams = this.mapTextOptionsToGrok(options)\n const timestamp = Date.now()\n\n // AG-UI lifecycle tracking (mutable state object for ESLint compatibility)\n const aguiState = {\n runId: generateId(this.name),\n messageId: generateId(this.name),\n timestamp,\n hasEmittedRunStarted: false,\n }\n\n try {\n const stream = await this.client.chat.completions.create({\n ...requestParams,\n stream: true,\n })\n\n yield* this.processGrokStreamChunks(stream, options, aguiState)\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n\n // Emit RUN_STARTED if not yet emitted\n if (!aguiState.hasEmittedRunStarted) {\n aguiState.hasEmittedRunStarted = true\n yield {\n type: 'RUN_STARTED',\n runId: aguiState.runId,\n model: options.model,\n timestamp,\n }\n }\n\n // Emit AG-UI RUN_ERROR\n yield {\n type: 'RUN_ERROR',\n runId: aguiState.runId,\n model: options.model,\n timestamp,\n error: {\n message: err.message || 'Unknown error',\n code: err.code,\n },\n }\n\n console.error('>>> chatStream: Fatal error during response creation <<<')\n console.error('>>> Error message:', err.message)\n console.error('>>> Error stack:', err.stack)\n console.error('>>> Full error:', err)\n }\n }\n\n /**\n * Generate structured output using Grok's JSON Schema response format.\n * Uses stream: false to get the complete response in one call.\n *\n * Grok has strict requirements for structured output (via OpenAI-compatible API):\n * - All properties must be in the `required` array\n * - Optional fields should have null added to their type union\n * - additionalProperties must be false for all objects\n *\n * The outputSchema is already JSON Schema (converted in the ai layer).\n * We apply Grok-specific transformations for structured output compatibility.\n */\n async structuredOutput(\n options: StructuredOutputOptions<ResolveProviderOptions<TModel>>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n const requestParams = this.mapTextOptionsToGrok(chatOptions)\n\n // Apply Grok-specific transformations for structured output compatibility\n const jsonSchema = makeGrokStructuredOutputCompatible(\n outputSchema,\n outputSchema.required || [],\n )\n\n try {\n const response = await this.client.chat.completions.create({\n ...requestParams,\n stream: false,\n response_format: {\n type: 'json_schema',\n json_schema: {\n name: 'structured_output',\n schema: jsonSchema,\n strict: true,\n },\n },\n })\n\n // Extract text content from the response\n const rawText = response.choices[0]?.message.content || ''\n\n // Parse the JSON response\n let parsed: unknown\n try {\n parsed = JSON.parse(rawText)\n } catch {\n throw new Error(\n `Failed to parse structured output as JSON. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? '...' : ''}`,\n )\n }\n\n // Transform null values to undefined to match original Zod schema expectations\n // Grok returns null for optional fields we made nullable in the schema\n const transformed = transformNullsToUndefined(parsed)\n\n return {\n data: transformed,\n rawText,\n }\n } catch (error: unknown) {\n const err = error as Error\n console.error('>>> structuredOutput: Error during response creation <<<')\n console.error('>>> Error message:', err.message)\n throw error\n }\n }\n\n private async *processGrokStreamChunks(\n stream: AsyncIterable<OpenAI_SDK.Chat.Completions.ChatCompletionChunk>,\n options: TextOptions,\n aguiState: {\n runId: string\n messageId: string\n timestamp: number\n hasEmittedRunStarted: boolean\n },\n ): AsyncIterable<StreamChunk> {\n let accumulatedContent = ''\n const timestamp = aguiState.timestamp\n let hasEmittedTextMessageStart = false\n\n // Track tool calls being streamed (arguments come in chunks)\n const toolCallsInProgress = new Map<\n number,\n {\n id: string\n name: string\n arguments: string\n started: boolean // Track if TOOL_CALL_START has been emitted\n }\n >()\n\n try {\n for await (const chunk of stream) {\n const choice = chunk.choices[0]\n\n if (!choice) continue\n\n // Emit RUN_STARTED on first chunk\n if (!aguiState.hasEmittedRunStarted) {\n aguiState.hasEmittedRunStarted = true\n yield {\n type: 'RUN_STARTED',\n runId: aguiState.runId,\n model: chunk.model || options.model,\n timestamp,\n }\n }\n\n const delta = choice.delta\n const deltaContent = delta.content\n const deltaToolCalls = delta.tool_calls\n\n // Handle content delta\n if (deltaContent) {\n // Emit TEXT_MESSAGE_START on first text content\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield {\n type: 'TEXT_MESSAGE_START',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n role: 'assistant',\n }\n }\n\n accumulatedContent += deltaContent\n\n // Emit AG-UI TEXT_MESSAGE_CONTENT\n yield {\n type: 'TEXT_MESSAGE_CONTENT',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n delta: deltaContent,\n content: accumulatedContent,\n }\n }\n\n // Handle tool calls - they come in as deltas\n if (deltaToolCalls) {\n for (const toolCallDelta of deltaToolCalls) {\n const index = toolCallDelta.index\n\n // Initialize or update the tool call in progress\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n id: toolCallDelta.id || '',\n name: toolCallDelta.function?.name || '',\n arguments: '',\n started: false,\n })\n }\n\n const toolCall = toolCallsInProgress.get(index)!\n\n // Update with any new data from the delta\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments\n }\n\n // Emit TOOL_CALL_START when we have id and name\n if (toolCall.id && toolCall.name && !toolCall.started) {\n toolCall.started = true\n yield {\n type: 'TOOL_CALL_START',\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n model: chunk.model || options.model,\n timestamp,\n index,\n }\n }\n\n // Emit TOOL_CALL_ARGS for argument deltas\n if (toolCallDelta.function?.arguments && toolCall.started) {\n yield {\n type: 'TOOL_CALL_ARGS',\n toolCallId: toolCall.id,\n model: chunk.model || options.model,\n timestamp,\n delta: toolCallDelta.function.arguments,\n }\n }\n }\n }\n\n // Handle finish reason\n if (choice.finish_reason) {\n // Emit all completed tool calls\n if (\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ) {\n for (const [, toolCall] of toolCallsInProgress) {\n // Parse arguments for TOOL_CALL_END\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.arguments\n ? JSON.parse(toolCall.arguments)\n : {}\n } catch {\n parsedInput = {}\n }\n\n // Emit AG-UI TOOL_CALL_END\n yield {\n type: 'TOOL_CALL_END',\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n model: chunk.model || options.model,\n timestamp,\n input: parsedInput,\n }\n }\n }\n\n const computedFinishReason =\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ? 'tool_calls'\n : 'stop'\n\n // Emit TEXT_MESSAGE_END if we had text content\n if (hasEmittedTextMessageStart) {\n yield {\n type: 'TEXT_MESSAGE_END',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n }\n }\n\n // Emit AG-UI RUN_FINISHED\n yield {\n type: 'RUN_FINISHED',\n runId: aguiState.runId,\n model: chunk.model || options.model,\n timestamp,\n usage: chunk.usage\n ? {\n promptTokens: chunk.usage.prompt_tokens || 0,\n completionTokens: chunk.usage.completion_tokens || 0,\n totalTokens: chunk.usage.total_tokens || 0,\n }\n : undefined,\n finishReason: computedFinishReason,\n }\n }\n }\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n console.log('[Grok Adapter] Stream ended with error:', err.message)\n\n // Emit AG-UI RUN_ERROR\n yield {\n type: 'RUN_ERROR',\n runId: aguiState.runId,\n model: options.model,\n timestamp,\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code,\n },\n }\n }\n }\n\n /**\n * Maps common options to Grok-specific Chat Completions format\n */\n private mapTextOptionsToGrok(\n options: TextOptions,\n ): OpenAI_SDK.Chat.Completions.ChatCompletionCreateParamsStreaming {\n const modelOptions = options.modelOptions as\n | Omit<\n InternalTextProviderOptions,\n 'max_tokens' | 'tools' | 'temperature' | 'input' | 'top_p'\n >\n | undefined\n\n if (modelOptions) {\n validateTextProviderOptions({\n ...modelOptions,\n model: options.model,\n })\n }\n\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n // Build messages array with system prompts\n const messages: Array<OpenAI_SDK.Chat.Completions.ChatCompletionMessageParam> =\n []\n\n // Add system prompts first\n if (options.systemPrompts && options.systemPrompts.length > 0) {\n messages.push({\n role: 'system',\n content: options.systemPrompts.join('\\n'),\n })\n }\n\n // Convert messages\n for (const message of options.messages) {\n messages.push(this.convertMessageToGrok(message))\n }\n\n return {\n model: options.model,\n messages,\n temperature: options.temperature,\n max_tokens: options.maxTokens,\n top_p: options.topP,\n tools: tools as Array<OpenAI_SDK.Chat.Completions.ChatCompletionTool>,\n stream: true,\n stream_options: { include_usage: true },\n }\n }\n\n private convertMessageToGrok(\n message: ModelMessage,\n ): OpenAI_SDK.Chat.Completions.ChatCompletionMessageParam {\n // Handle tool messages\n if (message.role === 'tool') {\n return {\n role: 'tool',\n tool_call_id: message.toolCallId || '',\n content:\n typeof message.content === 'string'\n ? message.content\n : JSON.stringify(message.content),\n }\n }\n\n // Handle assistant messages\n if (message.role === 'assistant') {\n const toolCalls = message.toolCalls?.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.function.name,\n arguments:\n typeof tc.function.arguments === 'string'\n ? tc.function.arguments\n : JSON.stringify(tc.function.arguments),\n },\n }))\n\n return {\n role: 'assistant',\n content: this.extractTextContent(message.content),\n ...(toolCalls && toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n }\n }\n\n // Handle user messages - support multimodal content\n const contentParts = this.normalizeContent(message.content)\n\n // If only text, use simple string format\n if (contentParts.length === 1 && contentParts[0]?.type === 'text') {\n return {\n role: 'user',\n content: contentParts[0].content,\n }\n }\n\n // Otherwise, use array format for multimodal\n const parts: Array<OpenAI_SDK.Chat.Completions.ChatCompletionContentPart> =\n []\n for (const part of contentParts) {\n if (part.type === 'text') {\n parts.push({ type: 'text', text: part.content })\n } else if (part.type === 'image') {\n const imageMetadata = part.metadata as GrokImageMetadata | undefined\n // For base64 data, construct a data URI using the mimeType from source\n const imageValue = part.source.value\n const imageUrl =\n part.source.type === 'data' && !imageValue.startsWith('data:')\n ? `data:${part.source.mimeType};base64,${imageValue}`\n : imageValue\n parts.push({\n type: 'image_url',\n image_url: {\n url: imageUrl,\n detail: imageMetadata?.detail || 'auto',\n },\n })\n }\n }\n\n return {\n role: 'user',\n content: parts.length > 0 ? parts : '',\n }\n }\n\n /**\n * Normalizes message content to an array of ContentPart.\n * Handles backward compatibility with string content.\n */\n private normalizeContent(\n content: string | null | Array<ContentPart>,\n ): Array<ContentPart> {\n if (content === null) {\n return []\n }\n if (typeof content === 'string') {\n return [{ type: 'text', content: content }]\n }\n return content\n }\n\n /**\n * Extracts text content from a content value that may be string, null, or ContentPart array.\n */\n private extractTextContent(\n content: string | null | Array<ContentPart>,\n ): string {\n if (content === null) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n // It's an array of ContentPart\n return content\n .filter((p) => p.type === 'text')\n .map((p) => p.content)\n .join('')\n }\n}\n\n/**\n * Creates a Grok text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokText('grok-3', \"xai-...\");\n * // adapter has type-safe providerOptions for grok-3\n * ```\n */\nexport function createGrokText<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n return new GrokTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok text adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokText('grok-3');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function grokText<TModel extends (typeof GROK_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokText(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { validateTextProviderOptions } from '../text/text-provider-options'\nimport { convertToolsToProviderFormat } from '../tools'\nimport {\n createGrokClient,\n generateId,\n getGrokApiKeyFromEnv,\n makeGrokStructuredOutputCompatible,\n transformNullsToUndefined,\n} from '../utils'\nimport type {\n GROK_CHAT_MODELS,\n GrokChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type OpenAI_SDK from 'openai'\nimport type {\n ContentPart,\n Modality,\n ModelMessage,\n StreamChunk,\n TextOptions,\n} from '@tanstack/ai'\nimport type {\n ExternalTextProviderOptions as GrokTextProviderOptions,\n InternalTextProviderOptions,\n} from '../text/text-provider-options'\nimport type {\n GrokImageMetadata,\n GrokMessageMetadataByModality,\n} from '../message-types'\nimport type { GrokClientConfig } from '../utils'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GrokChatModelToolCapabilitiesByName\n ? NonNullable<GrokChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/** Cast an event object to StreamChunk. Adapters construct events with string\n * literal types which are structurally compatible with the EventType enum. */\nconst asChunk = (chunk: Record<string, unknown>) =>\n chunk as unknown as StreamChunk\n\n/**\n * Configuration for Grok text adapter\n */\nexport interface GrokTextConfig extends GrokClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Grok Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Grok chat/text completion functionality.\n * Uses OpenAI-compatible Chat Completions API (not Responses API).\n */\nexport class GrokTextAdapter<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends BaseTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n GrokMessageMetadataByModality,\n TToolCapabilities\n> {\n readonly kind = 'text' as const\n readonly name = 'grok' as const\n\n private client: OpenAI_SDK\n\n constructor(config: GrokTextConfig, model: TModel) {\n super({}, model)\n this.client = createGrokClient(config)\n }\n\n async *chatStream(\n options: TextOptions<GrokTextProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const requestParams = this.mapTextOptionsToGrok(options)\n const timestamp = Date.now()\n\n // AG-UI lifecycle tracking (mutable state object for ESLint compatibility)\n const aguiState = {\n runId: options.runId ?? generateId(this.name),\n threadId: options.threadId ?? generateId(this.name),\n messageId: generateId(this.name),\n timestamp,\n hasEmittedRunStarted: false,\n }\n\n try {\n const stream = await this.client.chat.completions.create({\n ...requestParams,\n stream: true,\n })\n\n yield* this.processGrokStreamChunks(stream, options, aguiState)\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n\n // Emit RUN_STARTED if not yet emitted\n if (!aguiState.hasEmittedRunStarted) {\n aguiState.hasEmittedRunStarted = true\n yield asChunk({\n type: 'RUN_STARTED',\n runId: aguiState.runId,\n threadId: aguiState.threadId,\n model: options.model,\n timestamp,\n })\n }\n\n // Emit AG-UI RUN_ERROR\n yield asChunk({\n type: 'RUN_ERROR',\n runId: aguiState.runId,\n model: options.model,\n timestamp,\n message: err.message || 'Unknown error',\n code: err.code,\n error: {\n message: err.message || 'Unknown error',\n code: err.code,\n },\n })\n\n console.error('>>> chatStream: Fatal error during response creation <<<')\n console.error('>>> Error message:', err.message)\n console.error('>>> Error stack:', err.stack)\n console.error('>>> Full error:', err)\n }\n }\n\n /**\n * Generate structured output using Grok's JSON Schema response format.\n * Uses stream: false to get the complete response in one call.\n *\n * Grok has strict requirements for structured output (via OpenAI-compatible API):\n * - All properties must be in the `required` array\n * - Optional fields should have null added to their type union\n * - additionalProperties must be false for all objects\n *\n * The outputSchema is already JSON Schema (converted in the ai layer).\n * We apply Grok-specific transformations for structured output compatibility.\n */\n async structuredOutput(\n options: StructuredOutputOptions<GrokTextProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n const requestParams = this.mapTextOptionsToGrok(chatOptions)\n\n // Apply Grok-specific transformations for structured output compatibility\n const jsonSchema = makeGrokStructuredOutputCompatible(\n outputSchema,\n outputSchema.required || [],\n )\n\n try {\n const response = await this.client.chat.completions.create({\n ...requestParams,\n stream: false,\n response_format: {\n type: 'json_schema',\n json_schema: {\n name: 'structured_output',\n schema: jsonSchema,\n strict: true,\n },\n },\n })\n\n // Extract text content from the response\n const rawText = response.choices[0]?.message.content || ''\n\n // Parse the JSON response\n let parsed: unknown\n try {\n parsed = JSON.parse(rawText)\n } catch {\n throw new Error(\n `Failed to parse structured output as JSON. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? '...' : ''}`,\n )\n }\n\n // Transform null values to undefined to match original Zod schema expectations\n // Grok returns null for optional fields we made nullable in the schema\n const transformed = transformNullsToUndefined(parsed)\n\n return {\n data: transformed,\n rawText,\n }\n } catch (error: unknown) {\n const err = error as Error\n console.error('>>> structuredOutput: Error during response creation <<<')\n console.error('>>> Error message:', err.message)\n throw error\n }\n }\n\n private async *processGrokStreamChunks(\n stream: AsyncIterable<OpenAI_SDK.Chat.Completions.ChatCompletionChunk>,\n options: TextOptions,\n aguiState: {\n runId: string\n threadId: string\n messageId: string\n timestamp: number\n hasEmittedRunStarted: boolean\n },\n ): AsyncIterable<StreamChunk> {\n let accumulatedContent = ''\n const timestamp = aguiState.timestamp\n let hasEmittedTextMessageStart = false\n\n // Track tool calls being streamed (arguments come in chunks)\n const toolCallsInProgress = new Map<\n number,\n {\n id: string\n name: string\n arguments: string\n started: boolean // Track if TOOL_CALL_START has been emitted\n }\n >()\n\n try {\n for await (const chunk of stream) {\n const choice = chunk.choices[0]\n\n if (!choice) continue\n\n // Emit RUN_STARTED on first chunk\n if (!aguiState.hasEmittedRunStarted) {\n aguiState.hasEmittedRunStarted = true\n yield asChunk({\n type: 'RUN_STARTED',\n runId: aguiState.runId,\n threadId: aguiState.threadId,\n model: chunk.model || options.model,\n timestamp,\n })\n }\n\n const delta = choice.delta\n const deltaContent = delta.content\n const deltaToolCalls = delta.tool_calls\n\n // Handle content delta\n if (deltaContent) {\n // Emit TEXT_MESSAGE_START on first text content\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield asChunk({\n type: 'TEXT_MESSAGE_START',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n role: 'assistant',\n })\n }\n\n accumulatedContent += deltaContent\n\n // Emit AG-UI TEXT_MESSAGE_CONTENT\n yield asChunk({\n type: 'TEXT_MESSAGE_CONTENT',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n delta: deltaContent,\n content: accumulatedContent,\n })\n }\n\n // Handle tool calls - they come in as deltas\n if (deltaToolCalls) {\n for (const toolCallDelta of deltaToolCalls) {\n const index = toolCallDelta.index\n\n // Initialize or update the tool call in progress\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n id: toolCallDelta.id || '',\n name: toolCallDelta.function?.name || '',\n arguments: '',\n started: false,\n })\n }\n\n const toolCall = toolCallsInProgress.get(index)!\n\n // Update with any new data from the delta\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments\n }\n\n // Emit TOOL_CALL_START when we have id and name\n if (toolCall.id && toolCall.name && !toolCall.started) {\n toolCall.started = true\n yield asChunk({\n type: 'TOOL_CALL_START',\n toolCallId: toolCall.id,\n toolCallName: toolCall.name,\n toolName: toolCall.name,\n model: chunk.model || options.model,\n timestamp,\n index,\n })\n }\n\n // Emit TOOL_CALL_ARGS for argument deltas\n if (toolCallDelta.function?.arguments && toolCall.started) {\n yield asChunk({\n type: 'TOOL_CALL_ARGS',\n toolCallId: toolCall.id,\n model: chunk.model || options.model,\n timestamp,\n delta: toolCallDelta.function.arguments,\n })\n }\n }\n }\n\n // Handle finish reason\n if (choice.finish_reason) {\n // Emit all completed tool calls\n if (\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ) {\n for (const [, toolCall] of toolCallsInProgress) {\n // Parse arguments for TOOL_CALL_END\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.arguments\n ? JSON.parse(toolCall.arguments)\n : {}\n } catch {\n parsedInput = {}\n }\n\n // Emit AG-UI TOOL_CALL_END\n yield asChunk({\n type: 'TOOL_CALL_END',\n toolCallId: toolCall.id,\n toolCallName: toolCall.name,\n toolName: toolCall.name,\n model: chunk.model || options.model,\n timestamp,\n input: parsedInput,\n })\n }\n }\n\n const computedFinishReason =\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ? 'tool_calls'\n : 'stop'\n\n // Emit TEXT_MESSAGE_END if we had text content\n if (hasEmittedTextMessageStart) {\n yield asChunk({\n type: 'TEXT_MESSAGE_END',\n messageId: aguiState.messageId,\n model: chunk.model || options.model,\n timestamp,\n })\n }\n\n // Emit AG-UI RUN_FINISHED\n yield asChunk({\n type: 'RUN_FINISHED',\n runId: aguiState.runId,\n threadId: aguiState.threadId,\n model: chunk.model || options.model,\n timestamp,\n usage: chunk.usage\n ? {\n promptTokens: chunk.usage.prompt_tokens || 0,\n completionTokens: chunk.usage.completion_tokens || 0,\n totalTokens: chunk.usage.total_tokens || 0,\n }\n : undefined,\n finishReason: computedFinishReason,\n })\n }\n }\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n console.log('[Grok Adapter] Stream ended with error:', err.message)\n\n // Emit AG-UI RUN_ERROR\n yield asChunk({\n type: 'RUN_ERROR',\n runId: aguiState.runId,\n model: options.model,\n timestamp,\n message: err.message || 'Unknown error occurred',\n code: err.code,\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code,\n },\n })\n }\n }\n\n /**\n * Maps common options to Grok-specific Chat Completions format\n */\n private mapTextOptionsToGrok(\n options: TextOptions,\n ): OpenAI_SDK.Chat.Completions.ChatCompletionCreateParamsStreaming {\n const modelOptions = options.modelOptions as\n | Omit<\n InternalTextProviderOptions,\n 'max_tokens' | 'tools' | 'temperature' | 'input' | 'top_p'\n >\n | undefined\n\n if (modelOptions) {\n validateTextProviderOptions({\n ...modelOptions,\n model: options.model,\n })\n }\n\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n // Build messages array with system prompts\n const messages: Array<OpenAI_SDK.Chat.Completions.ChatCompletionMessageParam> =\n []\n\n // Add system prompts first\n if (options.systemPrompts && options.systemPrompts.length > 0) {\n messages.push({\n role: 'system',\n content: options.systemPrompts.join('\\n'),\n })\n }\n\n // Convert messages\n for (const message of options.messages) {\n messages.push(this.convertMessageToGrok(message))\n }\n\n return {\n model: options.model,\n messages,\n temperature: options.temperature,\n max_tokens: options.maxTokens,\n top_p: options.topP,\n tools: tools as Array<OpenAI_SDK.Chat.Completions.ChatCompletionTool>,\n stream: true,\n stream_options: { include_usage: true },\n }\n }\n\n private convertMessageToGrok(\n message: ModelMessage,\n ): OpenAI_SDK.Chat.Completions.ChatCompletionMessageParam {\n // Handle tool messages\n if (message.role === 'tool') {\n return {\n role: 'tool',\n tool_call_id: message.toolCallId || '',\n content:\n typeof message.content === 'string'\n ? message.content\n : JSON.stringify(message.content),\n }\n }\n\n // Handle assistant messages\n if (message.role === 'assistant') {\n const toolCalls = message.toolCalls?.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.function.name,\n arguments:\n typeof tc.function.arguments === 'string'\n ? tc.function.arguments\n : JSON.stringify(tc.function.arguments),\n },\n }))\n\n return {\n role: 'assistant',\n content: this.extractTextContent(message.content),\n ...(toolCalls && toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n }\n }\n\n // Handle user messages - support multimodal content\n const contentParts = this.normalizeContent(message.content)\n\n // If only text, use simple string format\n if (contentParts.length === 1 && contentParts[0]?.type === 'text') {\n return {\n role: 'user',\n content: contentParts[0].content,\n }\n }\n\n // Otherwise, use array format for multimodal\n const parts: Array<OpenAI_SDK.Chat.Completions.ChatCompletionContentPart> =\n []\n for (const part of contentParts) {\n if (part.type === 'text') {\n parts.push({ type: 'text', text: part.content })\n } else if (part.type === 'image') {\n const imageMetadata = part.metadata as GrokImageMetadata | undefined\n // For base64 data, construct a data URI using the mimeType from source\n const imageValue = part.source.value\n const imageUrl =\n part.source.type === 'data' && !imageValue.startsWith('data:')\n ? `data:${part.source.mimeType};base64,${imageValue}`\n : imageValue\n parts.push({\n type: 'image_url',\n image_url: {\n url: imageUrl,\n detail: imageMetadata?.detail || 'auto',\n },\n })\n }\n }\n\n return {\n role: 'user',\n content: parts.length > 0 ? parts : '',\n }\n }\n\n /**\n * Normalizes message content to an array of ContentPart.\n * Handles backward compatibility with string content.\n */\n private normalizeContent(\n content: string | null | Array<ContentPart>,\n ): Array<ContentPart> {\n if (content === null) {\n return []\n }\n if (typeof content === 'string') {\n return [{ type: 'text', content: content }]\n }\n return content\n }\n\n /**\n * Extracts text content from a content value that may be string, null, or ContentPart array.\n */\n private extractTextContent(\n content: string | null | Array<ContentPart>,\n ): string {\n if (content === null) {\n return ''\n }\n if (typeof content === 'string') {\n return content\n }\n // It's an array of ContentPart\n return content\n .filter((p) => p.type === 'text')\n .map((p) => p.content)\n .join('')\n }\n}\n\n/**\n * Creates a Grok text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokText('grok-3', \"xai-...\");\n * // adapter has type-safe providerOptions for grok-3\n * ```\n */\nexport function createGrokText<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n return new GrokTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok text adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokText('grok-3');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function grokText<TModel extends (typeof GROK_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokText(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export { GrokTextAdapter, createGrokText, grokText, type GrokTextConfig, type Gr
|
|
|
2
2
|
export { GrokSummarizeAdapter, createGrokSummarize, grokSummarize, type GrokSummarizeConfig, type GrokSummarizeProviderOptions, type GrokSummarizeModel, } from './adapters/summarize.js';
|
|
3
3
|
export { GrokImageAdapter, createGrokImage, grokImage, type GrokImageConfig, } from './adapters/image.js';
|
|
4
4
|
export type { GrokImageProviderOptions, GrokImageModelProviderOptionsByName, } from './image/image-provider-options.js';
|
|
5
|
-
export type { GrokChatModelProviderOptionsByName, GrokModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, GrokChatModel, GrokImageModel, } from './model-meta.js';
|
|
5
|
+
export type { GrokChatModelProviderOptionsByName, GrokChatModelToolCapabilitiesByName, GrokModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, GrokChatModel, GrokImageModel, } from './model-meta.js';
|
|
6
6
|
export { GROK_CHAT_MODELS, GROK_IMAGE_MODELS } from './model-meta.js';
|
|
7
7
|
export type { GrokTextMetadata, GrokImageMetadata, GrokAudioMetadata, GrokVideoMetadata, GrokDocumentMetadata, GrokMessageMetadataByModality, } from './message-types.js';
|
package/dist/esm/model-meta.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare const GROK_4_1_FAST_REASONING: {
|
|
|
5
5
|
readonly input: ["text", "image"];
|
|
6
6
|
readonly output: ["text"];
|
|
7
7
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
8
|
+
readonly tools: readonly [];
|
|
8
9
|
};
|
|
9
10
|
readonly pricing: {
|
|
10
11
|
readonly input: {
|
|
@@ -23,6 +24,7 @@ declare const GROK_4_1_FAST_NON_REASONING: {
|
|
|
23
24
|
readonly input: ["text", "image"];
|
|
24
25
|
readonly output: ["text"];
|
|
25
26
|
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
27
|
+
readonly tools: readonly [];
|
|
26
28
|
};
|
|
27
29
|
readonly pricing: {
|
|
28
30
|
readonly input: {
|
|
@@ -41,6 +43,7 @@ declare const GROK_CODE_FAST_1: {
|
|
|
41
43
|
readonly input: ["text"];
|
|
42
44
|
readonly output: ["text"];
|
|
43
45
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
46
|
+
readonly tools: readonly [];
|
|
44
47
|
};
|
|
45
48
|
readonly pricing: {
|
|
46
49
|
readonly input: {
|
|
@@ -59,6 +62,7 @@ declare const GROK_4_FAST_REASONING: {
|
|
|
59
62
|
readonly input: ["text", "image"];
|
|
60
63
|
readonly output: ["text"];
|
|
61
64
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
65
|
+
readonly tools: readonly [];
|
|
62
66
|
};
|
|
63
67
|
readonly pricing: {
|
|
64
68
|
readonly input: {
|
|
@@ -77,6 +81,7 @@ declare const GROK_4_FAST_NON_REASONING: {
|
|
|
77
81
|
readonly input: ["text", "image"];
|
|
78
82
|
readonly output: ["text"];
|
|
79
83
|
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
84
|
+
readonly tools: readonly [];
|
|
80
85
|
};
|
|
81
86
|
readonly pricing: {
|
|
82
87
|
readonly input: {
|
|
@@ -95,6 +100,7 @@ declare const GROK_4: {
|
|
|
95
100
|
readonly input: ["text", "image"];
|
|
96
101
|
readonly output: ["text"];
|
|
97
102
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
103
|
+
readonly tools: readonly [];
|
|
98
104
|
};
|
|
99
105
|
readonly pricing: {
|
|
100
106
|
readonly input: {
|
|
@@ -113,6 +119,7 @@ declare const GROK_3_MINI: {
|
|
|
113
119
|
readonly input: ["text"];
|
|
114
120
|
readonly output: ["text"];
|
|
115
121
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
122
|
+
readonly tools: readonly [];
|
|
116
123
|
};
|
|
117
124
|
readonly pricing: {
|
|
118
125
|
readonly input: {
|
|
@@ -131,6 +138,7 @@ declare const GROK_3: {
|
|
|
131
138
|
readonly input: ["text"];
|
|
132
139
|
readonly output: ["text"];
|
|
133
140
|
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
141
|
+
readonly tools: readonly [];
|
|
134
142
|
};
|
|
135
143
|
readonly pricing: {
|
|
136
144
|
readonly input: {
|
|
@@ -149,6 +157,7 @@ declare const GROK_2_VISION: {
|
|
|
149
157
|
readonly input: ["text", "image"];
|
|
150
158
|
readonly output: ["text"];
|
|
151
159
|
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
160
|
+
readonly tools: readonly [];
|
|
152
161
|
};
|
|
153
162
|
readonly pricing: {
|
|
154
163
|
readonly input: {
|
|
@@ -170,6 +179,7 @@ declare const GROK_4_20: {
|
|
|
170
179
|
readonly input: ["text", "image", "document"];
|
|
171
180
|
readonly output: ["text"];
|
|
172
181
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
182
|
+
readonly tools: readonly [];
|
|
173
183
|
};
|
|
174
184
|
readonly pricing: {
|
|
175
185
|
readonly input: {
|
|
@@ -188,6 +198,7 @@ declare const GROK_4_20_MULTI_AGENT: {
|
|
|
188
198
|
readonly input: ["text", "image", "document"];
|
|
189
199
|
readonly output: ["text"];
|
|
190
200
|
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
201
|
+
readonly tools: readonly [];
|
|
191
202
|
};
|
|
192
203
|
readonly pricing: {
|
|
193
204
|
readonly input: {
|
|
@@ -230,6 +241,25 @@ export type GrokModelInputModalitiesByName = {
|
|
|
230
241
|
export type GrokChatModelProviderOptionsByName = {
|
|
231
242
|
[K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions;
|
|
232
243
|
};
|
|
244
|
+
/**
|
|
245
|
+
* Type-only map from Grok chat model name to its supported provider tools.
|
|
246
|
+
* Grok exposes no provider-specific tool factories, so every model gets an
|
|
247
|
+
* empty tuple. This ensures that passing an Anthropic/OpenAI ProviderTool to
|
|
248
|
+
* a Grok adapter produces a compile-time type error.
|
|
249
|
+
*/
|
|
250
|
+
export type GrokChatModelToolCapabilitiesByName = {
|
|
251
|
+
[GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.tools;
|
|
252
|
+
[GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.tools;
|
|
253
|
+
[GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.tools;
|
|
254
|
+
[GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.tools;
|
|
255
|
+
[GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.tools;
|
|
256
|
+
[GROK_4.name]: typeof GROK_4.supports.tools;
|
|
257
|
+
[GROK_3.name]: typeof GROK_3.supports.tools;
|
|
258
|
+
[GROK_3_MINI.name]: typeof GROK_3_MINI.supports.tools;
|
|
259
|
+
[GROK_2_VISION.name]: typeof GROK_2_VISION.supports.tools;
|
|
260
|
+
[GROK_4_20.name]: typeof GROK_4_20.supports.tools;
|
|
261
|
+
[GROK_4_20_MULTI_AGENT.name]: typeof GROK_4_20_MULTI_AGENT.supports.tools;
|
|
262
|
+
};
|
|
233
263
|
/**
|
|
234
264
|
* Grok-specific provider options
|
|
235
265
|
* Based on OpenAI-compatible API options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-meta.js","sources":["../../src/model-meta.ts"],"sourcesContent":["/**\n * Model metadata interface for documentation and type inference\n */\ninterface ModelMeta {\n name: string\n supports: {\n input: Array<'text' | 'image' | 'audio' | 'video' | 'document'>\n output: Array<'text' | 'image' | 'audio' | 'video'>\n capabilities?: Array<'reasoning' | 'tool_calling' | 'structured_outputs'>\n }\n max_input_tokens?: number\n max_output_tokens?: number\n context_window?: number\n knowledge_cutoff?: string\n pricing?: {\n input: {\n normal: number\n cached?: number\n }\n output: {\n normal: number\n }\n }\n}\n\nconst GROK_4_1_FAST_REASONING = {\n name: 'grok-4-1-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_1_FAST_NON_REASONING = {\n name: 'grok-4-1-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_CODE_FAST_1 = {\n name: 'grok-code-fast-1',\n context_window: 256_000,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.02,\n },\n output: {\n normal: 1.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_REASONING = {\n name: 'grok-4-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_NON_REASONING = {\n name: 'grok-4-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4 = {\n name: 'grok-4',\n context_window: 256_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3_MINI = {\n name: 'grok-3-mini',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.3,\n cached: 0.075,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3 = {\n name: 'grok-3',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_VISION = {\n name: 'grok-2-vision-1212',\n context_window: 32_768,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 2,\n },\n output: {\n normal: 10,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_IMAGE = {\n name: 'grok-2-image-1212',\n supports: {\n input: ['text'],\n output: ['image'],\n },\n pricing: {\n input: {\n normal: 0.07,\n },\n output: {\n normal: 0.07,\n },\n },\n} as const satisfies ModelMeta\n\n/**\n * Grok Chat Models\n * Based on xAI's available models as of 2025\n */\nconst GROK_4_20 = {\n name: 'grok-4.20',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image', 'document'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 2,\n cached: 0.2,\n },\n output: {\n normal: 6,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_20_MULTI_AGENT = {\n name: 'grok-4.20-multi-agent',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image', 'document'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 2,\n cached: 0.2,\n },\n output: {\n normal: 6,\n },\n },\n} as const satisfies ModelMeta\n\nexport const GROK_CHAT_MODELS = [\n GROK_4_1_FAST_REASONING.name,\n GROK_4_1_FAST_NON_REASONING.name,\n GROK_CODE_FAST_1.name,\n GROK_4_FAST_REASONING.name,\n GROK_4_FAST_NON_REASONING.name,\n GROK_4.name,\n GROK_3.name,\n GROK_3_MINI.name,\n GROK_2_VISION.name,\n\n GROK_4_20.name,\n GROK_4_20_MULTI_AGENT.name,\n] as const\n\n/**\n * Grok Image Generation Models\n */\nexport const GROK_IMAGE_MODELS = [GROK_2_IMAGE.name] as const\n\nexport type GrokChatModel = (typeof GROK_CHAT_MODELS)[number]\nexport type GrokImageModel = (typeof GROK_IMAGE_MODELS)[number]\n\n/**\n * Type-only map from Grok chat model name to its supported input modalities.\n * Used for type inference when constructing multimodal messages.\n */\nexport type GrokModelInputModalitiesByName = {\n [GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.input\n [GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.input\n [GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.input\n [GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.input\n [GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.input\n [GROK_4.name]: typeof GROK_4.supports.input\n [GROK_3.name]: typeof GROK_3.supports.input\n [GROK_3_MINI.name]: typeof GROK_3_MINI.supports.input\n [GROK_2_VISION.name]: typeof GROK_2_VISION.supports.input\n [GROK_4_20.name]: typeof GROK_4_20.supports.input\n [GROK_4_20_MULTI_AGENT.name]: typeof GROK_4_20_MULTI_AGENT.supports.input\n}\n\n/**\n * Type-only map from Grok chat model name to its provider options type.\n * Since Grok uses OpenAI-compatible API, we reuse OpenAI provider options.\n */\nexport type GrokChatModelProviderOptionsByName = {\n [K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions\n}\n\n/**\n * Grok-specific provider options\n * Based on OpenAI-compatible API options\n */\nexport interface GrokProviderOptions {\n /** Temperature for response generation (0-2) */\n temperature?: number\n /** Maximum tokens in the response */\n max_tokens?: number\n /** Top-p sampling parameter */\n top_p?: number\n /** Frequency penalty (-2.0 to 2.0) */\n frequency_penalty?: number\n /** Presence penalty (-2.0 to 2.0) */\n presence_penalty?: number\n /** Stop sequences */\n stop?: string | Array<string>\n /** A unique identifier representing your end-user */\n user?: string\n}\n\n// ===========================\n// Type Resolution Helpers\n// ===========================\n\n/**\n * Resolve provider options for a specific model.\n * If the model has explicit options in the map, use those; otherwise use base options.\n */\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof GrokChatModelProviderOptionsByName\n ? GrokChatModelProviderOptionsByName[TModel]\n : GrokProviderOptions\n\n/**\n * Resolve input modalities for a specific model.\n * If the model has explicit modalities in the map, use those; otherwise use text only.\n */\nexport type ResolveInputModalities<TModel extends string> =\n TModel extends keyof GrokModelInputModalitiesByName\n ? GrokModelInputModalitiesByName[TModel]\n : readonly ['text']\n"],"names":[],"mappings":"AAyBA,MAAM,0BAA0B;AAAA,EAC9B,MAAM;AAgBR;AAEA,MAAM,8BAA8B;AAAA,EAClC,MAAM;AAgBR;AAEA,MAAM,mBAAmB;AAAA,EACvB,MAAM;AAgBR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAgBR;AAEA,MAAM,4BAA4B;AAAA,EAChC,MAAM;AAgBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAgBR;AAEA,MAAM,cAAc;AAAA,EAClB,MAAM;AAgBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAgBR;AAEA,MAAM,gBAAgB;AAAA,EACpB,MAAM;AAeR;AAEA,MAAM,eAAe;AAAA,EACnB,MAAM;AAaR;AAMA,MAAM,YAAY;AAAA,EAChB,MAAM;AAgBR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAgBR;AAEO,MAAM,mBAAmB;AAAA,EAC9B,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,0BAA0B;AAAA,EAC1B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,cAAc;AAAA,EAEd,UAAU;AAAA,EACV,sBAAsB;AACxB;AAKO,MAAM,oBAAoB,CAAC,aAAa,IAAI;"}
|
|
1
|
+
{"version":3,"file":"model-meta.js","sources":["../../src/model-meta.ts"],"sourcesContent":["/**\n * Model metadata interface for documentation and type inference\n */\ninterface ModelMeta {\n name: string\n supports: {\n input: Array<'text' | 'image' | 'audio' | 'video' | 'document'>\n output: Array<'text' | 'image' | 'audio' | 'video'>\n capabilities?: Array<'reasoning' | 'tool_calling' | 'structured_outputs'>\n tools?: ReadonlyArray<never>\n }\n max_input_tokens?: number\n max_output_tokens?: number\n context_window?: number\n knowledge_cutoff?: string\n pricing?: {\n input: {\n normal: number\n cached?: number\n }\n output: {\n normal: number\n }\n }\n}\n\nconst GROK_4_1_FAST_REASONING = {\n name: 'grok-4-1-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_1_FAST_NON_REASONING = {\n name: 'grok-4-1-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_CODE_FAST_1 = {\n name: 'grok-code-fast-1',\n context_window: 256_000,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.02,\n },\n output: {\n normal: 1.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_REASONING = {\n name: 'grok-4-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_NON_REASONING = {\n name: 'grok-4-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4 = {\n name: 'grok-4',\n context_window: 256_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3_MINI = {\n name: 'grok-3-mini',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 0.3,\n cached: 0.075,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3 = {\n name: 'grok-3',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_VISION = {\n name: 'grok-2-vision-1212',\n context_window: 32_768,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 2,\n },\n output: {\n normal: 10,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_IMAGE = {\n name: 'grok-2-image-1212',\n supports: {\n input: ['text'],\n output: ['image'],\n },\n pricing: {\n input: {\n normal: 0.07,\n },\n output: {\n normal: 0.07,\n },\n },\n} as const satisfies ModelMeta\n\n/**\n * Grok Chat Models\n * Based on xAI's available models as of 2025\n */\nconst GROK_4_20 = {\n name: 'grok-4.20',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image', 'document'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 2,\n cached: 0.2,\n },\n output: {\n normal: 6,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_20_MULTI_AGENT = {\n name: 'grok-4.20-multi-agent',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image', 'document'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n tools: [] as const,\n },\n pricing: {\n input: {\n normal: 2,\n cached: 0.2,\n },\n output: {\n normal: 6,\n },\n },\n} as const satisfies ModelMeta\n\nexport const GROK_CHAT_MODELS = [\n GROK_4_1_FAST_REASONING.name,\n GROK_4_1_FAST_NON_REASONING.name,\n GROK_CODE_FAST_1.name,\n GROK_4_FAST_REASONING.name,\n GROK_4_FAST_NON_REASONING.name,\n GROK_4.name,\n GROK_3.name,\n GROK_3_MINI.name,\n GROK_2_VISION.name,\n\n GROK_4_20.name,\n GROK_4_20_MULTI_AGENT.name,\n] as const\n\n/**\n * Grok Image Generation Models\n */\nexport const GROK_IMAGE_MODELS = [GROK_2_IMAGE.name] as const\n\nexport type GrokChatModel = (typeof GROK_CHAT_MODELS)[number]\nexport type GrokImageModel = (typeof GROK_IMAGE_MODELS)[number]\n\n/**\n * Type-only map from Grok chat model name to its supported input modalities.\n * Used for type inference when constructing multimodal messages.\n */\nexport type GrokModelInputModalitiesByName = {\n [GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.input\n [GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.input\n [GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.input\n [GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.input\n [GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.input\n [GROK_4.name]: typeof GROK_4.supports.input\n [GROK_3.name]: typeof GROK_3.supports.input\n [GROK_3_MINI.name]: typeof GROK_3_MINI.supports.input\n [GROK_2_VISION.name]: typeof GROK_2_VISION.supports.input\n [GROK_4_20.name]: typeof GROK_4_20.supports.input\n [GROK_4_20_MULTI_AGENT.name]: typeof GROK_4_20_MULTI_AGENT.supports.input\n}\n\n/**\n * Type-only map from Grok chat model name to its provider options type.\n * Since Grok uses OpenAI-compatible API, we reuse OpenAI provider options.\n */\nexport type GrokChatModelProviderOptionsByName = {\n [K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions\n}\n\n/**\n * Type-only map from Grok chat model name to its supported provider tools.\n * Grok exposes no provider-specific tool factories, so every model gets an\n * empty tuple. This ensures that passing an Anthropic/OpenAI ProviderTool to\n * a Grok adapter produces a compile-time type error.\n */\nexport type GrokChatModelToolCapabilitiesByName = {\n [GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.tools\n [GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.tools\n [GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.tools\n [GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.tools\n [GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.tools\n [GROK_4.name]: typeof GROK_4.supports.tools\n [GROK_3.name]: typeof GROK_3.supports.tools\n [GROK_3_MINI.name]: typeof GROK_3_MINI.supports.tools\n [GROK_2_VISION.name]: typeof GROK_2_VISION.supports.tools\n [GROK_4_20.name]: typeof GROK_4_20.supports.tools\n [GROK_4_20_MULTI_AGENT.name]: typeof GROK_4_20_MULTI_AGENT.supports.tools\n}\n\n/**\n * Grok-specific provider options\n * Based on OpenAI-compatible API options\n */\nexport interface GrokProviderOptions {\n /** Temperature for response generation (0-2) */\n temperature?: number\n /** Maximum tokens in the response */\n max_tokens?: number\n /** Top-p sampling parameter */\n top_p?: number\n /** Frequency penalty (-2.0 to 2.0) */\n frequency_penalty?: number\n /** Presence penalty (-2.0 to 2.0) */\n presence_penalty?: number\n /** Stop sequences */\n stop?: string | Array<string>\n /** A unique identifier representing your end-user */\n user?: string\n}\n\n// ===========================\n// Type Resolution Helpers\n// ===========================\n\n/**\n * Resolve provider options for a specific model.\n * If the model has explicit options in the map, use those; otherwise use base options.\n */\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof GrokChatModelProviderOptionsByName\n ? GrokChatModelProviderOptionsByName[TModel]\n : GrokProviderOptions\n\n/**\n * Resolve input modalities for a specific model.\n * If the model has explicit modalities in the map, use those; otherwise use text only.\n */\nexport type ResolveInputModalities<TModel extends string> =\n TModel extends keyof GrokModelInputModalitiesByName\n ? GrokModelInputModalitiesByName[TModel]\n : readonly ['text']\n"],"names":[],"mappings":"AA0BA,MAAM,0BAA0B;AAAA,EAC9B,MAAM;AAiBR;AAEA,MAAM,8BAA8B;AAAA,EAClC,MAAM;AAiBR;AAEA,MAAM,mBAAmB;AAAA,EACvB,MAAM;AAiBR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAiBR;AAEA,MAAM,4BAA4B;AAAA,EAChC,MAAM;AAiBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAiBR;AAEA,MAAM,cAAc;AAAA,EAClB,MAAM;AAiBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAiBR;AAEA,MAAM,gBAAgB;AAAA,EACpB,MAAM;AAgBR;AAEA,MAAM,eAAe;AAAA,EACnB,MAAM;AAaR;AAMA,MAAM,YAAY;AAAA,EAChB,MAAM;AAiBR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAiBR;AAEO,MAAM,mBAAmB;AAAA,EAC9B,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,0BAA0B;AAAA,EAC1B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,cAAc;AAAA,EAEd,UAAU;AAAA,EACV,sBAAsB;AACxB;AAKO,MAAM,oBAAoB,CAAC,aAAa,IAAI;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-grok",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Grok (xAI) adapter for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
".": {
|
|
17
17
|
"types": "./dist/esm/index.d.ts",
|
|
18
18
|
"import": "./dist/esm/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./tools": {
|
|
21
|
+
"types": "./dist/esm/tools/index.d.ts",
|
|
22
|
+
"import": "./dist/esm/tools/index.js"
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
25
|
"files": [
|
|
@@ -38,7 +42,7 @@
|
|
|
38
42
|
},
|
|
39
43
|
"peerDependencies": {
|
|
40
44
|
"zod": "^4.0.0",
|
|
41
|
-
"@tanstack/ai": "^0.
|
|
45
|
+
"@tanstack/ai": "^0.12.0"
|
|
42
46
|
},
|
|
43
47
|
"scripts": {
|
|
44
48
|
"build": "vite build",
|
package/src/adapters/text.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '../utils'
|
|
11
11
|
import type {
|
|
12
12
|
GROK_CHAT_MODELS,
|
|
13
|
+
GrokChatModelToolCapabilitiesByName,
|
|
13
14
|
ResolveInputModalities,
|
|
14
15
|
ResolveProviderOptions,
|
|
15
16
|
} from '../model-meta'
|
|
@@ -20,17 +21,31 @@ import type {
|
|
|
20
21
|
import type OpenAI_SDK from 'openai'
|
|
21
22
|
import type {
|
|
22
23
|
ContentPart,
|
|
24
|
+
Modality,
|
|
23
25
|
ModelMessage,
|
|
24
26
|
StreamChunk,
|
|
25
27
|
TextOptions,
|
|
26
28
|
} from '@tanstack/ai'
|
|
27
|
-
import type {
|
|
29
|
+
import type {
|
|
30
|
+
ExternalTextProviderOptions as GrokTextProviderOptions,
|
|
31
|
+
InternalTextProviderOptions,
|
|
32
|
+
} from '../text/text-provider-options'
|
|
28
33
|
import type {
|
|
29
34
|
GrokImageMetadata,
|
|
30
35
|
GrokMessageMetadataByModality,
|
|
31
36
|
} from '../message-types'
|
|
32
37
|
import type { GrokClientConfig } from '../utils'
|
|
33
38
|
|
|
39
|
+
type ResolveToolCapabilities<TModel extends string> =
|
|
40
|
+
TModel extends keyof GrokChatModelToolCapabilitiesByName
|
|
41
|
+
? NonNullable<GrokChatModelToolCapabilitiesByName[TModel]>
|
|
42
|
+
: readonly []
|
|
43
|
+
|
|
44
|
+
/** Cast an event object to StreamChunk. Adapters construct events with string
|
|
45
|
+
* literal types which are structurally compatible with the EventType enum. */
|
|
46
|
+
const asChunk = (chunk: Record<string, unknown>) =>
|
|
47
|
+
chunk as unknown as StreamChunk
|
|
48
|
+
|
|
34
49
|
/**
|
|
35
50
|
* Configuration for Grok text adapter
|
|
36
51
|
*/
|
|
@@ -49,11 +64,17 @@ export type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../
|
|
|
49
64
|
*/
|
|
50
65
|
export class GrokTextAdapter<
|
|
51
66
|
TModel extends (typeof GROK_CHAT_MODELS)[number],
|
|
67
|
+
TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,
|
|
68
|
+
TInputModalities extends ReadonlyArray<Modality> =
|
|
69
|
+
ResolveInputModalities<TModel>,
|
|
70
|
+
TToolCapabilities extends ReadonlyArray<string> =
|
|
71
|
+
ResolveToolCapabilities<TModel>,
|
|
52
72
|
> extends BaseTextAdapter<
|
|
53
73
|
TModel,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
GrokMessageMetadataByModality
|
|
74
|
+
TProviderOptions,
|
|
75
|
+
TInputModalities,
|
|
76
|
+
GrokMessageMetadataByModality,
|
|
77
|
+
TToolCapabilities
|
|
57
78
|
> {
|
|
58
79
|
readonly kind = 'text' as const
|
|
59
80
|
readonly name = 'grok' as const
|
|
@@ -66,14 +87,15 @@ export class GrokTextAdapter<
|
|
|
66
87
|
}
|
|
67
88
|
|
|
68
89
|
async *chatStream(
|
|
69
|
-
options: TextOptions<
|
|
90
|
+
options: TextOptions<GrokTextProviderOptions>,
|
|
70
91
|
): AsyncIterable<StreamChunk> {
|
|
71
92
|
const requestParams = this.mapTextOptionsToGrok(options)
|
|
72
93
|
const timestamp = Date.now()
|
|
73
94
|
|
|
74
95
|
// AG-UI lifecycle tracking (mutable state object for ESLint compatibility)
|
|
75
96
|
const aguiState = {
|
|
76
|
-
runId: generateId(this.name),
|
|
97
|
+
runId: options.runId ?? generateId(this.name),
|
|
98
|
+
threadId: options.threadId ?? generateId(this.name),
|
|
77
99
|
messageId: generateId(this.name),
|
|
78
100
|
timestamp,
|
|
79
101
|
hasEmittedRunStarted: false,
|
|
@@ -92,25 +114,28 @@ export class GrokTextAdapter<
|
|
|
92
114
|
// Emit RUN_STARTED if not yet emitted
|
|
93
115
|
if (!aguiState.hasEmittedRunStarted) {
|
|
94
116
|
aguiState.hasEmittedRunStarted = true
|
|
95
|
-
yield {
|
|
117
|
+
yield asChunk({
|
|
96
118
|
type: 'RUN_STARTED',
|
|
97
119
|
runId: aguiState.runId,
|
|
120
|
+
threadId: aguiState.threadId,
|
|
98
121
|
model: options.model,
|
|
99
122
|
timestamp,
|
|
100
|
-
}
|
|
123
|
+
})
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
// Emit AG-UI RUN_ERROR
|
|
104
|
-
yield {
|
|
127
|
+
yield asChunk({
|
|
105
128
|
type: 'RUN_ERROR',
|
|
106
129
|
runId: aguiState.runId,
|
|
107
130
|
model: options.model,
|
|
108
131
|
timestamp,
|
|
132
|
+
message: err.message || 'Unknown error',
|
|
133
|
+
code: err.code,
|
|
109
134
|
error: {
|
|
110
135
|
message: err.message || 'Unknown error',
|
|
111
136
|
code: err.code,
|
|
112
137
|
},
|
|
113
|
-
}
|
|
138
|
+
})
|
|
114
139
|
|
|
115
140
|
console.error('>>> chatStream: Fatal error during response creation <<<')
|
|
116
141
|
console.error('>>> Error message:', err.message)
|
|
@@ -132,7 +157,7 @@ export class GrokTextAdapter<
|
|
|
132
157
|
* We apply Grok-specific transformations for structured output compatibility.
|
|
133
158
|
*/
|
|
134
159
|
async structuredOutput(
|
|
135
|
-
options: StructuredOutputOptions<
|
|
160
|
+
options: StructuredOutputOptions<GrokTextProviderOptions>,
|
|
136
161
|
): Promise<StructuredOutputResult<unknown>> {
|
|
137
162
|
const { chatOptions, outputSchema } = options
|
|
138
163
|
const requestParams = this.mapTextOptionsToGrok(chatOptions)
|
|
@@ -191,6 +216,7 @@ export class GrokTextAdapter<
|
|
|
191
216
|
options: TextOptions,
|
|
192
217
|
aguiState: {
|
|
193
218
|
runId: string
|
|
219
|
+
threadId: string
|
|
194
220
|
messageId: string
|
|
195
221
|
timestamp: number
|
|
196
222
|
hasEmittedRunStarted: boolean
|
|
@@ -220,12 +246,13 @@ export class GrokTextAdapter<
|
|
|
220
246
|
// Emit RUN_STARTED on first chunk
|
|
221
247
|
if (!aguiState.hasEmittedRunStarted) {
|
|
222
248
|
aguiState.hasEmittedRunStarted = true
|
|
223
|
-
yield {
|
|
249
|
+
yield asChunk({
|
|
224
250
|
type: 'RUN_STARTED',
|
|
225
251
|
runId: aguiState.runId,
|
|
252
|
+
threadId: aguiState.threadId,
|
|
226
253
|
model: chunk.model || options.model,
|
|
227
254
|
timestamp,
|
|
228
|
-
}
|
|
255
|
+
})
|
|
229
256
|
}
|
|
230
257
|
|
|
231
258
|
const delta = choice.delta
|
|
@@ -237,26 +264,26 @@ export class GrokTextAdapter<
|
|
|
237
264
|
// Emit TEXT_MESSAGE_START on first text content
|
|
238
265
|
if (!hasEmittedTextMessageStart) {
|
|
239
266
|
hasEmittedTextMessageStart = true
|
|
240
|
-
yield {
|
|
267
|
+
yield asChunk({
|
|
241
268
|
type: 'TEXT_MESSAGE_START',
|
|
242
269
|
messageId: aguiState.messageId,
|
|
243
270
|
model: chunk.model || options.model,
|
|
244
271
|
timestamp,
|
|
245
272
|
role: 'assistant',
|
|
246
|
-
}
|
|
273
|
+
})
|
|
247
274
|
}
|
|
248
275
|
|
|
249
276
|
accumulatedContent += deltaContent
|
|
250
277
|
|
|
251
278
|
// Emit AG-UI TEXT_MESSAGE_CONTENT
|
|
252
|
-
yield {
|
|
279
|
+
yield asChunk({
|
|
253
280
|
type: 'TEXT_MESSAGE_CONTENT',
|
|
254
281
|
messageId: aguiState.messageId,
|
|
255
282
|
model: chunk.model || options.model,
|
|
256
283
|
timestamp,
|
|
257
284
|
delta: deltaContent,
|
|
258
285
|
content: accumulatedContent,
|
|
259
|
-
}
|
|
286
|
+
})
|
|
260
287
|
}
|
|
261
288
|
|
|
262
289
|
// Handle tool calls - they come in as deltas
|
|
@@ -290,25 +317,26 @@ export class GrokTextAdapter<
|
|
|
290
317
|
// Emit TOOL_CALL_START when we have id and name
|
|
291
318
|
if (toolCall.id && toolCall.name && !toolCall.started) {
|
|
292
319
|
toolCall.started = true
|
|
293
|
-
yield {
|
|
320
|
+
yield asChunk({
|
|
294
321
|
type: 'TOOL_CALL_START',
|
|
295
322
|
toolCallId: toolCall.id,
|
|
323
|
+
toolCallName: toolCall.name,
|
|
296
324
|
toolName: toolCall.name,
|
|
297
325
|
model: chunk.model || options.model,
|
|
298
326
|
timestamp,
|
|
299
327
|
index,
|
|
300
|
-
}
|
|
328
|
+
})
|
|
301
329
|
}
|
|
302
330
|
|
|
303
331
|
// Emit TOOL_CALL_ARGS for argument deltas
|
|
304
332
|
if (toolCallDelta.function?.arguments && toolCall.started) {
|
|
305
|
-
yield {
|
|
333
|
+
yield asChunk({
|
|
306
334
|
type: 'TOOL_CALL_ARGS',
|
|
307
335
|
toolCallId: toolCall.id,
|
|
308
336
|
model: chunk.model || options.model,
|
|
309
337
|
timestamp,
|
|
310
338
|
delta: toolCallDelta.function.arguments,
|
|
311
|
-
}
|
|
339
|
+
})
|
|
312
340
|
}
|
|
313
341
|
}
|
|
314
342
|
}
|
|
@@ -332,14 +360,15 @@ export class GrokTextAdapter<
|
|
|
332
360
|
}
|
|
333
361
|
|
|
334
362
|
// Emit AG-UI TOOL_CALL_END
|
|
335
|
-
yield {
|
|
363
|
+
yield asChunk({
|
|
336
364
|
type: 'TOOL_CALL_END',
|
|
337
365
|
toolCallId: toolCall.id,
|
|
366
|
+
toolCallName: toolCall.name,
|
|
338
367
|
toolName: toolCall.name,
|
|
339
368
|
model: chunk.model || options.model,
|
|
340
369
|
timestamp,
|
|
341
370
|
input: parsedInput,
|
|
342
|
-
}
|
|
371
|
+
})
|
|
343
372
|
}
|
|
344
373
|
}
|
|
345
374
|
|
|
@@ -351,18 +380,19 @@ export class GrokTextAdapter<
|
|
|
351
380
|
|
|
352
381
|
// Emit TEXT_MESSAGE_END if we had text content
|
|
353
382
|
if (hasEmittedTextMessageStart) {
|
|
354
|
-
yield {
|
|
383
|
+
yield asChunk({
|
|
355
384
|
type: 'TEXT_MESSAGE_END',
|
|
356
385
|
messageId: aguiState.messageId,
|
|
357
386
|
model: chunk.model || options.model,
|
|
358
387
|
timestamp,
|
|
359
|
-
}
|
|
388
|
+
})
|
|
360
389
|
}
|
|
361
390
|
|
|
362
391
|
// Emit AG-UI RUN_FINISHED
|
|
363
|
-
yield {
|
|
392
|
+
yield asChunk({
|
|
364
393
|
type: 'RUN_FINISHED',
|
|
365
394
|
runId: aguiState.runId,
|
|
395
|
+
threadId: aguiState.threadId,
|
|
366
396
|
model: chunk.model || options.model,
|
|
367
397
|
timestamp,
|
|
368
398
|
usage: chunk.usage
|
|
@@ -373,7 +403,7 @@ export class GrokTextAdapter<
|
|
|
373
403
|
}
|
|
374
404
|
: undefined,
|
|
375
405
|
finishReason: computedFinishReason,
|
|
376
|
-
}
|
|
406
|
+
})
|
|
377
407
|
}
|
|
378
408
|
}
|
|
379
409
|
} catch (error: unknown) {
|
|
@@ -381,16 +411,18 @@ export class GrokTextAdapter<
|
|
|
381
411
|
console.log('[Grok Adapter] Stream ended with error:', err.message)
|
|
382
412
|
|
|
383
413
|
// Emit AG-UI RUN_ERROR
|
|
384
|
-
yield {
|
|
414
|
+
yield asChunk({
|
|
385
415
|
type: 'RUN_ERROR',
|
|
386
416
|
runId: aguiState.runId,
|
|
387
417
|
model: options.model,
|
|
388
418
|
timestamp,
|
|
419
|
+
message: err.message || 'Unknown error occurred',
|
|
420
|
+
code: err.code,
|
|
389
421
|
error: {
|
|
390
422
|
message: err.message || 'Unknown error occurred',
|
|
391
423
|
code: err.code,
|
|
392
424
|
},
|
|
393
|
-
}
|
|
425
|
+
})
|
|
394
426
|
}
|
|
395
427
|
}
|
|
396
428
|
|
package/src/index.ts
CHANGED
package/src/model-meta.ts
CHANGED
|
@@ -7,6 +7,7 @@ interface ModelMeta {
|
|
|
7
7
|
input: Array<'text' | 'image' | 'audio' | 'video' | 'document'>
|
|
8
8
|
output: Array<'text' | 'image' | 'audio' | 'video'>
|
|
9
9
|
capabilities?: Array<'reasoning' | 'tool_calling' | 'structured_outputs'>
|
|
10
|
+
tools?: ReadonlyArray<never>
|
|
10
11
|
}
|
|
11
12
|
max_input_tokens?: number
|
|
12
13
|
max_output_tokens?: number
|
|
@@ -30,6 +31,7 @@ const GROK_4_1_FAST_REASONING = {
|
|
|
30
31
|
input: ['text', 'image'],
|
|
31
32
|
output: ['text'],
|
|
32
33
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
34
|
+
tools: [] as const,
|
|
33
35
|
},
|
|
34
36
|
pricing: {
|
|
35
37
|
input: {
|
|
@@ -49,6 +51,7 @@ const GROK_4_1_FAST_NON_REASONING = {
|
|
|
49
51
|
input: ['text', 'image'],
|
|
50
52
|
output: ['text'],
|
|
51
53
|
capabilities: ['structured_outputs', 'tool_calling'],
|
|
54
|
+
tools: [] as const,
|
|
52
55
|
},
|
|
53
56
|
pricing: {
|
|
54
57
|
input: {
|
|
@@ -68,6 +71,7 @@ const GROK_CODE_FAST_1 = {
|
|
|
68
71
|
input: ['text'],
|
|
69
72
|
output: ['text'],
|
|
70
73
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
74
|
+
tools: [] as const,
|
|
71
75
|
},
|
|
72
76
|
pricing: {
|
|
73
77
|
input: {
|
|
@@ -87,6 +91,7 @@ const GROK_4_FAST_REASONING = {
|
|
|
87
91
|
input: ['text', 'image'],
|
|
88
92
|
output: ['text'],
|
|
89
93
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
94
|
+
tools: [] as const,
|
|
90
95
|
},
|
|
91
96
|
pricing: {
|
|
92
97
|
input: {
|
|
@@ -106,6 +111,7 @@ const GROK_4_FAST_NON_REASONING = {
|
|
|
106
111
|
input: ['text', 'image'],
|
|
107
112
|
output: ['text'],
|
|
108
113
|
capabilities: ['structured_outputs', 'tool_calling'],
|
|
114
|
+
tools: [] as const,
|
|
109
115
|
},
|
|
110
116
|
pricing: {
|
|
111
117
|
input: {
|
|
@@ -125,6 +131,7 @@ const GROK_4 = {
|
|
|
125
131
|
input: ['text', 'image'],
|
|
126
132
|
output: ['text'],
|
|
127
133
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
134
|
+
tools: [] as const,
|
|
128
135
|
},
|
|
129
136
|
pricing: {
|
|
130
137
|
input: {
|
|
@@ -144,6 +151,7 @@ const GROK_3_MINI = {
|
|
|
144
151
|
input: ['text'],
|
|
145
152
|
output: ['text'],
|
|
146
153
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
154
|
+
tools: [] as const,
|
|
147
155
|
},
|
|
148
156
|
pricing: {
|
|
149
157
|
input: {
|
|
@@ -163,6 +171,7 @@ const GROK_3 = {
|
|
|
163
171
|
input: ['text'],
|
|
164
172
|
output: ['text'],
|
|
165
173
|
capabilities: ['structured_outputs', 'tool_calling'],
|
|
174
|
+
tools: [] as const,
|
|
166
175
|
},
|
|
167
176
|
pricing: {
|
|
168
177
|
input: {
|
|
@@ -182,6 +191,7 @@ const GROK_2_VISION = {
|
|
|
182
191
|
input: ['text', 'image'],
|
|
183
192
|
output: ['text'],
|
|
184
193
|
capabilities: ['structured_outputs', 'tool_calling'],
|
|
194
|
+
tools: [] as const,
|
|
185
195
|
},
|
|
186
196
|
pricing: {
|
|
187
197
|
input: {
|
|
@@ -220,6 +230,7 @@ const GROK_4_20 = {
|
|
|
220
230
|
input: ['text', 'image', 'document'],
|
|
221
231
|
output: ['text'],
|
|
222
232
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
233
|
+
tools: [] as const,
|
|
223
234
|
},
|
|
224
235
|
pricing: {
|
|
225
236
|
input: {
|
|
@@ -239,6 +250,7 @@ const GROK_4_20_MULTI_AGENT = {
|
|
|
239
250
|
input: ['text', 'image', 'document'],
|
|
240
251
|
output: ['text'],
|
|
241
252
|
capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],
|
|
253
|
+
tools: [] as const,
|
|
242
254
|
},
|
|
243
255
|
pricing: {
|
|
244
256
|
input: {
|
|
@@ -300,6 +312,26 @@ export type GrokChatModelProviderOptionsByName = {
|
|
|
300
312
|
[K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions
|
|
301
313
|
}
|
|
302
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Type-only map from Grok chat model name to its supported provider tools.
|
|
317
|
+
* Grok exposes no provider-specific tool factories, so every model gets an
|
|
318
|
+
* empty tuple. This ensures that passing an Anthropic/OpenAI ProviderTool to
|
|
319
|
+
* a Grok adapter produces a compile-time type error.
|
|
320
|
+
*/
|
|
321
|
+
export type GrokChatModelToolCapabilitiesByName = {
|
|
322
|
+
[GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.tools
|
|
323
|
+
[GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.tools
|
|
324
|
+
[GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.tools
|
|
325
|
+
[GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.tools
|
|
326
|
+
[GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.tools
|
|
327
|
+
[GROK_4.name]: typeof GROK_4.supports.tools
|
|
328
|
+
[GROK_3.name]: typeof GROK_3.supports.tools
|
|
329
|
+
[GROK_3_MINI.name]: typeof GROK_3_MINI.supports.tools
|
|
330
|
+
[GROK_2_VISION.name]: typeof GROK_2_VISION.supports.tools
|
|
331
|
+
[GROK_4_20.name]: typeof GROK_4_20.supports.tools
|
|
332
|
+
[GROK_4_20_MULTI_AGENT.name]: typeof GROK_4_20_MULTI_AGENT.supports.tools
|
|
333
|
+
}
|
|
334
|
+
|
|
303
335
|
/**
|
|
304
336
|
* Grok-specific provider options
|
|
305
337
|
* Based on OpenAI-compatible API options
|