@tanstack/ai-grok 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +113 -28
- package/dist/esm/adapters/image.d.ts +77 -0
- package/dist/esm/adapters/image.js +63 -0
- package/dist/esm/adapters/image.js.map +1 -0
- package/dist/esm/adapters/summarize.d.ts +75 -0
- package/dist/esm/adapters/summarize.js +81 -0
- package/dist/esm/adapters/summarize.js.map +1 -0
- package/dist/esm/adapters/text.d.ts +96 -0
- package/dist/esm/adapters/text.js +300 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/image/image-provider-options.d.ts +66 -0
- package/dist/esm/image/image-provider-options.js +39 -0
- package/dist/esm/image/image-provider-options.js.map +1 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/message-types.d.ts +64 -0
- package/dist/esm/model-meta.d.ts +223 -0
- package/dist/esm/model-meta.js +47 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/text-provider-options.d.ts +66 -0
- package/dist/esm/text/text-provider-options.js +6 -0
- package/dist/esm/text/text-provider-options.js.map +1 -0
- package/dist/esm/tools/function-tool.d.ts +15 -0
- package/dist/esm/tools/function-tool.js +27 -0
- package/dist/esm/tools/function-tool.js.map +1 -0
- package/dist/esm/tools/index.d.ts +2 -0
- package/dist/esm/tools/tool-converter.d.ts +7 -0
- package/dist/esm/tools/tool-converter.js +10 -0
- package/dist/esm/tools/tool-converter.js.map +1 -0
- package/dist/esm/utils/client.d.ts +18 -0
- package/dist/esm/utils/client.js +26 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/schema-converter.d.ts +24 -0
- package/dist/esm/utils/schema-converter.js +71 -0
- package/dist/esm/utils/schema-converter.js.map +1 -0
- package/package.json +50 -7
- package/src/adapters/image.ts +176 -0
- package/src/adapters/summarize.ts +174 -0
- package/src/adapters/text.ts +506 -0
- package/src/image/image-provider-options.ts +118 -0
- package/src/index.ts +55 -0
- package/src/message-types.ts +67 -0
- package/src/model-meta.ts +298 -0
- package/src/text/text-provider-options.ts +77 -0
- package/src/tools/function-tool.ts +45 -0
- package/src/tools/index.ts +5 -0
- package/src/tools/tool-converter.ts +17 -0
- package/src/utils/client.ts +45 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/schema-converter.ts +110 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { BaseTextAdapter } from "@tanstack/ai/adapters";
|
|
2
|
+
import { validateTextProviderOptions } from "../text/text-provider-options.js";
|
|
3
|
+
import { makeGrokStructuredOutputCompatible, transformNullsToUndefined } from "../utils/schema-converter.js";
|
|
4
|
+
import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
|
|
5
|
+
import { createGrokClient, generateId, getGrokApiKeyFromEnv } from "../utils/client.js";
|
|
6
|
+
class GrokTextAdapter extends BaseTextAdapter {
|
|
7
|
+
constructor(config, model) {
|
|
8
|
+
super({}, model);
|
|
9
|
+
this.kind = "text";
|
|
10
|
+
this.name = "grok";
|
|
11
|
+
this.client = createGrokClient(config);
|
|
12
|
+
}
|
|
13
|
+
async *chatStream(options) {
|
|
14
|
+
const requestParams = this.mapTextOptionsToGrok(options);
|
|
15
|
+
try {
|
|
16
|
+
const stream = await this.client.chat.completions.create({
|
|
17
|
+
...requestParams,
|
|
18
|
+
stream: true
|
|
19
|
+
});
|
|
20
|
+
yield* this.processGrokStreamChunks(stream, options);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
const err = error;
|
|
23
|
+
console.error(">>> chatStream: Fatal error during response creation <<<");
|
|
24
|
+
console.error(">>> Error message:", err.message);
|
|
25
|
+
console.error(">>> Error stack:", err.stack);
|
|
26
|
+
console.error(">>> Full error:", err);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate structured output using Grok's JSON Schema response format.
|
|
32
|
+
* Uses stream: false to get the complete response in one call.
|
|
33
|
+
*
|
|
34
|
+
* Grok has strict requirements for structured output (via OpenAI-compatible API):
|
|
35
|
+
* - All properties must be in the `required` array
|
|
36
|
+
* - Optional fields should have null added to their type union
|
|
37
|
+
* - additionalProperties must be false for all objects
|
|
38
|
+
*
|
|
39
|
+
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
40
|
+
* We apply Grok-specific transformations for structured output compatibility.
|
|
41
|
+
*/
|
|
42
|
+
async structuredOutput(options) {
|
|
43
|
+
const { chatOptions, outputSchema } = options;
|
|
44
|
+
const requestParams = this.mapTextOptionsToGrok(chatOptions);
|
|
45
|
+
const jsonSchema = makeGrokStructuredOutputCompatible(
|
|
46
|
+
outputSchema,
|
|
47
|
+
outputSchema.required || []
|
|
48
|
+
);
|
|
49
|
+
try {
|
|
50
|
+
const response = await this.client.chat.completions.create({
|
|
51
|
+
...requestParams,
|
|
52
|
+
stream: false,
|
|
53
|
+
response_format: {
|
|
54
|
+
type: "json_schema",
|
|
55
|
+
json_schema: {
|
|
56
|
+
name: "structured_output",
|
|
57
|
+
schema: jsonSchema,
|
|
58
|
+
strict: true
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const rawText = response.choices[0]?.message.content || "";
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = JSON.parse(rawText);
|
|
66
|
+
} catch {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Failed to parse structured output as JSON. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? "..." : ""}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const transformed = transformNullsToUndefined(parsed);
|
|
72
|
+
return {
|
|
73
|
+
data: transformed,
|
|
74
|
+
rawText
|
|
75
|
+
};
|
|
76
|
+
} catch (error) {
|
|
77
|
+
const err = error;
|
|
78
|
+
console.error(">>> structuredOutput: Error during response creation <<<");
|
|
79
|
+
console.error(">>> Error message:", err.message);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async *processGrokStreamChunks(stream, options) {
|
|
84
|
+
let accumulatedContent = "";
|
|
85
|
+
const timestamp = Date.now();
|
|
86
|
+
let responseId = generateId(this.name);
|
|
87
|
+
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
88
|
+
try {
|
|
89
|
+
for await (const chunk of stream) {
|
|
90
|
+
responseId = chunk.id || responseId;
|
|
91
|
+
const choice = chunk.choices[0];
|
|
92
|
+
if (!choice) continue;
|
|
93
|
+
const delta = choice.delta;
|
|
94
|
+
const deltaContent = delta.content;
|
|
95
|
+
const deltaToolCalls = delta.tool_calls;
|
|
96
|
+
if (deltaContent) {
|
|
97
|
+
accumulatedContent += deltaContent;
|
|
98
|
+
yield {
|
|
99
|
+
type: "content",
|
|
100
|
+
id: responseId,
|
|
101
|
+
model: chunk.model || options.model,
|
|
102
|
+
timestamp,
|
|
103
|
+
delta: deltaContent,
|
|
104
|
+
content: accumulatedContent,
|
|
105
|
+
role: "assistant"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (deltaToolCalls) {
|
|
109
|
+
for (const toolCallDelta of deltaToolCalls) {
|
|
110
|
+
const index = toolCallDelta.index;
|
|
111
|
+
if (!toolCallsInProgress.has(index)) {
|
|
112
|
+
toolCallsInProgress.set(index, {
|
|
113
|
+
id: toolCallDelta.id || "",
|
|
114
|
+
name: toolCallDelta.function?.name || "",
|
|
115
|
+
arguments: ""
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const toolCall = toolCallsInProgress.get(index);
|
|
119
|
+
if (toolCallDelta.id) {
|
|
120
|
+
toolCall.id = toolCallDelta.id;
|
|
121
|
+
}
|
|
122
|
+
if (toolCallDelta.function?.name) {
|
|
123
|
+
toolCall.name = toolCallDelta.function.name;
|
|
124
|
+
}
|
|
125
|
+
if (toolCallDelta.function?.arguments) {
|
|
126
|
+
toolCall.arguments += toolCallDelta.function.arguments;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (choice.finish_reason) {
|
|
131
|
+
if (choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0) {
|
|
132
|
+
for (const [index, toolCall] of toolCallsInProgress) {
|
|
133
|
+
yield {
|
|
134
|
+
type: "tool_call",
|
|
135
|
+
id: responseId,
|
|
136
|
+
model: chunk.model || options.model,
|
|
137
|
+
timestamp,
|
|
138
|
+
index,
|
|
139
|
+
toolCall: {
|
|
140
|
+
id: toolCall.id,
|
|
141
|
+
type: "function",
|
|
142
|
+
function: {
|
|
143
|
+
name: toolCall.name,
|
|
144
|
+
arguments: toolCall.arguments
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
yield {
|
|
151
|
+
type: "done",
|
|
152
|
+
id: responseId,
|
|
153
|
+
model: chunk.model || options.model,
|
|
154
|
+
timestamp,
|
|
155
|
+
usage: chunk.usage ? {
|
|
156
|
+
promptTokens: chunk.usage.prompt_tokens || 0,
|
|
157
|
+
completionTokens: chunk.usage.completion_tokens || 0,
|
|
158
|
+
totalTokens: chunk.usage.total_tokens || 0
|
|
159
|
+
} : void 0,
|
|
160
|
+
finishReason: choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0 ? "tool_calls" : "stop"
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} catch (error) {
|
|
165
|
+
const err = error;
|
|
166
|
+
console.log("[Grok Adapter] Stream ended with error:", err.message);
|
|
167
|
+
yield {
|
|
168
|
+
type: "error",
|
|
169
|
+
id: responseId,
|
|
170
|
+
model: options.model,
|
|
171
|
+
timestamp,
|
|
172
|
+
error: {
|
|
173
|
+
message: err.message || "Unknown error occurred",
|
|
174
|
+
code: err.code
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Maps common options to Grok-specific Chat Completions format
|
|
181
|
+
*/
|
|
182
|
+
mapTextOptionsToGrok(options) {
|
|
183
|
+
const modelOptions = options.modelOptions;
|
|
184
|
+
if (modelOptions) {
|
|
185
|
+
validateTextProviderOptions({
|
|
186
|
+
...modelOptions,
|
|
187
|
+
model: options.model
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const tools = options.tools ? convertToolsToProviderFormat(options.tools) : void 0;
|
|
191
|
+
const messages = [];
|
|
192
|
+
if (options.systemPrompts && options.systemPrompts.length > 0) {
|
|
193
|
+
messages.push({
|
|
194
|
+
role: "system",
|
|
195
|
+
content: options.systemPrompts.join("\n")
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
for (const message of options.messages) {
|
|
199
|
+
messages.push(this.convertMessageToGrok(message));
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
model: options.model,
|
|
203
|
+
messages,
|
|
204
|
+
temperature: options.temperature,
|
|
205
|
+
max_tokens: options.maxTokens,
|
|
206
|
+
top_p: options.topP,
|
|
207
|
+
tools,
|
|
208
|
+
stream: true,
|
|
209
|
+
stream_options: { include_usage: true }
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
convertMessageToGrok(message) {
|
|
213
|
+
if (message.role === "tool") {
|
|
214
|
+
return {
|
|
215
|
+
role: "tool",
|
|
216
|
+
tool_call_id: message.toolCallId || "",
|
|
217
|
+
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content)
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
if (message.role === "assistant") {
|
|
221
|
+
const toolCalls = message.toolCalls?.map((tc) => ({
|
|
222
|
+
id: tc.id,
|
|
223
|
+
type: "function",
|
|
224
|
+
function: {
|
|
225
|
+
name: tc.function.name,
|
|
226
|
+
arguments: typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
227
|
+
}
|
|
228
|
+
}));
|
|
229
|
+
return {
|
|
230
|
+
role: "assistant",
|
|
231
|
+
content: this.extractTextContent(message.content),
|
|
232
|
+
...toolCalls && toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
const contentParts = this.normalizeContent(message.content);
|
|
236
|
+
if (contentParts.length === 1 && contentParts[0]?.type === "text") {
|
|
237
|
+
return {
|
|
238
|
+
role: "user",
|
|
239
|
+
content: contentParts[0].content
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const parts = [];
|
|
243
|
+
for (const part of contentParts) {
|
|
244
|
+
if (part.type === "text") {
|
|
245
|
+
parts.push({ type: "text", text: part.content });
|
|
246
|
+
} else if (part.type === "image") {
|
|
247
|
+
const imageMetadata = part.metadata;
|
|
248
|
+
parts.push({
|
|
249
|
+
type: "image_url",
|
|
250
|
+
image_url: {
|
|
251
|
+
url: part.source.value,
|
|
252
|
+
detail: imageMetadata?.detail || "auto"
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
role: "user",
|
|
259
|
+
content: parts.length > 0 ? parts : ""
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Normalizes message content to an array of ContentPart.
|
|
264
|
+
* Handles backward compatibility with string content.
|
|
265
|
+
*/
|
|
266
|
+
normalizeContent(content) {
|
|
267
|
+
if (content === null) {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
if (typeof content === "string") {
|
|
271
|
+
return [{ type: "text", content }];
|
|
272
|
+
}
|
|
273
|
+
return content;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Extracts text content from a content value that may be string, null, or ContentPart array.
|
|
277
|
+
*/
|
|
278
|
+
extractTextContent(content) {
|
|
279
|
+
if (content === null) {
|
|
280
|
+
return "";
|
|
281
|
+
}
|
|
282
|
+
if (typeof content === "string") {
|
|
283
|
+
return content;
|
|
284
|
+
}
|
|
285
|
+
return content.filter((p) => p.type === "text").map((p) => p.content).join("");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function createGrokText(model, apiKey, config) {
|
|
289
|
+
return new GrokTextAdapter({ apiKey, ...config }, model);
|
|
290
|
+
}
|
|
291
|
+
function grokText(model, config) {
|
|
292
|
+
const apiKey = getGrokApiKeyFromEnv();
|
|
293
|
+
return createGrokText(model, apiKey, config);
|
|
294
|
+
}
|
|
295
|
+
export {
|
|
296
|
+
GrokTextAdapter,
|
|
297
|
+
createGrokText,
|
|
298
|
+
grokText
|
|
299
|
+
};
|
|
300
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +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\n try {\n const stream = await this.client.chat.completions.create({\n ...requestParams,\n stream: true,\n })\n\n yield* this.processGrokStreamChunks(stream, options)\n } catch (error: unknown) {\n const err = error as Error\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 throw error\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 ): AsyncIterable<StreamChunk> {\n let accumulatedContent = ''\n const timestamp = Date.now()\n let responseId = generateId(this.name)\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 }\n >()\n\n try {\n for await (const chunk of stream) {\n responseId = chunk.id || responseId\n const choice = chunk.choices[0]\n\n if (!choice) continue\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 accumulatedContent += deltaContent\n yield {\n type: 'content',\n id: responseId,\n model: chunk.model || options.model,\n timestamp,\n delta: deltaContent,\n content: accumulatedContent,\n role: 'assistant',\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 })\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 }\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 [index, toolCall] of toolCallsInProgress) {\n yield {\n type: 'tool_call',\n id: responseId,\n model: chunk.model || options.model,\n timestamp,\n index,\n toolCall: {\n id: toolCall.id,\n type: 'function',\n function: {\n name: toolCall.name,\n arguments: toolCall.arguments,\n },\n },\n }\n }\n }\n\n yield {\n type: 'done',\n id: responseId,\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:\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ? 'tool_calls'\n : 'stop',\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 yield {\n type: 'error',\n id: responseId,\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 parts.push({\n type: 'image_url',\n image_url: {\n url: part.source.value,\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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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grok Image Generation Provider Options
|
|
3
|
+
*
|
|
4
|
+
* These are provider-specific options for Grok image generation.
|
|
5
|
+
* Grok uses the grok-2-image-1212 model for image generation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Supported sizes for grok-2-image-1212 model
|
|
9
|
+
*/
|
|
10
|
+
export type GrokImageSize = '1024x1024' | '1536x1024' | '1024x1536';
|
|
11
|
+
/**
|
|
12
|
+
* Base provider options for Grok image models
|
|
13
|
+
*/
|
|
14
|
+
export interface GrokImageBaseProviderOptions {
|
|
15
|
+
/**
|
|
16
|
+
* A unique identifier representing your end-user.
|
|
17
|
+
* Can help xAI to monitor and detect abuse.
|
|
18
|
+
*/
|
|
19
|
+
user?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Provider options for grok-2-image-1212 model
|
|
23
|
+
*/
|
|
24
|
+
export interface GrokImageProviderOptions extends GrokImageBaseProviderOptions {
|
|
25
|
+
/**
|
|
26
|
+
* The quality of the image.
|
|
27
|
+
* @default 'standard'
|
|
28
|
+
*/
|
|
29
|
+
quality?: 'standard' | 'hd';
|
|
30
|
+
/**
|
|
31
|
+
* The format in which generated images are returned.
|
|
32
|
+
* URLs are only valid for 60 minutes after generation.
|
|
33
|
+
* @default 'url'
|
|
34
|
+
*/
|
|
35
|
+
response_format?: 'url' | 'b64_json';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Type-only map from model name to its specific provider options.
|
|
39
|
+
*/
|
|
40
|
+
export type GrokImageModelProviderOptionsByName = {
|
|
41
|
+
'grok-2-image-1212': GrokImageProviderOptions;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Type-only map from model name to its supported sizes.
|
|
45
|
+
*/
|
|
46
|
+
export type GrokImageModelSizeByName = {
|
|
47
|
+
'grok-2-image-1212': GrokImageSize;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Internal options interface for validation
|
|
51
|
+
*/
|
|
52
|
+
interface ImageValidationOptions {
|
|
53
|
+
prompt: string;
|
|
54
|
+
model: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validates that the provided size is supported by the model.
|
|
58
|
+
* Throws a descriptive error if the size is not supported.
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateImageSize(model: string, size: string | undefined): void;
|
|
61
|
+
/**
|
|
62
|
+
* Validates that the number of images is within bounds for the model.
|
|
63
|
+
*/
|
|
64
|
+
export declare function validateNumberOfImages(_model: string, numberOfImages: number | undefined): void;
|
|
65
|
+
export declare const validatePrompt: (options: ImageValidationOptions) => void;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function validateImageSize(model, size) {
|
|
2
|
+
if (!size) return;
|
|
3
|
+
const validSizes = {
|
|
4
|
+
"grok-2-image-1212": ["1024x1024", "1536x1024", "1024x1536"]
|
|
5
|
+
};
|
|
6
|
+
const modelSizes = validSizes[model];
|
|
7
|
+
if (!modelSizes) {
|
|
8
|
+
throw new Error(`Unknown image model: ${model}`);
|
|
9
|
+
}
|
|
10
|
+
if (!modelSizes.includes(size)) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
`Size "${size}" is not supported by model "${model}". Supported sizes: ${modelSizes.join(", ")}`
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function validateNumberOfImages(_model, numberOfImages) {
|
|
17
|
+
if (numberOfImages === void 0) return;
|
|
18
|
+
if (numberOfImages < 1 || numberOfImages > 10) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`Number of images must be between 1 and 10. Requested: ${numberOfImages}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const validatePrompt = (options) => {
|
|
25
|
+
if (options.prompt.length === 0) {
|
|
26
|
+
throw new Error("Prompt cannot be empty.");
|
|
27
|
+
}
|
|
28
|
+
if (options.prompt.length > 4e3) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
"For grok-2-image-1212, prompt length must be less than or equal to 4000 characters."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
validateImageSize,
|
|
36
|
+
validateNumberOfImages,
|
|
37
|
+
validatePrompt
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=image-provider-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-provider-options.js","sources":["../../../src/image/image-provider-options.ts"],"sourcesContent":["/**\n * Grok Image Generation Provider Options\n *\n * These are provider-specific options for Grok image generation.\n * Grok uses the grok-2-image-1212 model for image generation.\n */\n\n/**\n * Supported sizes for grok-2-image-1212 model\n */\nexport type GrokImageSize = '1024x1024' | '1536x1024' | '1024x1536'\n\n/**\n * Base provider options for Grok image models\n */\nexport interface GrokImageBaseProviderOptions {\n /**\n * A unique identifier representing your end-user.\n * Can help xAI to monitor and detect abuse.\n */\n user?: string\n}\n\n/**\n * Provider options for grok-2-image-1212 model\n */\nexport interface GrokImageProviderOptions extends GrokImageBaseProviderOptions {\n /**\n * The quality of the image.\n * @default 'standard'\n */\n quality?: 'standard' | 'hd'\n\n /**\n * The format in which generated images are returned.\n * URLs are only valid for 60 minutes after generation.\n * @default 'url'\n */\n response_format?: 'url' | 'b64_json'\n}\n\n/**\n * Type-only map from model name to its specific provider options.\n */\nexport type GrokImageModelProviderOptionsByName = {\n 'grok-2-image-1212': GrokImageProviderOptions\n}\n\n/**\n * Type-only map from model name to its supported sizes.\n */\nexport type GrokImageModelSizeByName = {\n 'grok-2-image-1212': GrokImageSize\n}\n\n/**\n * Internal options interface for validation\n */\ninterface ImageValidationOptions {\n prompt: string\n model: string\n}\n\n/**\n * Validates that the provided size is supported by the model.\n * Throws a descriptive error if the size is not supported.\n */\nexport function validateImageSize(\n model: string,\n size: string | undefined,\n): void {\n if (!size) return\n\n const validSizes: Record<string, Array<string>> = {\n 'grok-2-image-1212': ['1024x1024', '1536x1024', '1024x1536'],\n }\n\n const modelSizes = validSizes[model]\n if (!modelSizes) {\n throw new Error(`Unknown image model: ${model}`)\n }\n\n if (!modelSizes.includes(size)) {\n throw new Error(\n `Size \"${size}\" is not supported by model \"${model}\". ` +\n `Supported sizes: ${modelSizes.join(', ')}`,\n )\n }\n}\n\n/**\n * Validates that the number of images is within bounds for the model.\n */\nexport function validateNumberOfImages(\n _model: string,\n numberOfImages: number | undefined,\n): void {\n if (numberOfImages === undefined) return\n\n // grok-2-image-1212 supports 1-10 images per request\n if (numberOfImages < 1 || numberOfImages > 10) {\n throw new Error(\n `Number of images must be between 1 and 10. Requested: ${numberOfImages}`,\n )\n }\n}\n\nexport const validatePrompt = (options: ImageValidationOptions) => {\n if (options.prompt.length === 0) {\n throw new Error('Prompt cannot be empty.')\n }\n // Grok image model supports up to 4000 characters\n if (options.prompt.length > 4000) {\n throw new Error(\n 'For grok-2-image-1212, prompt length must be less than or equal to 4000 characters.',\n )\n }\n}\n"],"names":[],"mappings":"AAmEO,SAAS,kBACd,OACA,MACM;AACN,MAAI,CAAC,KAAM;AAEX,QAAM,aAA4C;AAAA,IAChD,qBAAqB,CAAC,aAAa,aAAa,WAAW;AAAA,EAAA;AAG7D,QAAM,aAAa,WAAW,KAAK;AACnC,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,wBAAwB,KAAK,EAAE;AAAA,EACjD;AAEA,MAAI,CAAC,WAAW,SAAS,IAAI,GAAG;AAC9B,UAAM,IAAI;AAAA,MACR,SAAS,IAAI,gCAAgC,KAAK,uBAC5B,WAAW,KAAK,IAAI,CAAC;AAAA,IAAA;AAAA,EAE/C;AACF;AAKO,SAAS,uBACd,QACA,gBACM;AACN,MAAI,mBAAmB,OAAW;AAGlC,MAAI,iBAAiB,KAAK,iBAAiB,IAAI;AAC7C,UAAM,IAAI;AAAA,MACR,yDAAyD,cAAc;AAAA,IAAA;AAAA,EAE3E;AACF;AAEO,MAAM,iBAAiB,CAAC,YAAoC;AACjE,MAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,MAAI,QAAQ,OAAO,SAAS,KAAM;AAChC,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { GrokTextAdapter, createGrokText, grokText, type GrokTextConfig, type GrokTextProviderOptions, } from './adapters/text.js';
|
|
2
|
+
export { GrokSummarizeAdapter, createGrokSummarize, grokSummarize, type GrokSummarizeConfig, type GrokSummarizeProviderOptions, type GrokSummarizeModel, } from './adapters/summarize.js';
|
|
3
|
+
export { GrokImageAdapter, createGrokImage, grokImage, type GrokImageConfig, type GrokImageModel, } from './adapters/image.js';
|
|
4
|
+
export type { GrokImageProviderOptions, GrokImageModelProviderOptionsByName, } from './image/image-provider-options.js';
|
|
5
|
+
export type { GrokChatModelProviderOptionsByName, GrokModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, } from './model-meta.js';
|
|
6
|
+
export { GROK_CHAT_MODELS, GROK_IMAGE_MODELS } from './model-meta.js';
|
|
7
|
+
export type { GrokTextMetadata, GrokImageMetadata, GrokAudioMetadata, GrokVideoMetadata, GrokDocumentMetadata, GrokMessageMetadataByModality, } from './message-types.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GrokTextAdapter, createGrokText, grokText } from "./adapters/text.js";
|
|
2
|
+
import { GrokSummarizeAdapter, createGrokSummarize, grokSummarize } from "./adapters/summarize.js";
|
|
3
|
+
import { GrokImageAdapter, createGrokImage, grokImage } from "./adapters/image.js";
|
|
4
|
+
import { GROK_CHAT_MODELS, GROK_IMAGE_MODELS } from "./model-meta.js";
|
|
5
|
+
export {
|
|
6
|
+
GROK_CHAT_MODELS,
|
|
7
|
+
GROK_IMAGE_MODELS,
|
|
8
|
+
GrokImageAdapter,
|
|
9
|
+
GrokSummarizeAdapter,
|
|
10
|
+
GrokTextAdapter,
|
|
11
|
+
createGrokImage,
|
|
12
|
+
createGrokSummarize,
|
|
13
|
+
createGrokText,
|
|
14
|
+
grokImage,
|
|
15
|
+
grokSummarize,
|
|
16
|
+
grokText
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grok-specific metadata types for multimodal content parts.
|
|
3
|
+
* These types extend the base ContentPart metadata with Grok-specific options.
|
|
4
|
+
*
|
|
5
|
+
* Grok uses an OpenAI-compatible API, so metadata types are similar to OpenAI.
|
|
6
|
+
*
|
|
7
|
+
* @see https://docs.x.ai
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Metadata for Grok image content parts.
|
|
11
|
+
* Controls how the model processes and analyzes images.
|
|
12
|
+
*/
|
|
13
|
+
export interface GrokImageMetadata {
|
|
14
|
+
/**
|
|
15
|
+
* Controls how the model processes the image.
|
|
16
|
+
* - 'auto': Let the model decide based on image size and content
|
|
17
|
+
* - 'low': Use low resolution processing (faster, cheaper, less detail)
|
|
18
|
+
* - 'high': Use high resolution processing (slower, more expensive, more detail)
|
|
19
|
+
*
|
|
20
|
+
* @default 'auto'
|
|
21
|
+
*/
|
|
22
|
+
detail?: 'auto' | 'low' | 'high';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Metadata for Grok audio content parts.
|
|
26
|
+
* Specifies the audio format for proper processing.
|
|
27
|
+
*/
|
|
28
|
+
export interface GrokAudioMetadata {
|
|
29
|
+
/**
|
|
30
|
+
* The format of the audio.
|
|
31
|
+
* Supported formats: mp3, wav, flac, etc.
|
|
32
|
+
* @default 'mp3'
|
|
33
|
+
*/
|
|
34
|
+
format?: 'mp3' | 'wav' | 'flac' | 'ogg' | 'webm' | 'aac';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Metadata for Grok video content parts.
|
|
38
|
+
* Note: Video support in Grok is limited; check current API capabilities.
|
|
39
|
+
*/
|
|
40
|
+
export interface GrokVideoMetadata {
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Metadata for Grok document content parts.
|
|
44
|
+
* Note: Direct document support may vary; PDFs often need to be converted to images.
|
|
45
|
+
*/
|
|
46
|
+
export interface GrokDocumentMetadata {
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Metadata for Grok text content parts.
|
|
50
|
+
* Currently no specific metadata options for text in Grok.
|
|
51
|
+
*/
|
|
52
|
+
export interface GrokTextMetadata {
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Map of modality types to their Grok-specific metadata types.
|
|
56
|
+
* Used for type inference when constructing multimodal messages.
|
|
57
|
+
*/
|
|
58
|
+
export interface GrokMessageMetadataByModality {
|
|
59
|
+
text: GrokTextMetadata;
|
|
60
|
+
image: GrokImageMetadata;
|
|
61
|
+
audio: GrokAudioMetadata;
|
|
62
|
+
video: GrokVideoMetadata;
|
|
63
|
+
document: GrokDocumentMetadata;
|
|
64
|
+
}
|