@tanstack/ai-groq 0.1.4 → 0.1.6
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 +8 -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 +32 -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 +63 -29
- package/src/index.ts +1 -0
- package/src/model-meta.ts +34 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { BaseTextAdapter, StructuredOutputOptions, StructuredOutputResult } from '@tanstack/ai/adapters';
|
|
2
|
-
import { GROQ_CHAT_MODELS, ResolveInputModalities, ResolveProviderOptions } from '../model-meta.js';
|
|
3
|
-
import { StreamChunk, TextOptions } from '@tanstack/ai';
|
|
2
|
+
import { GROQ_CHAT_MODELS, GroqChatModelToolCapabilitiesByName, ResolveInputModalities, ResolveProviderOptions } from '../model-meta.js';
|
|
3
|
+
import { Modality, StreamChunk, TextOptions } from '@tanstack/ai';
|
|
4
|
+
import { ExternalTextProviderOptions } from '../text/text-provider-options.js';
|
|
4
5
|
import { GroqMessageMetadataByModality } from '../message-types.js';
|
|
5
6
|
import { GroqClientConfig } from '../utils.js';
|
|
7
|
+
type GroqTextProviderOptions = ExternalTextProviderOptions;
|
|
8
|
+
type ResolveToolCapabilities<TModel extends string> = TModel extends keyof GroqChatModelToolCapabilitiesByName ? NonNullable<GroqChatModelToolCapabilitiesByName[TModel]> : readonly [];
|
|
6
9
|
/**
|
|
7
10
|
* Configuration for Groq text adapter
|
|
8
11
|
*/
|
|
@@ -18,12 +21,12 @@ export type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../
|
|
|
18
21
|
* Tree-shakeable adapter for Groq chat/text completion functionality.
|
|
19
22
|
* Uses the Groq SDK which provides an OpenAI-compatible Chat Completions API.
|
|
20
23
|
*/
|
|
21
|
-
export declare class GroqTextAdapter<TModel extends (typeof GROQ_CHAT_MODELS)[number]
|
|
24
|
+
export declare class GroqTextAdapter<TModel extends (typeof GROQ_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, GroqMessageMetadataByModality, TToolCapabilities> {
|
|
22
25
|
readonly kind: "text";
|
|
23
26
|
readonly name: "groq";
|
|
24
27
|
private client;
|
|
25
28
|
constructor(config: GroqTextConfig, model: TModel);
|
|
26
|
-
chatStream(options: TextOptions<
|
|
29
|
+
chatStream(options: TextOptions<GroqTextProviderOptions>): AsyncIterable<StreamChunk>;
|
|
27
30
|
/**
|
|
28
31
|
* Generate structured output using Groq's JSON Schema response format.
|
|
29
32
|
* Uses stream: false to get the complete response in one call.
|
|
@@ -36,7 +39,7 @@ export declare class GroqTextAdapter<TModel extends (typeof GROQ_CHAT_MODELS)[nu
|
|
|
36
39
|
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
37
40
|
* We apply Groq-specific transformations for structured output compatibility.
|
|
38
41
|
*/
|
|
39
|
-
structuredOutput(options: StructuredOutputOptions<
|
|
42
|
+
structuredOutput(options: StructuredOutputOptions<GroqTextProviderOptions>): Promise<StructuredOutputResult<unknown>>;
|
|
40
43
|
/**
|
|
41
44
|
* Processes streaming chunks from the Groq API and yields AG-UI stream events.
|
|
42
45
|
* Handles text content deltas, tool call assembly, and lifecycle events.
|
|
@@ -3,6 +3,7 @@ import { validateTextProviderOptions } from "../text/text-provider-options.js";
|
|
|
3
3
|
import { makeGroqStructuredOutputCompatible, transformNullsToUndefined } from "../utils/schema-converter.js";
|
|
4
4
|
import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
|
|
5
5
|
import { createGroqClient, generateId, getGroqApiKeyFromEnv } from "../utils/client.js";
|
|
6
|
+
const asChunk = (chunk) => chunk;
|
|
6
7
|
class GroqTextAdapter extends BaseTextAdapter {
|
|
7
8
|
constructor(config, model) {
|
|
8
9
|
super({}, model);
|
|
@@ -14,7 +15,8 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
14
15
|
const requestParams = this.mapTextOptionsToGroq(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 GroqTextAdapter 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);
|
|
@@ -120,12 +125,13 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
120
125
|
if (!choice) continue;
|
|
121
126
|
if (!aguiState.hasEmittedRunStarted) {
|
|
122
127
|
aguiState.hasEmittedRunStarted = true;
|
|
123
|
-
yield {
|
|
128
|
+
yield asChunk({
|
|
124
129
|
type: "RUN_STARTED",
|
|
125
130
|
runId: aguiState.runId,
|
|
131
|
+
threadId: aguiState.threadId,
|
|
126
132
|
model: chunk.model || options.model,
|
|
127
133
|
timestamp
|
|
128
|
-
};
|
|
134
|
+
});
|
|
129
135
|
}
|
|
130
136
|
const delta = choice.delta;
|
|
131
137
|
const deltaContent = delta.content;
|
|
@@ -133,23 +139,23 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
133
139
|
if (deltaContent) {
|
|
134
140
|
if (!hasEmittedTextMessageStart) {
|
|
135
141
|
hasEmittedTextMessageStart = true;
|
|
136
|
-
yield {
|
|
142
|
+
yield asChunk({
|
|
137
143
|
type: "TEXT_MESSAGE_START",
|
|
138
144
|
messageId: aguiState.messageId,
|
|
139
145
|
model: chunk.model || options.model,
|
|
140
146
|
timestamp,
|
|
141
147
|
role: "assistant"
|
|
142
|
-
};
|
|
148
|
+
});
|
|
143
149
|
}
|
|
144
150
|
accumulatedContent += deltaContent;
|
|
145
|
-
yield {
|
|
151
|
+
yield asChunk({
|
|
146
152
|
type: "TEXT_MESSAGE_CONTENT",
|
|
147
153
|
messageId: aguiState.messageId,
|
|
148
154
|
model: chunk.model || options.model,
|
|
149
155
|
timestamp,
|
|
150
156
|
delta: deltaContent,
|
|
151
157
|
content: accumulatedContent
|
|
152
|
-
};
|
|
158
|
+
});
|
|
153
159
|
}
|
|
154
160
|
if (deltaToolCalls) {
|
|
155
161
|
for (const toolCallDelta of deltaToolCalls) {
|
|
@@ -174,23 +180,24 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
174
180
|
}
|
|
175
181
|
if (toolCall.id && toolCall.name && !toolCall.started) {
|
|
176
182
|
toolCall.started = true;
|
|
177
|
-
yield {
|
|
183
|
+
yield asChunk({
|
|
178
184
|
type: "TOOL_CALL_START",
|
|
179
185
|
toolCallId: toolCall.id,
|
|
186
|
+
toolCallName: toolCall.name,
|
|
180
187
|
toolName: toolCall.name,
|
|
181
188
|
model: chunk.model || options.model,
|
|
182
189
|
timestamp,
|
|
183
190
|
index
|
|
184
|
-
};
|
|
191
|
+
});
|
|
185
192
|
}
|
|
186
193
|
if (toolCallDelta.function?.arguments && toolCall.started) {
|
|
187
|
-
yield {
|
|
194
|
+
yield asChunk({
|
|
188
195
|
type: "TOOL_CALL_ARGS",
|
|
189
196
|
toolCallId: toolCall.id,
|
|
190
197
|
model: chunk.model || options.model,
|
|
191
198
|
timestamp,
|
|
192
199
|
delta: toolCallDelta.function.arguments
|
|
193
|
-
};
|
|
200
|
+
});
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
}
|
|
@@ -206,29 +213,31 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
206
213
|
} catch {
|
|
207
214
|
parsedInput = {};
|
|
208
215
|
}
|
|
209
|
-
yield {
|
|
216
|
+
yield asChunk({
|
|
210
217
|
type: "TOOL_CALL_END",
|
|
211
218
|
toolCallId: toolCall.id,
|
|
219
|
+
toolCallName: toolCall.name,
|
|
212
220
|
toolName: toolCall.name,
|
|
213
221
|
model: chunk.model || options.model,
|
|
214
222
|
timestamp,
|
|
215
223
|
input: parsedInput
|
|
216
|
-
};
|
|
224
|
+
});
|
|
217
225
|
}
|
|
218
226
|
}
|
|
219
227
|
const computedFinishReason = choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0 ? "tool_calls" : choice.finish_reason === "length" ? "length" : "stop";
|
|
220
228
|
if (hasEmittedTextMessageStart) {
|
|
221
|
-
yield {
|
|
229
|
+
yield asChunk({
|
|
222
230
|
type: "TEXT_MESSAGE_END",
|
|
223
231
|
messageId: aguiState.messageId,
|
|
224
232
|
model: chunk.model || options.model,
|
|
225
233
|
timestamp
|
|
226
|
-
};
|
|
234
|
+
});
|
|
227
235
|
}
|
|
228
236
|
const groqUsage = chunk.x_groq?.usage;
|
|
229
|
-
yield {
|
|
237
|
+
yield asChunk({
|
|
230
238
|
type: "RUN_FINISHED",
|
|
231
239
|
runId: aguiState.runId,
|
|
240
|
+
threadId: aguiState.threadId,
|
|
232
241
|
model: chunk.model || options.model,
|
|
233
242
|
timestamp,
|
|
234
243
|
usage: groqUsage ? {
|
|
@@ -237,22 +246,24 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
237
246
|
totalTokens: groqUsage.total_tokens || 0
|
|
238
247
|
} : void 0,
|
|
239
248
|
finishReason: computedFinishReason
|
|
240
|
-
};
|
|
249
|
+
});
|
|
241
250
|
}
|
|
242
251
|
}
|
|
243
252
|
} catch (error) {
|
|
244
253
|
const err = error;
|
|
245
254
|
console.log("[Groq Adapter] Stream ended with error:", err.message);
|
|
246
|
-
yield {
|
|
255
|
+
yield asChunk({
|
|
247
256
|
type: "RUN_ERROR",
|
|
248
257
|
runId: aguiState.runId,
|
|
249
258
|
model: options.model,
|
|
250
259
|
timestamp,
|
|
260
|
+
message: err.message || "Unknown error occurred",
|
|
261
|
+
code: err.code,
|
|
251
262
|
error: {
|
|
252
263
|
message: err.message || "Unknown error occurred",
|
|
253
264
|
code: err.code
|
|
254
265
|
}
|
|
255
|
-
};
|
|
266
|
+
});
|
|
256
267
|
}
|
|
257
268
|
}
|
|
258
269
|
/**
|
|
@@ -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 createGroqClient,\n generateId,\n getGroqApiKeyFromEnv,\n makeGroqStructuredOutputCompatible,\n transformNullsToUndefined,\n} from '../utils'\nimport type {\n GROQ_CHAT_MODELS,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type GROQ_SDK from 'groq-sdk'\nimport type { ChatCompletionCreateParamsStreaming } from 'groq-sdk/resources/chat/completions'\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 ChatCompletionContentPart,\n ChatCompletionMessageParam,\n GroqImageMetadata,\n GroqMessageMetadataByModality,\n} from '../message-types'\nimport type { GroqClientConfig } from '../utils'\n\n/**\n * Configuration for Groq text adapter\n */\nexport interface GroqTextConfig extends GroqClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Groq Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Groq chat/text completion functionality.\n * Uses the Groq SDK which provides an OpenAI-compatible Chat Completions API.\n */\nexport class GroqTextAdapter<\n TModel extends (typeof GROQ_CHAT_MODELS)[number],\n> extends BaseTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>,\n GroqMessageMetadataByModality\n> {\n readonly kind = 'text' as const\n readonly name = 'groq' as const\n\n private client: GROQ_SDK\n\n constructor(config: GroqTextConfig, model: TModel) {\n super({}, model)\n this.client = createGroqClient(config)\n }\n\n async *chatStream(\n options: TextOptions<ResolveProviderOptions<TModel>>,\n ): AsyncIterable<StreamChunk> {\n const requestParams = this.mapTextOptionsToGroq(options)\n const timestamp = Date.now()\n\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.processGroqStreamChunks(stream, options, aguiState)\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n\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 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 Groq's JSON Schema response format.\n * Uses stream: false to get the complete response in one call.\n *\n * Groq has strict requirements for structured output:\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 Groq-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.mapTextOptionsToGroq(chatOptions)\n\n const jsonSchema = makeGroqStructuredOutputCompatible(\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 const rawText = response.choices[0]?.message.content || ''\n\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 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 /**\n * Processes streaming chunks from the Groq API and yields AG-UI stream events.\n * Handles text content deltas, tool call assembly, and lifecycle events.\n */\n private async *processGroqStreamChunks(\n stream: AsyncIterable<GROQ_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 const toolCallsInProgress = new Map<\n number,\n {\n id: string\n name: string\n arguments: string\n started: boolean\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 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 if (deltaContent) {\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 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 if (deltaToolCalls) {\n for (const toolCallDelta of deltaToolCalls) {\n const index = toolCallDelta.index\n\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 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 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 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 if (choice.finish_reason) {\n if (\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ) {\n for (const [, toolCall] of toolCallsInProgress) {\n if (!toolCall.started || !toolCall.id || !toolCall.name) {\n continue\n }\n\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.arguments\n ? JSON.parse(toolCall.arguments)\n : {}\n } catch {\n parsedInput = {}\n }\n\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 : choice.finish_reason === 'length'\n ? 'length'\n : 'stop'\n\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 const groqUsage = chunk.x_groq?.usage\n\n yield {\n type: 'RUN_FINISHED',\n runId: aguiState.runId,\n model: chunk.model || options.model,\n timestamp,\n usage: groqUsage\n ? {\n promptTokens: groqUsage.prompt_tokens || 0,\n completionTokens: groqUsage.completion_tokens || 0,\n totalTokens: groqUsage.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('[Groq Adapter] Stream ended with error:', err.message)\n\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 TextOptions to Groq-specific Chat Completions request parameters.\n */\n private mapTextOptionsToGroq(\n options: TextOptions,\n ): 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 const messages: Array<ChatCompletionMessageParam> = []\n\n if (options.systemPrompts && options.systemPrompts.length > 0) {\n messages.push({\n role: 'system',\n content: options.systemPrompts.join('\\n'),\n })\n }\n\n for (const message of options.messages) {\n messages.push(this.convertMessageToGroq(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,\n stream: true,\n }\n }\n\n /**\n * Converts a TanStack AI ModelMessage to a Groq ChatCompletionMessageParam.\n * Handles tool, assistant, and user messages including multimodal content.\n */\n private convertMessageToGroq(\n message: ModelMessage,\n ): ChatCompletionMessageParam {\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 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 const contentParts = this.normalizeContent(message.content)\n\n if (contentParts.length === 1 && contentParts[0]?.type === 'text') {\n return {\n role: 'user',\n content: contentParts[0].content,\n }\n }\n\n const parts: Array<ChatCompletionContentPart> = []\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 GroqImageMetadata | undefined\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 return content\n .filter((p) => p.type === 'text')\n .map((p) => p.content)\n .join('')\n }\n}\n\n/**\n * Creates a Groq text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')\n * @param apiKey - Your Groq API key\n * @param config - Optional additional configuration\n * @returns Configured Groq text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGroqText('llama-3.3-70b-versatile', \"gsk_...\");\n * // adapter has type-safe providerOptions for llama-3.3-70b-versatile\n * ```\n */\nexport function createGroqText<\n TModel extends (typeof GROQ_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GroqTextConfig, 'apiKey'>,\n): GroqTextAdapter<TModel> {\n return new GroqTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Groq text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `GROQ_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Groq text adapter instance with resolved types\n * @throws Error if GROQ_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses GROQ_API_KEY from environment\n * const adapter = groqText('llama-3.3-70b-versatile');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function groqText<TModel extends (typeof GROQ_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GroqTextConfig, 'apiKey'>,\n): GroqTextAdapter<TModel> {\n const apiKey = getGroqApiKeyFromEnv()\n return createGroqText(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 createGroqClient,\n generateId,\n getGroqApiKeyFromEnv,\n makeGroqStructuredOutputCompatible,\n transformNullsToUndefined,\n} from '../utils'\nimport type {\n GROQ_CHAT_MODELS,\n GroqChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type GROQ_SDK from 'groq-sdk'\nimport type { ChatCompletionCreateParamsStreaming } from 'groq-sdk/resources/chat/completions'\nimport type {\n ContentPart,\n Modality,\n ModelMessage,\n StreamChunk,\n TextOptions,\n} from '@tanstack/ai'\nimport type {\n ExternalTextProviderOptions,\n InternalTextProviderOptions,\n} from '../text/text-provider-options'\nimport type {\n ChatCompletionContentPart,\n ChatCompletionMessageParam,\n GroqImageMetadata,\n GroqMessageMetadataByModality,\n} from '../message-types'\nimport type { GroqClientConfig } from '../utils'\n\ntype GroqTextProviderOptions = ExternalTextProviderOptions\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GroqChatModelToolCapabilitiesByName\n ? NonNullable<GroqChatModelToolCapabilitiesByName[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 Groq text adapter\n */\nexport interface GroqTextConfig extends GroqClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Groq Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Groq chat/text completion functionality.\n * Uses the Groq SDK which provides an OpenAI-compatible Chat Completions API.\n */\nexport class GroqTextAdapter<\n TModel extends (typeof GROQ_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 GroqMessageMetadataByModality,\n TToolCapabilities\n> {\n readonly kind = 'text' as const\n readonly name = 'groq' as const\n\n private client: GROQ_SDK\n\n constructor(config: GroqTextConfig, model: TModel) {\n super({}, model)\n this.client = createGroqClient(config)\n }\n\n async *chatStream(\n options: TextOptions<GroqTextProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const requestParams = this.mapTextOptionsToGroq(options)\n const timestamp = Date.now()\n\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.processGroqStreamChunks(stream, options, aguiState)\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n\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 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 Groq's JSON Schema response format.\n * Uses stream: false to get the complete response in one call.\n *\n * Groq has strict requirements for structured output:\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 Groq-specific transformations for structured output compatibility.\n */\n async structuredOutput(\n options: StructuredOutputOptions<GroqTextProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n const requestParams = this.mapTextOptionsToGroq(chatOptions)\n\n const jsonSchema = makeGroqStructuredOutputCompatible(\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 const rawText = response.choices[0]?.message.content || ''\n\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 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 /**\n * Processes streaming chunks from the Groq API and yields AG-UI stream events.\n * Handles text content deltas, tool call assembly, and lifecycle events.\n */\n private async *processGroqStreamChunks(\n stream: AsyncIterable<GROQ_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 const toolCallsInProgress = new Map<\n number,\n {\n id: string\n name: string\n arguments: string\n started: boolean\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 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 if (deltaContent) {\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 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 if (deltaToolCalls) {\n for (const toolCallDelta of deltaToolCalls) {\n const index = toolCallDelta.index\n\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 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 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 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 if (choice.finish_reason) {\n if (\n choice.finish_reason === 'tool_calls' ||\n toolCallsInProgress.size > 0\n ) {\n for (const [, toolCall] of toolCallsInProgress) {\n if (!toolCall.started || !toolCall.id || !toolCall.name) {\n continue\n }\n\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.arguments\n ? JSON.parse(toolCall.arguments)\n : {}\n } catch {\n parsedInput = {}\n }\n\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 : choice.finish_reason === 'length'\n ? 'length'\n : 'stop'\n\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 const groqUsage = chunk.x_groq?.usage\n\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: groqUsage\n ? {\n promptTokens: groqUsage.prompt_tokens || 0,\n completionTokens: groqUsage.completion_tokens || 0,\n totalTokens: groqUsage.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('[Groq Adapter] Stream ended with error:', err.message)\n\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 TextOptions to Groq-specific Chat Completions request parameters.\n */\n private mapTextOptionsToGroq(\n options: TextOptions,\n ): 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 const messages: Array<ChatCompletionMessageParam> = []\n\n if (options.systemPrompts && options.systemPrompts.length > 0) {\n messages.push({\n role: 'system',\n content: options.systemPrompts.join('\\n'),\n })\n }\n\n for (const message of options.messages) {\n messages.push(this.convertMessageToGroq(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,\n stream: true,\n }\n }\n\n /**\n * Converts a TanStack AI ModelMessage to a Groq ChatCompletionMessageParam.\n * Handles tool, assistant, and user messages including multimodal content.\n */\n private convertMessageToGroq(\n message: ModelMessage,\n ): ChatCompletionMessageParam {\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 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 const contentParts = this.normalizeContent(message.content)\n\n if (contentParts.length === 1 && contentParts[0]?.type === 'text') {\n return {\n role: 'user',\n content: contentParts[0].content,\n }\n }\n\n const parts: Array<ChatCompletionContentPart> = []\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 GroqImageMetadata | undefined\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 return content\n .filter((p) => p.type === 'text')\n .map((p) => p.content)\n .join('')\n }\n}\n\n/**\n * Creates a Groq text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')\n * @param apiKey - Your Groq API key\n * @param config - Optional additional configuration\n * @returns Configured Groq text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGroqText('llama-3.3-70b-versatile', \"gsk_...\");\n * // adapter has type-safe providerOptions for llama-3.3-70b-versatile\n * ```\n */\nexport function createGroqText<\n TModel extends (typeof GROQ_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GroqTextConfig, 'apiKey'>,\n): GroqTextAdapter<TModel> {\n return new GroqTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Groq text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `GROQ_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Groq text adapter instance with resolved types\n * @throws Error if GROQ_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses GROQ_API_KEY from environment\n * const adapter = groqText('llama-3.3-70b-versatile');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function groqText<TModel extends (typeof GROQ_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GroqTextConfig, 'apiKey'>,\n): GroqTextAdapter<TModel> {\n const apiKey = getGroqApiKeyFromEnv()\n return createGroqText(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* Provides tree-shakeable adapters for Groq's Chat Completions API.
|
|
6
6
|
*/
|
|
7
7
|
export { GroqTextAdapter, createGroqText, groqText, type GroqTextConfig, type GroqTextProviderOptions, } from './adapters/text.js';
|
|
8
|
-
export type { GroqChatModelProviderOptionsByName, GroqModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, GroqChatModels, } from './model-meta.js';
|
|
8
|
+
export type { GroqChatModelProviderOptionsByName, GroqChatModelToolCapabilitiesByName, GroqModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, GroqChatModels, } from './model-meta.js';
|
|
9
9
|
export { GROQ_CHAT_MODELS } from './model-meta.js';
|
|
10
10
|
export type { GroqTextMetadata, GroqImageMetadata, GroqAudioMetadata, GroqVideoMetadata, GroqDocumentMetadata, GroqMessageMetadataByModality, } from './message-types.js';
|
package/dist/esm/model-meta.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ declare const LLAMA_3_3_70B_VERSATILE: {
|
|
|
16
16
|
readonly output: ["text"];
|
|
17
17
|
readonly endpoints: ["chat"];
|
|
18
18
|
readonly features: ["streaming", "tools", "json_object"];
|
|
19
|
+
readonly tools: readonly [];
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
22
|
declare const LLAMA_4_MAVERICK_17B_128E_INSTRUCT: {
|
|
@@ -35,6 +36,7 @@ declare const LLAMA_4_MAVERICK_17B_128E_INSTRUCT: {
|
|
|
35
36
|
readonly output: ["text"];
|
|
36
37
|
readonly endpoints: ["chat"];
|
|
37
38
|
readonly features: ["streaming", "tools", "json_object", "json_schema", "vision"];
|
|
39
|
+
readonly tools: readonly [];
|
|
38
40
|
};
|
|
39
41
|
};
|
|
40
42
|
declare const LLAMA_4_SCOUT_17B_16E_INSTRUCT: {
|
|
@@ -54,6 +56,7 @@ declare const LLAMA_4_SCOUT_17B_16E_INSTRUCT: {
|
|
|
54
56
|
readonly output: ["text"];
|
|
55
57
|
readonly endpoints: ["chat"];
|
|
56
58
|
readonly features: ["streaming", "tools", "json_object"];
|
|
59
|
+
readonly tools: readonly [];
|
|
57
60
|
};
|
|
58
61
|
};
|
|
59
62
|
declare const LLAMA_GUARD_4_12B: {
|
|
@@ -73,6 +76,7 @@ declare const LLAMA_GUARD_4_12B: {
|
|
|
73
76
|
readonly output: ["text"];
|
|
74
77
|
readonly endpoints: ["chat"];
|
|
75
78
|
readonly features: ["streaming", "json_object", "content_moderation", "vision"];
|
|
79
|
+
readonly tools: readonly [];
|
|
76
80
|
};
|
|
77
81
|
};
|
|
78
82
|
declare const LLAMA_PROMPT_GUARD_2_86M: {
|
|
@@ -92,6 +96,7 @@ declare const LLAMA_PROMPT_GUARD_2_86M: {
|
|
|
92
96
|
readonly output: ["text"];
|
|
93
97
|
readonly endpoints: ["chat"];
|
|
94
98
|
readonly features: ["streaming", "content_moderation", "json_object"];
|
|
99
|
+
readonly tools: readonly [];
|
|
95
100
|
};
|
|
96
101
|
};
|
|
97
102
|
declare const LLAMA_3_1_8B_INSTANT: {
|
|
@@ -111,6 +116,7 @@ declare const LLAMA_3_1_8B_INSTANT: {
|
|
|
111
116
|
readonly output: ["text"];
|
|
112
117
|
readonly endpoints: ["chat"];
|
|
113
118
|
readonly features: ["streaming", "json_object", "tools"];
|
|
119
|
+
readonly tools: readonly [];
|
|
114
120
|
};
|
|
115
121
|
};
|
|
116
122
|
declare const LLAMA_PROMPT_GUARD_2_22M: {
|
|
@@ -130,6 +136,7 @@ declare const LLAMA_PROMPT_GUARD_2_22M: {
|
|
|
130
136
|
readonly output: ["text"];
|
|
131
137
|
readonly endpoints: ["chat"];
|
|
132
138
|
readonly features: ["streaming", "content_moderation"];
|
|
139
|
+
readonly tools: readonly [];
|
|
133
140
|
};
|
|
134
141
|
};
|
|
135
142
|
declare const GPT_OSS_120B: {
|
|
@@ -150,6 +157,7 @@ declare const GPT_OSS_120B: {
|
|
|
150
157
|
readonly output: ["text"];
|
|
151
158
|
readonly endpoints: ["chat"];
|
|
152
159
|
readonly features: ["streaming", "json_object", "json_schema", "tools", "browser_search", "code_execution", "reasoning"];
|
|
160
|
+
readonly tools: readonly [];
|
|
153
161
|
};
|
|
154
162
|
};
|
|
155
163
|
declare const GPT_OSS_SAFEGUARD_20B: {
|
|
@@ -170,6 +178,7 @@ declare const GPT_OSS_SAFEGUARD_20B: {
|
|
|
170
178
|
readonly output: ["text"];
|
|
171
179
|
readonly endpoints: ["chat"];
|
|
172
180
|
readonly features: ["streaming", "tools", "browser_search", "code_execution", "json_object", "json_schema", "reasoning", "content_moderation"];
|
|
181
|
+
readonly tools: readonly [];
|
|
173
182
|
};
|
|
174
183
|
};
|
|
175
184
|
declare const GPT_OSS_20B: {
|
|
@@ -190,6 +199,7 @@ declare const GPT_OSS_20B: {
|
|
|
190
199
|
readonly output: ["text"];
|
|
191
200
|
readonly endpoints: ["chat"];
|
|
192
201
|
readonly features: ["streaming", "browser_search", "code_execution", "json_object", "json_schema", "reasoning", "tools"];
|
|
202
|
+
readonly tools: readonly [];
|
|
193
203
|
};
|
|
194
204
|
};
|
|
195
205
|
declare const KIMI_K2_INSTRUCT_0905: {
|
|
@@ -210,6 +220,7 @@ declare const KIMI_K2_INSTRUCT_0905: {
|
|
|
210
220
|
readonly output: ["text"];
|
|
211
221
|
readonly endpoints: ["chat"];
|
|
212
222
|
readonly features: ["streaming", "tools", "json_object", "json_schema"];
|
|
223
|
+
readonly tools: readonly [];
|
|
213
224
|
};
|
|
214
225
|
};
|
|
215
226
|
declare const QWEN3_32B: {
|
|
@@ -229,6 +240,7 @@ declare const QWEN3_32B: {
|
|
|
229
240
|
readonly output: ["text"];
|
|
230
241
|
readonly endpoints: ["chat"];
|
|
231
242
|
readonly features: ["streaming", "json_object", "tools", "reasoning"];
|
|
243
|
+
readonly tools: readonly [];
|
|
232
244
|
};
|
|
233
245
|
};
|
|
234
246
|
/**
|
|
@@ -262,6 +274,26 @@ export type GroqModelInputModalitiesByName = {
|
|
|
262
274
|
export type GroqChatModelProviderOptionsByName = {
|
|
263
275
|
[K in (typeof GROQ_CHAT_MODELS)[number]]: GroqTextProviderOptions;
|
|
264
276
|
};
|
|
277
|
+
/**
|
|
278
|
+
* Type-only map from Groq chat model name to its supported provider tools.
|
|
279
|
+
* Groq exposes no provider-specific tool factories, so every model gets an
|
|
280
|
+
* empty tuple. This ensures that passing an Anthropic/OpenAI ProviderTool to
|
|
281
|
+
* a Groq adapter produces a compile-time type error.
|
|
282
|
+
*/
|
|
283
|
+
export type GroqChatModelToolCapabilitiesByName = {
|
|
284
|
+
[LLAMA_3_1_8B_INSTANT.name]: typeof LLAMA_3_1_8B_INSTANT.supports.tools;
|
|
285
|
+
[LLAMA_3_3_70B_VERSATILE.name]: typeof LLAMA_3_3_70B_VERSATILE.supports.tools;
|
|
286
|
+
[LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name]: typeof LLAMA_4_MAVERICK_17B_128E_INSTRUCT.supports.tools;
|
|
287
|
+
[LLAMA_4_SCOUT_17B_16E_INSTRUCT.name]: typeof LLAMA_4_SCOUT_17B_16E_INSTRUCT.supports.tools;
|
|
288
|
+
[LLAMA_GUARD_4_12B.name]: typeof LLAMA_GUARD_4_12B.supports.tools;
|
|
289
|
+
[LLAMA_PROMPT_GUARD_2_86M.name]: typeof LLAMA_PROMPT_GUARD_2_86M.supports.tools;
|
|
290
|
+
[LLAMA_PROMPT_GUARD_2_22M.name]: typeof LLAMA_PROMPT_GUARD_2_22M.supports.tools;
|
|
291
|
+
[GPT_OSS_20B.name]: typeof GPT_OSS_20B.supports.tools;
|
|
292
|
+
[GPT_OSS_120B.name]: typeof GPT_OSS_120B.supports.tools;
|
|
293
|
+
[GPT_OSS_SAFEGUARD_20B.name]: typeof GPT_OSS_SAFEGUARD_20B.supports.tools;
|
|
294
|
+
[KIMI_K2_INSTRUCT_0905.name]: typeof KIMI_K2_INSTRUCT_0905.supports.tools;
|
|
295
|
+
[QWEN3_32B.name]: typeof QWEN3_32B.supports.tools;
|
|
296
|
+
};
|
|
265
297
|
/**
|
|
266
298
|
* Resolves the provider options type for a specific Groq model.
|
|
267
299
|
* Falls back to generic GroqTextProviderOptions for unknown models.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-meta.js","sources":["../../src/model-meta.ts"],"sourcesContent":["import type { GroqTextProviderOptions } from './text/text-provider-options'\n\n/**\n * Internal metadata structure describing a Groq model's capabilities and pricing.\n */\ninterface ModelMeta<TProviderOptions = unknown> {\n name: string\n context_window?: number\n max_completion_tokens?: number\n pricing: {\n input?: { normal: number; cached?: number }\n output?: { normal: number }\n }\n supports: {\n input: Array<'text' | 'image' | 'audio'>\n output: Array<'text' | 'audio'>\n endpoints: Array<'chat' | 'tts' | 'transcription' | 'batch'>\n\n features: Array<\n | 'streaming'\n | 'tools'\n | 'json_object'\n | 'browser_search'\n | 'code_execution'\n | 'reasoning'\n | 'content_moderation'\n | 'json_schema'\n | 'vision'\n >\n }\n /**\n * Type-level description of which provider options this model supports.\n */\n providerOptions?: TProviderOptions\n}\n\nconst LLAMA_3_3_70B_VERSATILE = {\n name: 'llama-3.3-70b-versatile',\n context_window: 131_072,\n max_completion_tokens: 32_768,\n pricing: {\n input: {\n normal: 0.59,\n },\n output: {\n normal: 0.79,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_4_MAVERICK_17B_128E_INSTRUCT = {\n name: 'meta-llama/llama-4-maverick-17b-128e-instruct',\n context_window: 131_072,\n max_completion_tokens: 8_192,\n pricing: {\n input: {\n normal: 0.2,\n },\n output: {\n normal: 0.6,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object', 'json_schema', 'vision'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_4_SCOUT_17B_16E_INSTRUCT = {\n name: 'meta-llama/llama-4-scout-17b-16e-instruct',\n context_window: 131_072,\n max_completion_tokens: 8_192,\n pricing: {\n input: {\n normal: 0.05,\n },\n output: {\n normal: 0.08,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_GUARD_4_12B = {\n name: 'meta-llama/llama-guard-4-12b',\n context_window: 131_072,\n max_completion_tokens: 1024,\n pricing: {\n input: {\n normal: 0.2,\n },\n output: {\n normal: 0.2,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'content_moderation', 'vision'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_PROMPT_GUARD_2_86M = {\n name: 'meta-llama/llama-prompt-guard-2-86m',\n context_window: 512,\n max_completion_tokens: 512,\n pricing: {\n input: {\n normal: 0.04,\n },\n output: {\n normal: 0.04,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'content_moderation', 'json_object'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_3_1_8B_INSTANT = {\n name: 'llama-3.1-8b-instant',\n context_window: 131_072,\n max_completion_tokens: 131_072,\n pricing: {\n input: {\n normal: 0.05,\n },\n output: {\n normal: 0.08,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'tools'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_PROMPT_GUARD_2_22M = {\n name: 'meta-llama/llama-prompt-guard-2-22m',\n context_window: 512,\n max_completion_tokens: 512,\n pricing: {\n input: {\n normal: 0.03,\n },\n output: {\n normal: 0.03,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'content_moderation'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_120B = {\n name: 'openai/gpt-oss-120b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.15,\n cached: 0.075,\n },\n output: {\n normal: 0.6,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'json_object',\n 'json_schema',\n 'tools',\n 'browser_search',\n 'code_execution',\n 'reasoning',\n ],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_SAFEGUARD_20B = {\n name: 'openai/gpt-oss-safeguard-20b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.075,\n cached: 0.037,\n },\n output: {\n normal: 0.3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'tools',\n 'browser_search',\n 'code_execution',\n 'json_object',\n 'json_schema',\n 'reasoning',\n 'content_moderation',\n ],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_20B = {\n name: 'openai/gpt-oss-20b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.075,\n cached: 0.037,\n },\n output: {\n normal: 0.3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'browser_search',\n 'code_execution',\n 'json_object',\n 'json_schema',\n 'reasoning',\n 'tools',\n ],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst KIMI_K2_INSTRUCT_0905 = {\n name: 'moonshotai/kimi-k2-instruct-0905',\n context_window: 262_144,\n max_completion_tokens: 16_384,\n pricing: {\n input: {\n normal: 1,\n cached: 0.5,\n },\n output: {\n normal: 3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object', 'json_schema'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst QWEN3_32B = {\n name: 'qwen/qwen3-32b',\n context_window: 131_072,\n max_completion_tokens: 40_960,\n pricing: {\n input: {\n normal: 0.29,\n },\n output: {\n normal: 0.59,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'tools', 'reasoning'],\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\n/**\n * All supported Groq chat model identifiers.\n */\nexport const GROQ_CHAT_MODELS = [\n LLAMA_3_1_8B_INSTANT.name,\n LLAMA_3_3_70B_VERSATILE.name,\n LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name,\n LLAMA_4_SCOUT_17B_16E_INSTRUCT.name,\n LLAMA_GUARD_4_12B.name,\n LLAMA_PROMPT_GUARD_2_86M.name,\n LLAMA_PROMPT_GUARD_2_22M.name,\n GPT_OSS_20B.name,\n GPT_OSS_120B.name,\n GPT_OSS_SAFEGUARD_20B.name,\n KIMI_K2_INSTRUCT_0905.name,\n QWEN3_32B.name,\n] as const\n\n/**\n * Union type of all supported Groq chat model names.\n */\nexport type GroqChatModels = (typeof GROQ_CHAT_MODELS)[number]\n\n/**\n * Type-only map from Groq chat model name to its supported input modalities.\n */\nexport type GroqModelInputModalitiesByName = {\n [LLAMA_3_1_8B_INSTANT.name]: typeof LLAMA_3_1_8B_INSTANT.supports.input\n [LLAMA_3_3_70B_VERSATILE.name]: typeof LLAMA_3_3_70B_VERSATILE.supports.input\n [LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name]: typeof LLAMA_4_MAVERICK_17B_128E_INSTRUCT.supports.input\n [LLAMA_4_SCOUT_17B_16E_INSTRUCT.name]: typeof LLAMA_4_SCOUT_17B_16E_INSTRUCT.supports.input\n [LLAMA_GUARD_4_12B.name]: typeof LLAMA_GUARD_4_12B.supports.input\n [LLAMA_PROMPT_GUARD_2_86M.name]: typeof LLAMA_PROMPT_GUARD_2_86M.supports.input\n [LLAMA_PROMPT_GUARD_2_22M.name]: typeof LLAMA_PROMPT_GUARD_2_22M.supports.input\n [GPT_OSS_20B.name]: typeof GPT_OSS_20B.supports.input\n [GPT_OSS_120B.name]: typeof GPT_OSS_120B.supports.input\n [GPT_OSS_SAFEGUARD_20B.name]: typeof GPT_OSS_SAFEGUARD_20B.supports.input\n [KIMI_K2_INSTRUCT_0905.name]: typeof KIMI_K2_INSTRUCT_0905.supports.input\n [QWEN3_32B.name]: typeof QWEN3_32B.supports.input\n}\n\n/**\n * Type-only map from Groq chat model name to its provider options type.\n */\nexport type GroqChatModelProviderOptionsByName = {\n [K in (typeof GROQ_CHAT_MODELS)[number]]: GroqTextProviderOptions\n}\n\n/**\n * Resolves the provider options type for a specific Groq model.\n * Falls back to generic GroqTextProviderOptions for unknown models.\n */\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof GroqChatModelProviderOptionsByName\n ? GroqChatModelProviderOptionsByName[TModel]\n : GroqTextProviderOptions\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 GroqModelInputModalitiesByName\n ? GroqModelInputModalitiesByName[TModel]\n : readonly ['text']\n"],"names":[],"mappings":"AAoCA,MAAM,0BAA0B;AAAA,EAC9B,MAAM;AAiBR;AAEA,MAAM,qCAAqC;AAAA,EACzC,MAAM;AAiBR;AAEA,MAAM,iCAAiC;AAAA,EACrC,MAAM;AAiBR;AAEA,MAAM,oBAAoB;AAAA,EACxB,MAAM;AAiBR;AAEA,MAAM,2BAA2B;AAAA,EAC/B,MAAM;AAiBR;AAEA,MAAM,uBAAuB;AAAA,EAC3B,MAAM;AAiBR;AAEA,MAAM,2BAA2B;AAAA,EAC/B,MAAM;AAiBR;AAEA,MAAM,eAAe;AAAA,EACnB,MAAM;AA0BR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AA2BR;AAEA,MAAM,cAAc;AAAA,EAClB,MAAM;AA0BR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAkBR;AAEA,MAAM,YAAY;AAAA,EAChB,MAAM;AAiBR;AAKO,MAAM,mBAAmB;AAAA,EAC9B,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,mCAAmC;AAAA,EACnC,+BAA+B;AAAA,EAC/B,kBAAkB;AAAA,EAClB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,UAAU;AACZ;"}
|
|
1
|
+
{"version":3,"file":"model-meta.js","sources":["../../src/model-meta.ts"],"sourcesContent":["import type { GroqTextProviderOptions } from './text/text-provider-options'\n\n/**\n * Internal metadata structure describing a Groq model's capabilities and pricing.\n */\ninterface ModelMeta<TProviderOptions = unknown> {\n name: string\n context_window?: number\n max_completion_tokens?: number\n pricing: {\n input?: { normal: number; cached?: number }\n output?: { normal: number }\n }\n supports: {\n input: Array<'text' | 'image' | 'audio'>\n output: Array<'text' | 'audio'>\n endpoints: Array<'chat' | 'tts' | 'transcription' | 'batch'>\n\n features: Array<\n | 'streaming'\n | 'tools'\n | 'json_object'\n | 'browser_search'\n | 'code_execution'\n | 'reasoning'\n | 'content_moderation'\n | 'json_schema'\n | 'vision'\n >\n tools?: ReadonlyArray<never>\n }\n /**\n * Type-level description of which provider options this model supports.\n */\n providerOptions?: TProviderOptions\n}\n\nconst LLAMA_3_3_70B_VERSATILE = {\n name: 'llama-3.3-70b-versatile',\n context_window: 131_072,\n max_completion_tokens: 32_768,\n pricing: {\n input: {\n normal: 0.59,\n },\n output: {\n normal: 0.79,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_4_MAVERICK_17B_128E_INSTRUCT = {\n name: 'meta-llama/llama-4-maverick-17b-128e-instruct',\n context_window: 131_072,\n max_completion_tokens: 8_192,\n pricing: {\n input: {\n normal: 0.2,\n },\n output: {\n normal: 0.6,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object', 'json_schema', 'vision'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_4_SCOUT_17B_16E_INSTRUCT = {\n name: 'meta-llama/llama-4-scout-17b-16e-instruct',\n context_window: 131_072,\n max_completion_tokens: 8_192,\n pricing: {\n input: {\n normal: 0.05,\n },\n output: {\n normal: 0.08,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_GUARD_4_12B = {\n name: 'meta-llama/llama-guard-4-12b',\n context_window: 131_072,\n max_completion_tokens: 1024,\n pricing: {\n input: {\n normal: 0.2,\n },\n output: {\n normal: 0.2,\n },\n },\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'content_moderation', 'vision'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_PROMPT_GUARD_2_86M = {\n name: 'meta-llama/llama-prompt-guard-2-86m',\n context_window: 512,\n max_completion_tokens: 512,\n pricing: {\n input: {\n normal: 0.04,\n },\n output: {\n normal: 0.04,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'content_moderation', 'json_object'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_3_1_8B_INSTANT = {\n name: 'llama-3.1-8b-instant',\n context_window: 131_072,\n max_completion_tokens: 131_072,\n pricing: {\n input: {\n normal: 0.05,\n },\n output: {\n normal: 0.08,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'tools'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst LLAMA_PROMPT_GUARD_2_22M = {\n name: 'meta-llama/llama-prompt-guard-2-22m',\n context_window: 512,\n max_completion_tokens: 512,\n pricing: {\n input: {\n normal: 0.03,\n },\n output: {\n normal: 0.03,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'content_moderation'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_120B = {\n name: 'openai/gpt-oss-120b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.15,\n cached: 0.075,\n },\n output: {\n normal: 0.6,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'json_object',\n 'json_schema',\n 'tools',\n 'browser_search',\n 'code_execution',\n 'reasoning',\n ],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_SAFEGUARD_20B = {\n name: 'openai/gpt-oss-safeguard-20b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.075,\n cached: 0.037,\n },\n output: {\n normal: 0.3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'tools',\n 'browser_search',\n 'code_execution',\n 'json_object',\n 'json_schema',\n 'reasoning',\n 'content_moderation',\n ],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst GPT_OSS_20B = {\n name: 'openai/gpt-oss-20b',\n context_window: 131_072,\n max_completion_tokens: 65_536,\n pricing: {\n input: {\n normal: 0.075,\n cached: 0.037,\n },\n output: {\n normal: 0.3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: [\n 'streaming',\n 'browser_search',\n 'code_execution',\n 'json_object',\n 'json_schema',\n 'reasoning',\n 'tools',\n ],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst KIMI_K2_INSTRUCT_0905 = {\n name: 'moonshotai/kimi-k2-instruct-0905',\n context_window: 262_144,\n max_completion_tokens: 16_384,\n pricing: {\n input: {\n normal: 1,\n cached: 0.5,\n },\n output: {\n normal: 3,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'tools', 'json_object', 'json_schema'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\nconst QWEN3_32B = {\n name: 'qwen/qwen3-32b',\n context_window: 131_072,\n max_completion_tokens: 40_960,\n pricing: {\n input: {\n normal: 0.29,\n },\n output: {\n normal: 0.59,\n },\n },\n supports: {\n input: ['text'],\n output: ['text'],\n endpoints: ['chat'],\n features: ['streaming', 'json_object', 'tools', 'reasoning'],\n tools: [] as const,\n },\n} as const satisfies ModelMeta<GroqTextProviderOptions>\n\n/**\n * All supported Groq chat model identifiers.\n */\nexport const GROQ_CHAT_MODELS = [\n LLAMA_3_1_8B_INSTANT.name,\n LLAMA_3_3_70B_VERSATILE.name,\n LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name,\n LLAMA_4_SCOUT_17B_16E_INSTRUCT.name,\n LLAMA_GUARD_4_12B.name,\n LLAMA_PROMPT_GUARD_2_86M.name,\n LLAMA_PROMPT_GUARD_2_22M.name,\n GPT_OSS_20B.name,\n GPT_OSS_120B.name,\n GPT_OSS_SAFEGUARD_20B.name,\n KIMI_K2_INSTRUCT_0905.name,\n QWEN3_32B.name,\n] as const\n\n/**\n * Union type of all supported Groq chat model names.\n */\nexport type GroqChatModels = (typeof GROQ_CHAT_MODELS)[number]\n\n/**\n * Type-only map from Groq chat model name to its supported input modalities.\n */\nexport type GroqModelInputModalitiesByName = {\n [LLAMA_3_1_8B_INSTANT.name]: typeof LLAMA_3_1_8B_INSTANT.supports.input\n [LLAMA_3_3_70B_VERSATILE.name]: typeof LLAMA_3_3_70B_VERSATILE.supports.input\n [LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name]: typeof LLAMA_4_MAVERICK_17B_128E_INSTRUCT.supports.input\n [LLAMA_4_SCOUT_17B_16E_INSTRUCT.name]: typeof LLAMA_4_SCOUT_17B_16E_INSTRUCT.supports.input\n [LLAMA_GUARD_4_12B.name]: typeof LLAMA_GUARD_4_12B.supports.input\n [LLAMA_PROMPT_GUARD_2_86M.name]: typeof LLAMA_PROMPT_GUARD_2_86M.supports.input\n [LLAMA_PROMPT_GUARD_2_22M.name]: typeof LLAMA_PROMPT_GUARD_2_22M.supports.input\n [GPT_OSS_20B.name]: typeof GPT_OSS_20B.supports.input\n [GPT_OSS_120B.name]: typeof GPT_OSS_120B.supports.input\n [GPT_OSS_SAFEGUARD_20B.name]: typeof GPT_OSS_SAFEGUARD_20B.supports.input\n [KIMI_K2_INSTRUCT_0905.name]: typeof KIMI_K2_INSTRUCT_0905.supports.input\n [QWEN3_32B.name]: typeof QWEN3_32B.supports.input\n}\n\n/**\n * Type-only map from Groq chat model name to its provider options type.\n */\nexport type GroqChatModelProviderOptionsByName = {\n [K in (typeof GROQ_CHAT_MODELS)[number]]: GroqTextProviderOptions\n}\n\n/**\n * Type-only map from Groq chat model name to its supported provider tools.\n * Groq 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 Groq adapter produces a compile-time type error.\n */\nexport type GroqChatModelToolCapabilitiesByName = {\n [LLAMA_3_1_8B_INSTANT.name]: typeof LLAMA_3_1_8B_INSTANT.supports.tools\n [LLAMA_3_3_70B_VERSATILE.name]: typeof LLAMA_3_3_70B_VERSATILE.supports.tools\n [LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name]: typeof LLAMA_4_MAVERICK_17B_128E_INSTRUCT.supports.tools\n [LLAMA_4_SCOUT_17B_16E_INSTRUCT.name]: typeof LLAMA_4_SCOUT_17B_16E_INSTRUCT.supports.tools\n [LLAMA_GUARD_4_12B.name]: typeof LLAMA_GUARD_4_12B.supports.tools\n [LLAMA_PROMPT_GUARD_2_86M.name]: typeof LLAMA_PROMPT_GUARD_2_86M.supports.tools\n [LLAMA_PROMPT_GUARD_2_22M.name]: typeof LLAMA_PROMPT_GUARD_2_22M.supports.tools\n [GPT_OSS_20B.name]: typeof GPT_OSS_20B.supports.tools\n [GPT_OSS_120B.name]: typeof GPT_OSS_120B.supports.tools\n [GPT_OSS_SAFEGUARD_20B.name]: typeof GPT_OSS_SAFEGUARD_20B.supports.tools\n [KIMI_K2_INSTRUCT_0905.name]: typeof KIMI_K2_INSTRUCT_0905.supports.tools\n [QWEN3_32B.name]: typeof QWEN3_32B.supports.tools\n}\n\n/**\n * Resolves the provider options type for a specific Groq model.\n * Falls back to generic GroqTextProviderOptions for unknown models.\n */\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof GroqChatModelProviderOptionsByName\n ? GroqChatModelProviderOptionsByName[TModel]\n : GroqTextProviderOptions\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 GroqModelInputModalitiesByName\n ? GroqModelInputModalitiesByName[TModel]\n : readonly ['text']\n"],"names":[],"mappings":"AAqCA,MAAM,0BAA0B;AAAA,EAC9B,MAAM;AAkBR;AAEA,MAAM,qCAAqC;AAAA,EACzC,MAAM;AAkBR;AAEA,MAAM,iCAAiC;AAAA,EACrC,MAAM;AAkBR;AAEA,MAAM,oBAAoB;AAAA,EACxB,MAAM;AAkBR;AAEA,MAAM,2BAA2B;AAAA,EAC/B,MAAM;AAkBR;AAEA,MAAM,uBAAuB;AAAA,EAC3B,MAAM;AAkBR;AAEA,MAAM,2BAA2B;AAAA,EAC/B,MAAM;AAkBR;AAEA,MAAM,eAAe;AAAA,EACnB,MAAM;AA2BR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AA4BR;AAEA,MAAM,cAAc;AAAA,EAClB,MAAM;AA2BR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAmBR;AAEA,MAAM,YAAY;AAAA,EAChB,MAAM;AAkBR;AAKO,MAAM,mBAAmB;AAAA,EAC9B,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,mCAAmC;AAAA,EACnC,+BAA+B;AAAA,EAC/B,kBAAkB;AAAA,EAClB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,UAAU;AACZ;"}
|
|
@@ -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-groq",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Groq adapter for TanStack AI",
|
|
6
6
|
"author": "",
|
|
@@ -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": [
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
},
|
|
35
39
|
"peerDependencies": {
|
|
36
40
|
"zod": "^4.0.0",
|
|
37
|
-
"@tanstack/ai": "^0.
|
|
41
|
+
"@tanstack/ai": "^0.12.0"
|
|
38
42
|
},
|
|
39
43
|
"dependencies": {
|
|
40
44
|
"groq-sdk": "^0.37.0"
|
package/src/adapters/text.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '../utils'
|
|
11
11
|
import type {
|
|
12
12
|
GROQ_CHAT_MODELS,
|
|
13
|
+
GroqChatModelToolCapabilitiesByName,
|
|
13
14
|
ResolveInputModalities,
|
|
14
15
|
ResolveProviderOptions,
|
|
15
16
|
} from '../model-meta'
|
|
@@ -21,11 +22,15 @@ import type GROQ_SDK from 'groq-sdk'
|
|
|
21
22
|
import type { ChatCompletionCreateParamsStreaming } from 'groq-sdk/resources/chat/completions'
|
|
22
23
|
import type {
|
|
23
24
|
ContentPart,
|
|
25
|
+
Modality,
|
|
24
26
|
ModelMessage,
|
|
25
27
|
StreamChunk,
|
|
26
28
|
TextOptions,
|
|
27
29
|
} from '@tanstack/ai'
|
|
28
|
-
import type {
|
|
30
|
+
import type {
|
|
31
|
+
ExternalTextProviderOptions,
|
|
32
|
+
InternalTextProviderOptions,
|
|
33
|
+
} from '../text/text-provider-options'
|
|
29
34
|
import type {
|
|
30
35
|
ChatCompletionContentPart,
|
|
31
36
|
ChatCompletionMessageParam,
|
|
@@ -34,6 +39,18 @@ import type {
|
|
|
34
39
|
} from '../message-types'
|
|
35
40
|
import type { GroqClientConfig } from '../utils'
|
|
36
41
|
|
|
42
|
+
type GroqTextProviderOptions = ExternalTextProviderOptions
|
|
43
|
+
|
|
44
|
+
type ResolveToolCapabilities<TModel extends string> =
|
|
45
|
+
TModel extends keyof GroqChatModelToolCapabilitiesByName
|
|
46
|
+
? NonNullable<GroqChatModelToolCapabilitiesByName[TModel]>
|
|
47
|
+
: readonly []
|
|
48
|
+
|
|
49
|
+
/** Cast an event object to StreamChunk. Adapters construct events with string
|
|
50
|
+
* literal types which are structurally compatible with the EventType enum. */
|
|
51
|
+
const asChunk = (chunk: Record<string, unknown>) =>
|
|
52
|
+
chunk as unknown as StreamChunk
|
|
53
|
+
|
|
37
54
|
/**
|
|
38
55
|
* Configuration for Groq text adapter
|
|
39
56
|
*/
|
|
@@ -52,11 +69,17 @@ export type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../
|
|
|
52
69
|
*/
|
|
53
70
|
export class GroqTextAdapter<
|
|
54
71
|
TModel extends (typeof GROQ_CHAT_MODELS)[number],
|
|
72
|
+
TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,
|
|
73
|
+
TInputModalities extends ReadonlyArray<Modality> =
|
|
74
|
+
ResolveInputModalities<TModel>,
|
|
75
|
+
TToolCapabilities extends ReadonlyArray<string> =
|
|
76
|
+
ResolveToolCapabilities<TModel>,
|
|
55
77
|
> extends BaseTextAdapter<
|
|
56
78
|
TModel,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
GroqMessageMetadataByModality
|
|
79
|
+
TProviderOptions,
|
|
80
|
+
TInputModalities,
|
|
81
|
+
GroqMessageMetadataByModality,
|
|
82
|
+
TToolCapabilities
|
|
60
83
|
> {
|
|
61
84
|
readonly kind = 'text' as const
|
|
62
85
|
readonly name = 'groq' as const
|
|
@@ -69,13 +92,14 @@ export class GroqTextAdapter<
|
|
|
69
92
|
}
|
|
70
93
|
|
|
71
94
|
async *chatStream(
|
|
72
|
-
options: TextOptions<
|
|
95
|
+
options: TextOptions<GroqTextProviderOptions>,
|
|
73
96
|
): AsyncIterable<StreamChunk> {
|
|
74
97
|
const requestParams = this.mapTextOptionsToGroq(options)
|
|
75
98
|
const timestamp = Date.now()
|
|
76
99
|
|
|
77
100
|
const aguiState = {
|
|
78
|
-
runId: generateId(this.name),
|
|
101
|
+
runId: options.runId ?? generateId(this.name),
|
|
102
|
+
threadId: options.threadId ?? generateId(this.name),
|
|
79
103
|
messageId: generateId(this.name),
|
|
80
104
|
timestamp,
|
|
81
105
|
hasEmittedRunStarted: false,
|
|
@@ -93,24 +117,27 @@ export class GroqTextAdapter<
|
|
|
93
117
|
|
|
94
118
|
if (!aguiState.hasEmittedRunStarted) {
|
|
95
119
|
aguiState.hasEmittedRunStarted = true
|
|
96
|
-
yield {
|
|
120
|
+
yield asChunk({
|
|
97
121
|
type: 'RUN_STARTED',
|
|
98
122
|
runId: aguiState.runId,
|
|
123
|
+
threadId: aguiState.threadId,
|
|
99
124
|
model: options.model,
|
|
100
125
|
timestamp,
|
|
101
|
-
}
|
|
126
|
+
})
|
|
102
127
|
}
|
|
103
128
|
|
|
104
|
-
yield {
|
|
129
|
+
yield asChunk({
|
|
105
130
|
type: 'RUN_ERROR',
|
|
106
131
|
runId: aguiState.runId,
|
|
107
132
|
model: options.model,
|
|
108
133
|
timestamp,
|
|
134
|
+
message: err.message || 'Unknown error',
|
|
135
|
+
code: err.code,
|
|
109
136
|
error: {
|
|
110
137
|
message: err.message || 'Unknown error',
|
|
111
138
|
code: err.code,
|
|
112
139
|
},
|
|
113
|
-
}
|
|
140
|
+
})
|
|
114
141
|
|
|
115
142
|
console.error('>>> chatStream: Fatal error during response creation <<<')
|
|
116
143
|
console.error('>>> Error message:', err.message)
|
|
@@ -132,7 +159,7 @@ export class GroqTextAdapter<
|
|
|
132
159
|
* We apply Groq-specific transformations for structured output compatibility.
|
|
133
160
|
*/
|
|
134
161
|
async structuredOutput(
|
|
135
|
-
options: StructuredOutputOptions<
|
|
162
|
+
options: StructuredOutputOptions<GroqTextProviderOptions>,
|
|
136
163
|
): Promise<StructuredOutputResult<unknown>> {
|
|
137
164
|
const { chatOptions, outputSchema } = options
|
|
138
165
|
const requestParams = this.mapTextOptionsToGroq(chatOptions)
|
|
@@ -190,6 +217,7 @@ export class GroqTextAdapter<
|
|
|
190
217
|
options: TextOptions,
|
|
191
218
|
aguiState: {
|
|
192
219
|
runId: string
|
|
220
|
+
threadId: string
|
|
193
221
|
messageId: string
|
|
194
222
|
timestamp: number
|
|
195
223
|
hasEmittedRunStarted: boolean
|
|
@@ -217,12 +245,13 @@ export class GroqTextAdapter<
|
|
|
217
245
|
|
|
218
246
|
if (!aguiState.hasEmittedRunStarted) {
|
|
219
247
|
aguiState.hasEmittedRunStarted = true
|
|
220
|
-
yield {
|
|
248
|
+
yield asChunk({
|
|
221
249
|
type: 'RUN_STARTED',
|
|
222
250
|
runId: aguiState.runId,
|
|
251
|
+
threadId: aguiState.threadId,
|
|
223
252
|
model: chunk.model || options.model,
|
|
224
253
|
timestamp,
|
|
225
|
-
}
|
|
254
|
+
})
|
|
226
255
|
}
|
|
227
256
|
|
|
228
257
|
const delta = choice.delta
|
|
@@ -232,25 +261,25 @@ export class GroqTextAdapter<
|
|
|
232
261
|
if (deltaContent) {
|
|
233
262
|
if (!hasEmittedTextMessageStart) {
|
|
234
263
|
hasEmittedTextMessageStart = true
|
|
235
|
-
yield {
|
|
264
|
+
yield asChunk({
|
|
236
265
|
type: 'TEXT_MESSAGE_START',
|
|
237
266
|
messageId: aguiState.messageId,
|
|
238
267
|
model: chunk.model || options.model,
|
|
239
268
|
timestamp,
|
|
240
269
|
role: 'assistant',
|
|
241
|
-
}
|
|
270
|
+
})
|
|
242
271
|
}
|
|
243
272
|
|
|
244
273
|
accumulatedContent += deltaContent
|
|
245
274
|
|
|
246
|
-
yield {
|
|
275
|
+
yield asChunk({
|
|
247
276
|
type: 'TEXT_MESSAGE_CONTENT',
|
|
248
277
|
messageId: aguiState.messageId,
|
|
249
278
|
model: chunk.model || options.model,
|
|
250
279
|
timestamp,
|
|
251
280
|
delta: deltaContent,
|
|
252
281
|
content: accumulatedContent,
|
|
253
|
-
}
|
|
282
|
+
})
|
|
254
283
|
}
|
|
255
284
|
|
|
256
285
|
if (deltaToolCalls) {
|
|
@@ -280,24 +309,25 @@ export class GroqTextAdapter<
|
|
|
280
309
|
|
|
281
310
|
if (toolCall.id && toolCall.name && !toolCall.started) {
|
|
282
311
|
toolCall.started = true
|
|
283
|
-
yield {
|
|
312
|
+
yield asChunk({
|
|
284
313
|
type: 'TOOL_CALL_START',
|
|
285
314
|
toolCallId: toolCall.id,
|
|
315
|
+
toolCallName: toolCall.name,
|
|
286
316
|
toolName: toolCall.name,
|
|
287
317
|
model: chunk.model || options.model,
|
|
288
318
|
timestamp,
|
|
289
319
|
index,
|
|
290
|
-
}
|
|
320
|
+
})
|
|
291
321
|
}
|
|
292
322
|
|
|
293
323
|
if (toolCallDelta.function?.arguments && toolCall.started) {
|
|
294
|
-
yield {
|
|
324
|
+
yield asChunk({
|
|
295
325
|
type: 'TOOL_CALL_ARGS',
|
|
296
326
|
toolCallId: toolCall.id,
|
|
297
327
|
model: chunk.model || options.model,
|
|
298
328
|
timestamp,
|
|
299
329
|
delta: toolCallDelta.function.arguments,
|
|
300
|
-
}
|
|
330
|
+
})
|
|
301
331
|
}
|
|
302
332
|
}
|
|
303
333
|
}
|
|
@@ -321,14 +351,15 @@ export class GroqTextAdapter<
|
|
|
321
351
|
parsedInput = {}
|
|
322
352
|
}
|
|
323
353
|
|
|
324
|
-
yield {
|
|
354
|
+
yield asChunk({
|
|
325
355
|
type: 'TOOL_CALL_END',
|
|
326
356
|
toolCallId: toolCall.id,
|
|
357
|
+
toolCallName: toolCall.name,
|
|
327
358
|
toolName: toolCall.name,
|
|
328
359
|
model: chunk.model || options.model,
|
|
329
360
|
timestamp,
|
|
330
361
|
input: parsedInput,
|
|
331
|
-
}
|
|
362
|
+
})
|
|
332
363
|
}
|
|
333
364
|
}
|
|
334
365
|
|
|
@@ -341,19 +372,20 @@ export class GroqTextAdapter<
|
|
|
341
372
|
: 'stop'
|
|
342
373
|
|
|
343
374
|
if (hasEmittedTextMessageStart) {
|
|
344
|
-
yield {
|
|
375
|
+
yield asChunk({
|
|
345
376
|
type: 'TEXT_MESSAGE_END',
|
|
346
377
|
messageId: aguiState.messageId,
|
|
347
378
|
model: chunk.model || options.model,
|
|
348
379
|
timestamp,
|
|
349
|
-
}
|
|
380
|
+
})
|
|
350
381
|
}
|
|
351
382
|
|
|
352
383
|
const groqUsage = chunk.x_groq?.usage
|
|
353
384
|
|
|
354
|
-
yield {
|
|
385
|
+
yield asChunk({
|
|
355
386
|
type: 'RUN_FINISHED',
|
|
356
387
|
runId: aguiState.runId,
|
|
388
|
+
threadId: aguiState.threadId,
|
|
357
389
|
model: chunk.model || options.model,
|
|
358
390
|
timestamp,
|
|
359
391
|
usage: groqUsage
|
|
@@ -364,23 +396,25 @@ export class GroqTextAdapter<
|
|
|
364
396
|
}
|
|
365
397
|
: undefined,
|
|
366
398
|
finishReason: computedFinishReason,
|
|
367
|
-
}
|
|
399
|
+
})
|
|
368
400
|
}
|
|
369
401
|
}
|
|
370
402
|
} catch (error: unknown) {
|
|
371
403
|
const err = error as Error & { code?: string }
|
|
372
404
|
console.log('[Groq Adapter] Stream ended with error:', err.message)
|
|
373
405
|
|
|
374
|
-
yield {
|
|
406
|
+
yield asChunk({
|
|
375
407
|
type: 'RUN_ERROR',
|
|
376
408
|
runId: aguiState.runId,
|
|
377
409
|
model: options.model,
|
|
378
410
|
timestamp,
|
|
411
|
+
message: err.message || 'Unknown error occurred',
|
|
412
|
+
code: err.code,
|
|
379
413
|
error: {
|
|
380
414
|
message: err.message || 'Unknown error occurred',
|
|
381
415
|
code: err.code,
|
|
382
416
|
},
|
|
383
|
-
}
|
|
417
|
+
})
|
|
384
418
|
}
|
|
385
419
|
}
|
|
386
420
|
|
package/src/index.ts
CHANGED
package/src/model-meta.ts
CHANGED
|
@@ -27,6 +27,7 @@ interface ModelMeta<TProviderOptions = unknown> {
|
|
|
27
27
|
| 'json_schema'
|
|
28
28
|
| 'vision'
|
|
29
29
|
>
|
|
30
|
+
tools?: ReadonlyArray<never>
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* Type-level description of which provider options this model supports.
|
|
@@ -51,6 +52,7 @@ const LLAMA_3_3_70B_VERSATILE = {
|
|
|
51
52
|
output: ['text'],
|
|
52
53
|
endpoints: ['chat'],
|
|
53
54
|
features: ['streaming', 'tools', 'json_object'],
|
|
55
|
+
tools: [] as const,
|
|
54
56
|
},
|
|
55
57
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
56
58
|
|
|
@@ -71,6 +73,7 @@ const LLAMA_4_MAVERICK_17B_128E_INSTRUCT = {
|
|
|
71
73
|
output: ['text'],
|
|
72
74
|
endpoints: ['chat'],
|
|
73
75
|
features: ['streaming', 'tools', 'json_object', 'json_schema', 'vision'],
|
|
76
|
+
tools: [] as const,
|
|
74
77
|
},
|
|
75
78
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
76
79
|
|
|
@@ -91,6 +94,7 @@ const LLAMA_4_SCOUT_17B_16E_INSTRUCT = {
|
|
|
91
94
|
output: ['text'],
|
|
92
95
|
endpoints: ['chat'],
|
|
93
96
|
features: ['streaming', 'tools', 'json_object'],
|
|
97
|
+
tools: [] as const,
|
|
94
98
|
},
|
|
95
99
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
96
100
|
|
|
@@ -111,6 +115,7 @@ const LLAMA_GUARD_4_12B = {
|
|
|
111
115
|
output: ['text'],
|
|
112
116
|
endpoints: ['chat'],
|
|
113
117
|
features: ['streaming', 'json_object', 'content_moderation', 'vision'],
|
|
118
|
+
tools: [] as const,
|
|
114
119
|
},
|
|
115
120
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
116
121
|
|
|
@@ -131,6 +136,7 @@ const LLAMA_PROMPT_GUARD_2_86M = {
|
|
|
131
136
|
output: ['text'],
|
|
132
137
|
endpoints: ['chat'],
|
|
133
138
|
features: ['streaming', 'content_moderation', 'json_object'],
|
|
139
|
+
tools: [] as const,
|
|
134
140
|
},
|
|
135
141
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
136
142
|
|
|
@@ -151,6 +157,7 @@ const LLAMA_3_1_8B_INSTANT = {
|
|
|
151
157
|
output: ['text'],
|
|
152
158
|
endpoints: ['chat'],
|
|
153
159
|
features: ['streaming', 'json_object', 'tools'],
|
|
160
|
+
tools: [] as const,
|
|
154
161
|
},
|
|
155
162
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
156
163
|
|
|
@@ -171,6 +178,7 @@ const LLAMA_PROMPT_GUARD_2_22M = {
|
|
|
171
178
|
output: ['text'],
|
|
172
179
|
endpoints: ['chat'],
|
|
173
180
|
features: ['streaming', 'content_moderation'],
|
|
181
|
+
tools: [] as const,
|
|
174
182
|
},
|
|
175
183
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
176
184
|
|
|
@@ -200,6 +208,7 @@ const GPT_OSS_120B = {
|
|
|
200
208
|
'code_execution',
|
|
201
209
|
'reasoning',
|
|
202
210
|
],
|
|
211
|
+
tools: [] as const,
|
|
203
212
|
},
|
|
204
213
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
205
214
|
|
|
@@ -230,6 +239,7 @@ const GPT_OSS_SAFEGUARD_20B = {
|
|
|
230
239
|
'reasoning',
|
|
231
240
|
'content_moderation',
|
|
232
241
|
],
|
|
242
|
+
tools: [] as const,
|
|
233
243
|
},
|
|
234
244
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
235
245
|
|
|
@@ -259,6 +269,7 @@ const GPT_OSS_20B = {
|
|
|
259
269
|
'reasoning',
|
|
260
270
|
'tools',
|
|
261
271
|
],
|
|
272
|
+
tools: [] as const,
|
|
262
273
|
},
|
|
263
274
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
264
275
|
|
|
@@ -280,6 +291,7 @@ const KIMI_K2_INSTRUCT_0905 = {
|
|
|
280
291
|
output: ['text'],
|
|
281
292
|
endpoints: ['chat'],
|
|
282
293
|
features: ['streaming', 'tools', 'json_object', 'json_schema'],
|
|
294
|
+
tools: [] as const,
|
|
283
295
|
},
|
|
284
296
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
285
297
|
|
|
@@ -300,6 +312,7 @@ const QWEN3_32B = {
|
|
|
300
312
|
output: ['text'],
|
|
301
313
|
endpoints: ['chat'],
|
|
302
314
|
features: ['streaming', 'json_object', 'tools', 'reasoning'],
|
|
315
|
+
tools: [] as const,
|
|
303
316
|
},
|
|
304
317
|
} as const satisfies ModelMeta<GroqTextProviderOptions>
|
|
305
318
|
|
|
@@ -351,6 +364,27 @@ export type GroqChatModelProviderOptionsByName = {
|
|
|
351
364
|
[K in (typeof GROQ_CHAT_MODELS)[number]]: GroqTextProviderOptions
|
|
352
365
|
}
|
|
353
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Type-only map from Groq chat model name to its supported provider tools.
|
|
369
|
+
* Groq exposes no provider-specific tool factories, so every model gets an
|
|
370
|
+
* empty tuple. This ensures that passing an Anthropic/OpenAI ProviderTool to
|
|
371
|
+
* a Groq adapter produces a compile-time type error.
|
|
372
|
+
*/
|
|
373
|
+
export type GroqChatModelToolCapabilitiesByName = {
|
|
374
|
+
[LLAMA_3_1_8B_INSTANT.name]: typeof LLAMA_3_1_8B_INSTANT.supports.tools
|
|
375
|
+
[LLAMA_3_3_70B_VERSATILE.name]: typeof LLAMA_3_3_70B_VERSATILE.supports.tools
|
|
376
|
+
[LLAMA_4_MAVERICK_17B_128E_INSTRUCT.name]: typeof LLAMA_4_MAVERICK_17B_128E_INSTRUCT.supports.tools
|
|
377
|
+
[LLAMA_4_SCOUT_17B_16E_INSTRUCT.name]: typeof LLAMA_4_SCOUT_17B_16E_INSTRUCT.supports.tools
|
|
378
|
+
[LLAMA_GUARD_4_12B.name]: typeof LLAMA_GUARD_4_12B.supports.tools
|
|
379
|
+
[LLAMA_PROMPT_GUARD_2_86M.name]: typeof LLAMA_PROMPT_GUARD_2_86M.supports.tools
|
|
380
|
+
[LLAMA_PROMPT_GUARD_2_22M.name]: typeof LLAMA_PROMPT_GUARD_2_22M.supports.tools
|
|
381
|
+
[GPT_OSS_20B.name]: typeof GPT_OSS_20B.supports.tools
|
|
382
|
+
[GPT_OSS_120B.name]: typeof GPT_OSS_120B.supports.tools
|
|
383
|
+
[GPT_OSS_SAFEGUARD_20B.name]: typeof GPT_OSS_SAFEGUARD_20B.supports.tools
|
|
384
|
+
[KIMI_K2_INSTRUCT_0905.name]: typeof KIMI_K2_INSTRUCT_0905.supports.tools
|
|
385
|
+
[QWEN3_32B.name]: typeof QWEN3_32B.supports.tools
|
|
386
|
+
}
|
|
387
|
+
|
|
354
388
|
/**
|
|
355
389
|
* Resolves the provider options type for a specific Groq model.
|
|
356
390
|
* Falls back to generic GroqTextProviderOptions for unknown models.
|