@tanstack/ai-groq 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/adapters/text.d.ts +8 -5
- package/dist/esm/adapters/text.js +25 -10
- 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 +50 -15
- 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.
|
|
@@ -14,6 +14,7 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
14
14
|
async *chatStream(options) {
|
|
15
15
|
const requestParams = this.mapTextOptionsToGroq(options);
|
|
16
16
|
const timestamp = Date.now();
|
|
17
|
+
const { logger } = options;
|
|
17
18
|
const aguiState = {
|
|
18
19
|
runId: options.runId ?? generateId(this.name),
|
|
19
20
|
threadId: options.threadId ?? generateId(this.name),
|
|
@@ -22,11 +23,15 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
22
23
|
hasEmittedRunStarted: false
|
|
23
24
|
};
|
|
24
25
|
try {
|
|
26
|
+
logger.request(
|
|
27
|
+
`activity=chat provider=groq model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,
|
|
28
|
+
{ provider: "groq", model: this.model }
|
|
29
|
+
);
|
|
25
30
|
const stream = await this.client.chat.completions.create({
|
|
26
31
|
...requestParams,
|
|
27
32
|
stream: true
|
|
28
33
|
});
|
|
29
|
-
yield* this.processGroqStreamChunks(stream, options, aguiState);
|
|
34
|
+
yield* this.processGroqStreamChunks(stream, options, aguiState, logger);
|
|
30
35
|
} catch (error) {
|
|
31
36
|
const err = error;
|
|
32
37
|
if (!aguiState.hasEmittedRunStarted) {
|
|
@@ -51,10 +56,10 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
51
56
|
code: err.code
|
|
52
57
|
}
|
|
53
58
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
logger.errors("groq.chatStream fatal", {
|
|
60
|
+
error,
|
|
61
|
+
source: "groq.chatStream"
|
|
62
|
+
});
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
/**
|
|
@@ -72,11 +77,16 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
72
77
|
async structuredOutput(options) {
|
|
73
78
|
const { chatOptions, outputSchema } = options;
|
|
74
79
|
const requestParams = this.mapTextOptionsToGroq(chatOptions);
|
|
80
|
+
const { logger } = chatOptions;
|
|
75
81
|
const jsonSchema = makeGroqStructuredOutputCompatible(
|
|
76
82
|
outputSchema,
|
|
77
83
|
outputSchema.required || []
|
|
78
84
|
);
|
|
79
85
|
try {
|
|
86
|
+
logger.request(
|
|
87
|
+
`activity=chat provider=groq model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,
|
|
88
|
+
{ provider: "groq", model: this.model }
|
|
89
|
+
);
|
|
80
90
|
const response = await this.client.chat.completions.create({
|
|
81
91
|
...requestParams,
|
|
82
92
|
stream: false,
|
|
@@ -104,9 +114,10 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
104
114
|
rawText
|
|
105
115
|
};
|
|
106
116
|
} catch (error) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
logger.errors("groq.structuredOutput fatal", {
|
|
118
|
+
error,
|
|
119
|
+
source: "groq.structuredOutput"
|
|
120
|
+
});
|
|
110
121
|
throw error;
|
|
111
122
|
}
|
|
112
123
|
}
|
|
@@ -114,13 +125,14 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
114
125
|
* Processes streaming chunks from the Groq API and yields AG-UI stream events.
|
|
115
126
|
* Handles text content deltas, tool call assembly, and lifecycle events.
|
|
116
127
|
*/
|
|
117
|
-
async *processGroqStreamChunks(stream, options, aguiState) {
|
|
128
|
+
async *processGroqStreamChunks(stream, options, aguiState, logger) {
|
|
118
129
|
let accumulatedContent = "";
|
|
119
130
|
const timestamp = aguiState.timestamp;
|
|
120
131
|
let hasEmittedTextMessageStart = false;
|
|
121
132
|
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
122
133
|
try {
|
|
123
134
|
for await (const chunk of stream) {
|
|
135
|
+
logger.provider(`provider=groq`, { chunk });
|
|
124
136
|
const choice = chunk.choices[0];
|
|
125
137
|
if (!choice) continue;
|
|
126
138
|
if (!aguiState.hasEmittedRunStarted) {
|
|
@@ -251,7 +263,10 @@ class GroqTextAdapter extends BaseTextAdapter {
|
|
|
251
263
|
}
|
|
252
264
|
} catch (error) {
|
|
253
265
|
const err = error;
|
|
254
|
-
|
|
266
|
+
logger.errors("groq stream ended with error", {
|
|
267
|
+
error,
|
|
268
|
+
source: "groq.processGroqStreamChunks"
|
|
269
|
+
});
|
|
255
270
|
yield asChunk({
|
|
256
271
|
type: "RUN_ERROR",
|
|
257
272
|
runId: aguiState.runId,
|
|
@@ -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/** 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> 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: 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<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 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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"}
|
|
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 { InternalLogger } from '@tanstack/ai/adapter-internals'\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 const { logger } = options\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 logger.request(\n `activity=chat provider=groq model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,\n { provider: 'groq', model: this.model },\n )\n const stream = await this.client.chat.completions.create({\n ...requestParams,\n stream: true,\n })\n\n yield* this.processGroqStreamChunks(stream, options, aguiState, logger)\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 logger.errors('groq.chatStream fatal', {\n error,\n source: 'groq.chatStream',\n })\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 const { logger } = chatOptions\n\n const jsonSchema = makeGroqStructuredOutputCompatible(\n outputSchema,\n outputSchema.required || [],\n )\n\n try {\n logger.request(\n `activity=chat provider=groq model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,\n { provider: 'groq', model: this.model },\n )\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 logger.errors('groq.structuredOutput fatal', {\n error,\n source: 'groq.structuredOutput',\n })\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 logger: InternalLogger,\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 logger.provider(`provider=groq`, { chunk })\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 logger.errors('groq stream ended with error', {\n error,\n source: 'groq.processGroqStreamChunks',\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 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.7",
|
|
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.13.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'
|
|
@@ -17,15 +18,20 @@ import type {
|
|
|
17
18
|
StructuredOutputOptions,
|
|
18
19
|
StructuredOutputResult,
|
|
19
20
|
} from '@tanstack/ai/adapters'
|
|
21
|
+
import type { InternalLogger } from '@tanstack/ai/adapter-internals'
|
|
20
22
|
import type GROQ_SDK from 'groq-sdk'
|
|
21
23
|
import type { ChatCompletionCreateParamsStreaming } from 'groq-sdk/resources/chat/completions'
|
|
22
24
|
import type {
|
|
23
25
|
ContentPart,
|
|
26
|
+
Modality,
|
|
24
27
|
ModelMessage,
|
|
25
28
|
StreamChunk,
|
|
26
29
|
TextOptions,
|
|
27
30
|
} from '@tanstack/ai'
|
|
28
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
ExternalTextProviderOptions,
|
|
33
|
+
InternalTextProviderOptions,
|
|
34
|
+
} from '../text/text-provider-options'
|
|
29
35
|
import type {
|
|
30
36
|
ChatCompletionContentPart,
|
|
31
37
|
ChatCompletionMessageParam,
|
|
@@ -34,6 +40,13 @@ import type {
|
|
|
34
40
|
} from '../message-types'
|
|
35
41
|
import type { GroqClientConfig } from '../utils'
|
|
36
42
|
|
|
43
|
+
type GroqTextProviderOptions = ExternalTextProviderOptions
|
|
44
|
+
|
|
45
|
+
type ResolveToolCapabilities<TModel extends string> =
|
|
46
|
+
TModel extends keyof GroqChatModelToolCapabilitiesByName
|
|
47
|
+
? NonNullable<GroqChatModelToolCapabilitiesByName[TModel]>
|
|
48
|
+
: readonly []
|
|
49
|
+
|
|
37
50
|
/** Cast an event object to StreamChunk. Adapters construct events with string
|
|
38
51
|
* literal types which are structurally compatible with the EventType enum. */
|
|
39
52
|
const asChunk = (chunk: Record<string, unknown>) =>
|
|
@@ -57,11 +70,17 @@ export type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../
|
|
|
57
70
|
*/
|
|
58
71
|
export class GroqTextAdapter<
|
|
59
72
|
TModel extends (typeof GROQ_CHAT_MODELS)[number],
|
|
73
|
+
TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,
|
|
74
|
+
TInputModalities extends ReadonlyArray<Modality> =
|
|
75
|
+
ResolveInputModalities<TModel>,
|
|
76
|
+
TToolCapabilities extends ReadonlyArray<string> =
|
|
77
|
+
ResolveToolCapabilities<TModel>,
|
|
60
78
|
> extends BaseTextAdapter<
|
|
61
79
|
TModel,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
GroqMessageMetadataByModality
|
|
80
|
+
TProviderOptions,
|
|
81
|
+
TInputModalities,
|
|
82
|
+
GroqMessageMetadataByModality,
|
|
83
|
+
TToolCapabilities
|
|
65
84
|
> {
|
|
66
85
|
readonly kind = 'text' as const
|
|
67
86
|
readonly name = 'groq' as const
|
|
@@ -74,10 +93,11 @@ export class GroqTextAdapter<
|
|
|
74
93
|
}
|
|
75
94
|
|
|
76
95
|
async *chatStream(
|
|
77
|
-
options: TextOptions<
|
|
96
|
+
options: TextOptions<GroqTextProviderOptions>,
|
|
78
97
|
): AsyncIterable<StreamChunk> {
|
|
79
98
|
const requestParams = this.mapTextOptionsToGroq(options)
|
|
80
99
|
const timestamp = Date.now()
|
|
100
|
+
const { logger } = options
|
|
81
101
|
|
|
82
102
|
const aguiState = {
|
|
83
103
|
runId: options.runId ?? generateId(this.name),
|
|
@@ -88,12 +108,16 @@ export class GroqTextAdapter<
|
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
try {
|
|
111
|
+
logger.request(
|
|
112
|
+
`activity=chat provider=groq model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,
|
|
113
|
+
{ provider: 'groq', model: this.model },
|
|
114
|
+
)
|
|
91
115
|
const stream = await this.client.chat.completions.create({
|
|
92
116
|
...requestParams,
|
|
93
117
|
stream: true,
|
|
94
118
|
})
|
|
95
119
|
|
|
96
|
-
yield* this.processGroqStreamChunks(stream, options, aguiState)
|
|
120
|
+
yield* this.processGroqStreamChunks(stream, options, aguiState, logger)
|
|
97
121
|
} catch (error: unknown) {
|
|
98
122
|
const err = error as Error & { code?: string }
|
|
99
123
|
|
|
@@ -121,10 +145,10 @@ export class GroqTextAdapter<
|
|
|
121
145
|
},
|
|
122
146
|
})
|
|
123
147
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
148
|
+
logger.errors('groq.chatStream fatal', {
|
|
149
|
+
error,
|
|
150
|
+
source: 'groq.chatStream',
|
|
151
|
+
})
|
|
128
152
|
}
|
|
129
153
|
}
|
|
130
154
|
|
|
@@ -141,10 +165,11 @@ export class GroqTextAdapter<
|
|
|
141
165
|
* We apply Groq-specific transformations for structured output compatibility.
|
|
142
166
|
*/
|
|
143
167
|
async structuredOutput(
|
|
144
|
-
options: StructuredOutputOptions<
|
|
168
|
+
options: StructuredOutputOptions<GroqTextProviderOptions>,
|
|
145
169
|
): Promise<StructuredOutputResult<unknown>> {
|
|
146
170
|
const { chatOptions, outputSchema } = options
|
|
147
171
|
const requestParams = this.mapTextOptionsToGroq(chatOptions)
|
|
172
|
+
const { logger } = chatOptions
|
|
148
173
|
|
|
149
174
|
const jsonSchema = makeGroqStructuredOutputCompatible(
|
|
150
175
|
outputSchema,
|
|
@@ -152,6 +177,10 @@ export class GroqTextAdapter<
|
|
|
152
177
|
)
|
|
153
178
|
|
|
154
179
|
try {
|
|
180
|
+
logger.request(
|
|
181
|
+
`activity=chat provider=groq model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,
|
|
182
|
+
{ provider: 'groq', model: this.model },
|
|
183
|
+
)
|
|
155
184
|
const response = await this.client.chat.completions.create({
|
|
156
185
|
...requestParams,
|
|
157
186
|
stream: false,
|
|
@@ -183,9 +212,10 @@ export class GroqTextAdapter<
|
|
|
183
212
|
rawText,
|
|
184
213
|
}
|
|
185
214
|
} catch (error: unknown) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
215
|
+
logger.errors('groq.structuredOutput fatal', {
|
|
216
|
+
error,
|
|
217
|
+
source: 'groq.structuredOutput',
|
|
218
|
+
})
|
|
189
219
|
throw error
|
|
190
220
|
}
|
|
191
221
|
}
|
|
@@ -204,6 +234,7 @@ export class GroqTextAdapter<
|
|
|
204
234
|
timestamp: number
|
|
205
235
|
hasEmittedRunStarted: boolean
|
|
206
236
|
},
|
|
237
|
+
logger: InternalLogger,
|
|
207
238
|
): AsyncIterable<StreamChunk> {
|
|
208
239
|
let accumulatedContent = ''
|
|
209
240
|
const timestamp = aguiState.timestamp
|
|
@@ -221,6 +252,7 @@ export class GroqTextAdapter<
|
|
|
221
252
|
|
|
222
253
|
try {
|
|
223
254
|
for await (const chunk of stream) {
|
|
255
|
+
logger.provider(`provider=groq`, { chunk })
|
|
224
256
|
const choice = chunk.choices[0]
|
|
225
257
|
|
|
226
258
|
if (!choice) continue
|
|
@@ -383,7 +415,10 @@ export class GroqTextAdapter<
|
|
|
383
415
|
}
|
|
384
416
|
} catch (error: unknown) {
|
|
385
417
|
const err = error as Error & { code?: string }
|
|
386
|
-
|
|
418
|
+
logger.errors('groq stream ended with error', {
|
|
419
|
+
error,
|
|
420
|
+
source: 'groq.processGroqStreamChunks',
|
|
421
|
+
})
|
|
387
422
|
|
|
388
423
|
yield asChunk({
|
|
389
424
|
type: 'RUN_ERROR',
|
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.
|