@tanstack/ai-groq 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -0
- package/dist/esm/adapters/text.d.ts +104 -0
- package/dist/esm/adapters/text.js +384 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/message-types.d.ts +292 -0
- package/dist/esm/model-meta.d.ts +275 -0
- package/dist/esm/model-meta.js +54 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/text-provider-options.d.ts +179 -0
- package/dist/esm/text/text-provider-options.js +6 -0
- package/dist/esm/text/text-provider-options.js.map +1 -0
- package/dist/esm/tools/function-tool.d.ts +13 -0
- package/dist/esm/tools/function-tool.js +29 -0
- package/dist/esm/tools/function-tool.js.map +1 -0
- package/dist/esm/tools/index.d.ts +2 -0
- package/dist/esm/tools/tool-converter.d.ts +7 -0
- package/dist/esm/tools/tool-converter.js +10 -0
- package/dist/esm/tools/tool-converter.js.map +1 -0
- package/dist/esm/utils/client.d.ts +17 -0
- package/dist/esm/utils/client.js +23 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/schema-converter.d.ts +25 -0
- package/dist/esm/utils/schema-converter.js +78 -0
- package/dist/esm/utils/schema-converter.js.map +1 -0
- package/package.json +52 -0
- package/src/adapters/text.ts +599 -0
- package/src/index.ts +33 -0
- package/src/message-types.ts +359 -0
- package/src/model-meta.ts +370 -0
- package/src/text/text-provider-options.ts +225 -0
- package/src/tools/function-tool.ts +44 -0
- package/src/tools/index.ts +5 -0
- package/src/tools/tool-converter.ts +15 -0
- package/src/utils/client.ts +42 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/schema-converter.ts +110 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# @tanstack/ai-groq
|
|
2
|
+
|
|
3
|
+
Groq adapter for TanStack AI
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @tanstack/ai-groq
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @tanstack/ai-groq
|
|
11
|
+
# or
|
|
12
|
+
yarn add @tanstack/ai-groq
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
Get your API key from [Groq Console](https://console.groq.com) and set it as an environment variable:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export GROQ_API_KEY="gsk_..."
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Text/Chat Adapter
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { groqText } from '@tanstack/ai-groq'
|
|
29
|
+
import { generate } from '@tanstack/ai'
|
|
30
|
+
|
|
31
|
+
const adapter = groqText('llama-3.3-70b-versatile')
|
|
32
|
+
|
|
33
|
+
const result = await generate({
|
|
34
|
+
adapter,
|
|
35
|
+
model: 'llama-3.3-70b-versatile',
|
|
36
|
+
messages: [
|
|
37
|
+
{ role: 'user', content: 'Explain quantum computing in simple terms' },
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
console.log(result.text)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### With Explicit API Key
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { createGroqText } from '@tanstack/ai-groq'
|
|
48
|
+
|
|
49
|
+
const adapter = createGroqText('llama-3.3-70b-versatile', 'gsk_api_key')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Supported Models
|
|
53
|
+
|
|
54
|
+
### Chat Models
|
|
55
|
+
|
|
56
|
+
- `llama-3.3-70b-versatile` - Meta Llama 3.3 70B (131k context)
|
|
57
|
+
- `llama-3.1-8b-instant` - Meta Llama 3.1 8B (131k context)
|
|
58
|
+
- `meta-llama/llama-4-maverick-17b-128e-instruct` - Meta Llama 4 Maverick (vision)
|
|
59
|
+
- `meta-llama/llama-4-scout-17b-16e-instruct` - Meta Llama 4 Scout
|
|
60
|
+
- `meta-llama/llama-guard-4-12b` - Meta Llama Guard 4 (content moderation, vision)
|
|
61
|
+
- `meta-llama/llama-prompt-guard-2-86m` - Meta Llama Prompt Guard (content moderation)
|
|
62
|
+
- `meta-llama/llama-prompt-guard-2-22m` - Meta Llama Prompt Guard (content moderation)
|
|
63
|
+
- `openai/gpt-oss-120b` - GPT OSS 120B (reasoning, tools, search)
|
|
64
|
+
- `openai/gpt-oss-20b` - GPT OSS 20B (reasoning, search)
|
|
65
|
+
- `openai/gpt-oss-safeguard-20b` - GPT OSS Safeguard 20B (content moderation, reasoning)
|
|
66
|
+
- `moonshotai/kimi-k2-instruct-0905` - Kimi K2 Instruct (262k context)
|
|
67
|
+
- `qwen/qwen3-32b` - Qwen3 32B (reasoning, tools)
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- ✅ Streaming chat completions
|
|
72
|
+
- ✅ Structured output (JSON Schema)
|
|
73
|
+
- ✅ Function/tool calling
|
|
74
|
+
- ✅ Multimodal input (text + images for vision models)
|
|
75
|
+
- ❌ Embeddings (not supported by Groq)
|
|
76
|
+
- ❌ Image generation (not supported by Groq)
|
|
77
|
+
|
|
78
|
+
## Tree-Shakeable Adapters
|
|
79
|
+
|
|
80
|
+
This package uses tree-shakeable adapters, so you only import what you need:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Only imports text adapter
|
|
84
|
+
import { groqText } from '@tanstack/ai-groq'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This keeps your bundle size small!
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
|
@@ -0,0 +1,104 @@
|
|
|
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';
|
|
4
|
+
import { GroqMessageMetadataByModality } from '../message-types.js';
|
|
5
|
+
import { GroqClientConfig } from '../utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for Groq text adapter
|
|
8
|
+
*/
|
|
9
|
+
export interface GroqTextConfig extends GroqClientConfig {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Alias for TextProviderOptions for external use
|
|
13
|
+
*/
|
|
14
|
+
export type { ExternalTextProviderOptions as GroqTextProviderOptions } from '../text/text-provider-options.js';
|
|
15
|
+
/**
|
|
16
|
+
* Groq Text (Chat) Adapter
|
|
17
|
+
*
|
|
18
|
+
* Tree-shakeable adapter for Groq chat/text completion functionality.
|
|
19
|
+
* Uses the Groq SDK which provides an OpenAI-compatible Chat Completions API.
|
|
20
|
+
*/
|
|
21
|
+
export declare class GroqTextAdapter<TModel extends (typeof GROQ_CHAT_MODELS)[number]> extends BaseTextAdapter<TModel, ResolveProviderOptions<TModel>, ResolveInputModalities<TModel>, GroqMessageMetadataByModality> {
|
|
22
|
+
readonly kind: "text";
|
|
23
|
+
readonly name: "groq";
|
|
24
|
+
private client;
|
|
25
|
+
constructor(config: GroqTextConfig, model: TModel);
|
|
26
|
+
chatStream(options: TextOptions<ResolveProviderOptions<TModel>>): AsyncIterable<StreamChunk>;
|
|
27
|
+
/**
|
|
28
|
+
* Generate structured output using Groq's JSON Schema response format.
|
|
29
|
+
* Uses stream: false to get the complete response in one call.
|
|
30
|
+
*
|
|
31
|
+
* Groq has strict requirements for structured output:
|
|
32
|
+
* - All properties must be in the `required` array
|
|
33
|
+
* - Optional fields should have null added to their type union
|
|
34
|
+
* - additionalProperties must be false for all objects
|
|
35
|
+
*
|
|
36
|
+
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
37
|
+
* We apply Groq-specific transformations for structured output compatibility.
|
|
38
|
+
*/
|
|
39
|
+
structuredOutput(options: StructuredOutputOptions<ResolveProviderOptions<TModel>>): Promise<StructuredOutputResult<unknown>>;
|
|
40
|
+
/**
|
|
41
|
+
* Processes streaming chunks from the Groq API and yields AG-UI stream events.
|
|
42
|
+
* Handles text content deltas, tool call assembly, and lifecycle events.
|
|
43
|
+
*/
|
|
44
|
+
private processGroqStreamChunks;
|
|
45
|
+
/**
|
|
46
|
+
* Maps common TextOptions to Groq-specific Chat Completions request parameters.
|
|
47
|
+
*/
|
|
48
|
+
private mapTextOptionsToGroq;
|
|
49
|
+
/**
|
|
50
|
+
* Converts a TanStack AI ModelMessage to a Groq ChatCompletionMessageParam.
|
|
51
|
+
* Handles tool, assistant, and user messages including multimodal content.
|
|
52
|
+
*/
|
|
53
|
+
private convertMessageToGroq;
|
|
54
|
+
/**
|
|
55
|
+
* Normalizes message content to an array of ContentPart.
|
|
56
|
+
* Handles backward compatibility with string content.
|
|
57
|
+
*/
|
|
58
|
+
private normalizeContent;
|
|
59
|
+
/**
|
|
60
|
+
* Extracts text content from a content value that may be string, null, or ContentPart array.
|
|
61
|
+
*/
|
|
62
|
+
private extractTextContent;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates a Groq text adapter with explicit API key.
|
|
66
|
+
* Type resolution happens here at the call site.
|
|
67
|
+
*
|
|
68
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')
|
|
69
|
+
* @param apiKey - Your Groq API key
|
|
70
|
+
* @param config - Optional additional configuration
|
|
71
|
+
* @returns Configured Groq text adapter instance with resolved types
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const adapter = createGroqText('llama-3.3-70b-versatile', "gsk_...");
|
|
76
|
+
* // adapter has type-safe providerOptions for llama-3.3-70b-versatile
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function createGroqText<TModel extends (typeof GROQ_CHAT_MODELS)[number]>(model: TModel, apiKey: string, config?: Omit<GroqTextConfig, 'apiKey'>): GroqTextAdapter<TModel>;
|
|
80
|
+
/**
|
|
81
|
+
* Creates a Groq text adapter with automatic API key detection from environment variables.
|
|
82
|
+
* Type resolution happens here at the call site.
|
|
83
|
+
*
|
|
84
|
+
* Looks for `GROQ_API_KEY` in:
|
|
85
|
+
* - `process.env` (Node.js)
|
|
86
|
+
* - `window.env` (Browser with injected env)
|
|
87
|
+
*
|
|
88
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile', 'openai/gpt-oss-120b')
|
|
89
|
+
* @param config - Optional configuration (excluding apiKey which is auto-detected)
|
|
90
|
+
* @returns Configured Groq text adapter instance with resolved types
|
|
91
|
+
* @throws Error if GROQ_API_KEY is not found in environment
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Automatically uses GROQ_API_KEY from environment
|
|
96
|
+
* const adapter = groqText('llama-3.3-70b-versatile');
|
|
97
|
+
*
|
|
98
|
+
* const stream = chat({
|
|
99
|
+
* adapter,
|
|
100
|
+
* messages: [{ role: "user", content: "Hello!" }]
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function groqText<TModel extends (typeof GROQ_CHAT_MODELS)[number]>(model: TModel, config?: Omit<GroqTextConfig, 'apiKey'>): GroqTextAdapter<TModel>;
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { BaseTextAdapter } from "@tanstack/ai/adapters";
|
|
2
|
+
import { validateTextProviderOptions } from "../text/text-provider-options.js";
|
|
3
|
+
import { makeGroqStructuredOutputCompatible, transformNullsToUndefined } from "../utils/schema-converter.js";
|
|
4
|
+
import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
|
|
5
|
+
import { createGroqClient, generateId, getGroqApiKeyFromEnv } from "../utils/client.js";
|
|
6
|
+
class GroqTextAdapter extends BaseTextAdapter {
|
|
7
|
+
constructor(config, model) {
|
|
8
|
+
super({}, model);
|
|
9
|
+
this.kind = "text";
|
|
10
|
+
this.name = "groq";
|
|
11
|
+
this.client = createGroqClient(config);
|
|
12
|
+
}
|
|
13
|
+
async *chatStream(options) {
|
|
14
|
+
const requestParams = this.mapTextOptionsToGroq(options);
|
|
15
|
+
const timestamp = Date.now();
|
|
16
|
+
const aguiState = {
|
|
17
|
+
runId: generateId(this.name),
|
|
18
|
+
messageId: generateId(this.name),
|
|
19
|
+
timestamp,
|
|
20
|
+
hasEmittedRunStarted: false
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
const stream = await this.client.chat.completions.create({
|
|
24
|
+
...requestParams,
|
|
25
|
+
stream: true
|
|
26
|
+
});
|
|
27
|
+
yield* this.processGroqStreamChunks(stream, options, aguiState);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
const err = error;
|
|
30
|
+
if (!aguiState.hasEmittedRunStarted) {
|
|
31
|
+
aguiState.hasEmittedRunStarted = true;
|
|
32
|
+
yield {
|
|
33
|
+
type: "RUN_STARTED",
|
|
34
|
+
runId: aguiState.runId,
|
|
35
|
+
model: options.model,
|
|
36
|
+
timestamp
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
yield {
|
|
40
|
+
type: "RUN_ERROR",
|
|
41
|
+
runId: aguiState.runId,
|
|
42
|
+
model: options.model,
|
|
43
|
+
timestamp,
|
|
44
|
+
error: {
|
|
45
|
+
message: err.message || "Unknown error",
|
|
46
|
+
code: err.code
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
console.error(">>> chatStream: Fatal error during response creation <<<");
|
|
50
|
+
console.error(">>> Error message:", err.message);
|
|
51
|
+
console.error(">>> Error stack:", err.stack);
|
|
52
|
+
console.error(">>> Full error:", err);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate structured output using Groq's JSON Schema response format.
|
|
57
|
+
* Uses stream: false to get the complete response in one call.
|
|
58
|
+
*
|
|
59
|
+
* Groq has strict requirements for structured output:
|
|
60
|
+
* - All properties must be in the `required` array
|
|
61
|
+
* - Optional fields should have null added to their type union
|
|
62
|
+
* - additionalProperties must be false for all objects
|
|
63
|
+
*
|
|
64
|
+
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
65
|
+
* We apply Groq-specific transformations for structured output compatibility.
|
|
66
|
+
*/
|
|
67
|
+
async structuredOutput(options) {
|
|
68
|
+
const { chatOptions, outputSchema } = options;
|
|
69
|
+
const requestParams = this.mapTextOptionsToGroq(chatOptions);
|
|
70
|
+
const jsonSchema = makeGroqStructuredOutputCompatible(
|
|
71
|
+
outputSchema,
|
|
72
|
+
outputSchema.required || []
|
|
73
|
+
);
|
|
74
|
+
try {
|
|
75
|
+
const response = await this.client.chat.completions.create({
|
|
76
|
+
...requestParams,
|
|
77
|
+
stream: false,
|
|
78
|
+
response_format: {
|
|
79
|
+
type: "json_schema",
|
|
80
|
+
json_schema: {
|
|
81
|
+
name: "structured_output",
|
|
82
|
+
schema: jsonSchema,
|
|
83
|
+
strict: true
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const rawText = response.choices[0]?.message.content || "";
|
|
88
|
+
let parsed;
|
|
89
|
+
try {
|
|
90
|
+
parsed = JSON.parse(rawText);
|
|
91
|
+
} catch {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Failed to parse structured output as JSON. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? "..." : ""}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const transformed = transformNullsToUndefined(parsed);
|
|
97
|
+
return {
|
|
98
|
+
data: transformed,
|
|
99
|
+
rawText
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const err = error;
|
|
103
|
+
console.error(">>> structuredOutput: Error during response creation <<<");
|
|
104
|
+
console.error(">>> Error message:", err.message);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Processes streaming chunks from the Groq API and yields AG-UI stream events.
|
|
110
|
+
* Handles text content deltas, tool call assembly, and lifecycle events.
|
|
111
|
+
*/
|
|
112
|
+
async *processGroqStreamChunks(stream, options, aguiState) {
|
|
113
|
+
let accumulatedContent = "";
|
|
114
|
+
const timestamp = aguiState.timestamp;
|
|
115
|
+
let hasEmittedTextMessageStart = false;
|
|
116
|
+
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
117
|
+
try {
|
|
118
|
+
for await (const chunk of stream) {
|
|
119
|
+
const choice = chunk.choices[0];
|
|
120
|
+
if (!choice) continue;
|
|
121
|
+
if (!aguiState.hasEmittedRunStarted) {
|
|
122
|
+
aguiState.hasEmittedRunStarted = true;
|
|
123
|
+
yield {
|
|
124
|
+
type: "RUN_STARTED",
|
|
125
|
+
runId: aguiState.runId,
|
|
126
|
+
model: chunk.model || options.model,
|
|
127
|
+
timestamp
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const delta = choice.delta;
|
|
131
|
+
const deltaContent = delta.content;
|
|
132
|
+
const deltaToolCalls = delta.tool_calls;
|
|
133
|
+
if (deltaContent) {
|
|
134
|
+
if (!hasEmittedTextMessageStart) {
|
|
135
|
+
hasEmittedTextMessageStart = true;
|
|
136
|
+
yield {
|
|
137
|
+
type: "TEXT_MESSAGE_START",
|
|
138
|
+
messageId: aguiState.messageId,
|
|
139
|
+
model: chunk.model || options.model,
|
|
140
|
+
timestamp,
|
|
141
|
+
role: "assistant"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
accumulatedContent += deltaContent;
|
|
145
|
+
yield {
|
|
146
|
+
type: "TEXT_MESSAGE_CONTENT",
|
|
147
|
+
messageId: aguiState.messageId,
|
|
148
|
+
model: chunk.model || options.model,
|
|
149
|
+
timestamp,
|
|
150
|
+
delta: deltaContent,
|
|
151
|
+
content: accumulatedContent
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (deltaToolCalls) {
|
|
155
|
+
for (const toolCallDelta of deltaToolCalls) {
|
|
156
|
+
const index = toolCallDelta.index;
|
|
157
|
+
if (!toolCallsInProgress.has(index)) {
|
|
158
|
+
toolCallsInProgress.set(index, {
|
|
159
|
+
id: toolCallDelta.id || "",
|
|
160
|
+
name: toolCallDelta.function?.name || "",
|
|
161
|
+
arguments: "",
|
|
162
|
+
started: false
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const toolCall = toolCallsInProgress.get(index);
|
|
166
|
+
if (toolCallDelta.id) {
|
|
167
|
+
toolCall.id = toolCallDelta.id;
|
|
168
|
+
}
|
|
169
|
+
if (toolCallDelta.function?.name) {
|
|
170
|
+
toolCall.name = toolCallDelta.function.name;
|
|
171
|
+
}
|
|
172
|
+
if (toolCallDelta.function?.arguments) {
|
|
173
|
+
toolCall.arguments += toolCallDelta.function.arguments;
|
|
174
|
+
}
|
|
175
|
+
if (toolCall.id && toolCall.name && !toolCall.started) {
|
|
176
|
+
toolCall.started = true;
|
|
177
|
+
yield {
|
|
178
|
+
type: "TOOL_CALL_START",
|
|
179
|
+
toolCallId: toolCall.id,
|
|
180
|
+
toolName: toolCall.name,
|
|
181
|
+
model: chunk.model || options.model,
|
|
182
|
+
timestamp,
|
|
183
|
+
index
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (toolCallDelta.function?.arguments && toolCall.started) {
|
|
187
|
+
yield {
|
|
188
|
+
type: "TOOL_CALL_ARGS",
|
|
189
|
+
toolCallId: toolCall.id,
|
|
190
|
+
model: chunk.model || options.model,
|
|
191
|
+
timestamp,
|
|
192
|
+
delta: toolCallDelta.function.arguments
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (choice.finish_reason) {
|
|
198
|
+
if (choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0) {
|
|
199
|
+
for (const [, toolCall] of toolCallsInProgress) {
|
|
200
|
+
if (!toolCall.started || !toolCall.id || !toolCall.name) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
let parsedInput = {};
|
|
204
|
+
try {
|
|
205
|
+
parsedInput = toolCall.arguments ? JSON.parse(toolCall.arguments) : {};
|
|
206
|
+
} catch {
|
|
207
|
+
parsedInput = {};
|
|
208
|
+
}
|
|
209
|
+
yield {
|
|
210
|
+
type: "TOOL_CALL_END",
|
|
211
|
+
toolCallId: toolCall.id,
|
|
212
|
+
toolName: toolCall.name,
|
|
213
|
+
model: chunk.model || options.model,
|
|
214
|
+
timestamp,
|
|
215
|
+
input: parsedInput
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const computedFinishReason = choice.finish_reason === "tool_calls" || toolCallsInProgress.size > 0 ? "tool_calls" : choice.finish_reason === "length" ? "length" : "stop";
|
|
220
|
+
if (hasEmittedTextMessageStart) {
|
|
221
|
+
yield {
|
|
222
|
+
type: "TEXT_MESSAGE_END",
|
|
223
|
+
messageId: aguiState.messageId,
|
|
224
|
+
model: chunk.model || options.model,
|
|
225
|
+
timestamp
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const groqUsage = chunk.x_groq?.usage;
|
|
229
|
+
yield {
|
|
230
|
+
type: "RUN_FINISHED",
|
|
231
|
+
runId: aguiState.runId,
|
|
232
|
+
model: chunk.model || options.model,
|
|
233
|
+
timestamp,
|
|
234
|
+
usage: groqUsage ? {
|
|
235
|
+
promptTokens: groqUsage.prompt_tokens || 0,
|
|
236
|
+
completionTokens: groqUsage.completion_tokens || 0,
|
|
237
|
+
totalTokens: groqUsage.total_tokens || 0
|
|
238
|
+
} : void 0,
|
|
239
|
+
finishReason: computedFinishReason
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
const err = error;
|
|
245
|
+
console.log("[Groq Adapter] Stream ended with error:", err.message);
|
|
246
|
+
yield {
|
|
247
|
+
type: "RUN_ERROR",
|
|
248
|
+
runId: aguiState.runId,
|
|
249
|
+
model: options.model,
|
|
250
|
+
timestamp,
|
|
251
|
+
error: {
|
|
252
|
+
message: err.message || "Unknown error occurred",
|
|
253
|
+
code: err.code
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Maps common TextOptions to Groq-specific Chat Completions request parameters.
|
|
260
|
+
*/
|
|
261
|
+
mapTextOptionsToGroq(options) {
|
|
262
|
+
const modelOptions = options.modelOptions;
|
|
263
|
+
if (modelOptions) {
|
|
264
|
+
validateTextProviderOptions({
|
|
265
|
+
...modelOptions,
|
|
266
|
+
model: options.model
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const tools = options.tools ? convertToolsToProviderFormat(options.tools) : void 0;
|
|
270
|
+
const messages = [];
|
|
271
|
+
if (options.systemPrompts && options.systemPrompts.length > 0) {
|
|
272
|
+
messages.push({
|
|
273
|
+
role: "system",
|
|
274
|
+
content: options.systemPrompts.join("\n")
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
for (const message of options.messages) {
|
|
278
|
+
messages.push(this.convertMessageToGroq(message));
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
model: options.model,
|
|
282
|
+
messages,
|
|
283
|
+
temperature: options.temperature,
|
|
284
|
+
max_tokens: options.maxTokens,
|
|
285
|
+
top_p: options.topP,
|
|
286
|
+
tools,
|
|
287
|
+
stream: true
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Converts a TanStack AI ModelMessage to a Groq ChatCompletionMessageParam.
|
|
292
|
+
* Handles tool, assistant, and user messages including multimodal content.
|
|
293
|
+
*/
|
|
294
|
+
convertMessageToGroq(message) {
|
|
295
|
+
if (message.role === "tool") {
|
|
296
|
+
return {
|
|
297
|
+
role: "tool",
|
|
298
|
+
tool_call_id: message.toolCallId || "",
|
|
299
|
+
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content)
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
if (message.role === "assistant") {
|
|
303
|
+
const toolCalls = message.toolCalls?.map((tc) => ({
|
|
304
|
+
id: tc.id,
|
|
305
|
+
type: "function",
|
|
306
|
+
function: {
|
|
307
|
+
name: tc.function.name,
|
|
308
|
+
arguments: typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
309
|
+
}
|
|
310
|
+
}));
|
|
311
|
+
return {
|
|
312
|
+
role: "assistant",
|
|
313
|
+
content: this.extractTextContent(message.content),
|
|
314
|
+
...toolCalls && toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const contentParts = this.normalizeContent(message.content);
|
|
318
|
+
if (contentParts.length === 1 && contentParts[0]?.type === "text") {
|
|
319
|
+
return {
|
|
320
|
+
role: "user",
|
|
321
|
+
content: contentParts[0].content
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const parts = [];
|
|
325
|
+
for (const part of contentParts) {
|
|
326
|
+
if (part.type === "text") {
|
|
327
|
+
parts.push({ type: "text", text: part.content });
|
|
328
|
+
} else if (part.type === "image") {
|
|
329
|
+
const imageMetadata = part.metadata;
|
|
330
|
+
const imageValue = part.source.value;
|
|
331
|
+
const imageUrl = part.source.type === "data" && !imageValue.startsWith("data:") ? `data:${part.source.mimeType};base64,${imageValue}` : imageValue;
|
|
332
|
+
parts.push({
|
|
333
|
+
type: "image_url",
|
|
334
|
+
image_url: {
|
|
335
|
+
url: imageUrl,
|
|
336
|
+
detail: imageMetadata?.detail || "auto"
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
role: "user",
|
|
343
|
+
content: parts.length > 0 ? parts : ""
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Normalizes message content to an array of ContentPart.
|
|
348
|
+
* Handles backward compatibility with string content.
|
|
349
|
+
*/
|
|
350
|
+
normalizeContent(content) {
|
|
351
|
+
if (content === null) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
if (typeof content === "string") {
|
|
355
|
+
return [{ type: "text", content }];
|
|
356
|
+
}
|
|
357
|
+
return content;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Extracts text content from a content value that may be string, null, or ContentPart array.
|
|
361
|
+
*/
|
|
362
|
+
extractTextContent(content) {
|
|
363
|
+
if (content === null) {
|
|
364
|
+
return "";
|
|
365
|
+
}
|
|
366
|
+
if (typeof content === "string") {
|
|
367
|
+
return content;
|
|
368
|
+
}
|
|
369
|
+
return content.filter((p) => p.type === "text").map((p) => p.content).join("");
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function createGroqText(model, apiKey, config) {
|
|
373
|
+
return new GroqTextAdapter({ apiKey, ...config }, model);
|
|
374
|
+
}
|
|
375
|
+
function groqText(model, config) {
|
|
376
|
+
const apiKey = getGroqApiKeyFromEnv();
|
|
377
|
+
return createGroqText(model, apiKey, config);
|
|
378
|
+
}
|
|
379
|
+
export {
|
|
380
|
+
GroqTextAdapter,
|
|
381
|
+
createGroqText,
|
|
382
|
+
groqText
|
|
383
|
+
};
|
|
384
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { validateTextProviderOptions } from '../text/text-provider-options'\nimport { convertToolsToProviderFormat } from '../tools'\nimport {\n 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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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @tanstack/ai-groq
|
|
3
|
+
*
|
|
4
|
+
* Groq provider adapter for TanStack AI.
|
|
5
|
+
* Provides tree-shakeable adapters for Groq's Chat Completions API.
|
|
6
|
+
*/
|
|
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';
|
|
9
|
+
export { GROQ_CHAT_MODELS } from './model-meta.js';
|
|
10
|
+
export type { GroqTextMetadata, GroqImageMetadata, GroqAudioMetadata, GroqVideoMetadata, GroqDocumentMetadata, GroqMessageMetadataByModality, } from './message-types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|