@tanstack/ai-groq 0.5.3 → 0.6.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 +1 -0
- package/dist/esm/adapters/summarize.d.ts +51 -0
- package/dist/esm/adapters/summarize.js +55 -0
- package/dist/esm/adapters/summarize.js.map +1 -0
- package/dist/esm/adapters/text.js +89 -61
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/adapters/transcription.js +210 -172
- package/dist/esm/adapters/transcription.js.map +1 -1
- package/dist/esm/adapters/tts.js +128 -66
- package/dist/esm/adapters/tts.js.map +1 -1
- package/dist/esm/audio/audio-provider-options.js +11 -8
- package/dist/esm/audio/audio-provider-options.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -15
- package/dist/esm/model-meta.js +300 -69
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/tools/function-tool.js +31 -26
- package/dist/esm/tools/function-tool.js.map +1 -1
- package/dist/esm/tools/index.js +1 -5
- package/dist/esm/tools/tool-converter.js +12 -7
- package/dist/esm/tools/tool-converter.js.map +1 -1
- package/dist/esm/utils/client.js +23 -16
- package/dist/esm/utils/client.js.map +1 -1
- package/dist/esm/utils/schema-converter.d.ts +0 -2
- package/dist/esm/utils/schema-converter.js +66 -66
- package/dist/esm/utils/schema-converter.js.map +1 -1
- package/package.json +7 -7
- package/src/adapters/summarize.ts +77 -0
- package/src/index.ts +8 -0
- package/src/utils/schema-converter.ts +0 -3
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/tools/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ const adapter = createGroqText('llama-3.3-70b-versatile', 'gsk_api_key')
|
|
|
72
72
|
- ✅ Structured output (JSON Schema)
|
|
73
73
|
- ✅ Function/tool calling
|
|
74
74
|
- ✅ Multimodal input (text + images for vision models)
|
|
75
|
+
- ✅ Summarization (`groqSummarize`)
|
|
75
76
|
- ❌ Embeddings (not supported by Groq)
|
|
76
77
|
- ❌ Image generation (not supported by Groq)
|
|
77
78
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ChatStreamSummarizeAdapter, InferTextProviderOptions } from '@tanstack/ai/adapters';
|
|
2
|
+
import { GroqTextAdapter } from './text.js';
|
|
3
|
+
import { GROQ_CHAT_MODELS } from '../model-meta.js';
|
|
4
|
+
import { GroqClientConfig } from '../utils/client.js';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for Groq summarize adapter
|
|
7
|
+
*/
|
|
8
|
+
export interface GroqSummarizeConfig extends GroqClientConfig {
|
|
9
|
+
}
|
|
10
|
+
/** Model type for Groq summarization */
|
|
11
|
+
export type GroqSummarizeModel = (typeof GROQ_CHAT_MODELS)[number];
|
|
12
|
+
/**
|
|
13
|
+
* Creates a Groq summarize adapter with explicit API key.
|
|
14
|
+
* Type resolution happens here at the call site.
|
|
15
|
+
*
|
|
16
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile')
|
|
17
|
+
* @param apiKey - Your Groq API key
|
|
18
|
+
* @param config - Optional additional configuration
|
|
19
|
+
* @returns Configured Groq summarize adapter instance with resolved types
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const adapter = createGroqSummarize('llama-3.3-70b-versatile', "gsk_...");
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function createGroqSummarize<TModel extends GroqSummarizeModel>(model: TModel, apiKey: string, config?: Omit<GroqSummarizeConfig, 'apiKey'>): ChatStreamSummarizeAdapter<TModel, InferTextProviderOptions<GroqTextAdapter<TModel>>>;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a Groq summarize adapter with automatic API key detection from environment variables.
|
|
29
|
+
* Type resolution happens here at the call site.
|
|
30
|
+
*
|
|
31
|
+
* Looks for `GROQ_API_KEY` in:
|
|
32
|
+
* - `process.env` (Node.js)
|
|
33
|
+
* - `window.env` (Browser with injected env)
|
|
34
|
+
*
|
|
35
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile')
|
|
36
|
+
* @param config - Optional configuration (excluding apiKey which is auto-detected)
|
|
37
|
+
* @returns Configured Groq summarize adapter instance with resolved types
|
|
38
|
+
* @throws Error if GROQ_API_KEY is not found in environment
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* // Automatically uses GROQ_API_KEY from environment
|
|
43
|
+
* const adapter = groqSummarize('llama-3.3-70b-versatile');
|
|
44
|
+
*
|
|
45
|
+
* await summarize({
|
|
46
|
+
* adapter,
|
|
47
|
+
* text: "Long article text..."
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function groqSummarize<TModel extends GroqSummarizeModel>(model: TModel, config?: Omit<GroqSummarizeConfig, 'apiKey'>): ChatStreamSummarizeAdapter<TModel, InferTextProviderOptions<GroqTextAdapter<TModel>>>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getGroqApiKeyFromEnv } from "../utils/client.js";
|
|
2
|
+
import { GroqTextAdapter } from "./text.js";
|
|
3
|
+
import { ChatStreamSummarizeAdapter } from "@tanstack/ai/adapters";
|
|
4
|
+
//#region src/adapters/summarize.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Groq summarize adapter with explicit API key.
|
|
7
|
+
* Type resolution happens here at the call site.
|
|
8
|
+
*
|
|
9
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile')
|
|
10
|
+
* @param apiKey - Your Groq API key
|
|
11
|
+
* @param config - Optional additional configuration
|
|
12
|
+
* @returns Configured Groq summarize adapter instance with resolved types
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const adapter = createGroqSummarize('llama-3.3-70b-versatile', "gsk_...");
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
function createGroqSummarize(model, apiKey, config) {
|
|
20
|
+
return new ChatStreamSummarizeAdapter(new GroqTextAdapter({
|
|
21
|
+
apiKey,
|
|
22
|
+
...config
|
|
23
|
+
}, model), model, "groq");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a Groq summarize adapter with automatic API key detection from environment variables.
|
|
27
|
+
* Type resolution happens here at the call site.
|
|
28
|
+
*
|
|
29
|
+
* Looks for `GROQ_API_KEY` in:
|
|
30
|
+
* - `process.env` (Node.js)
|
|
31
|
+
* - `window.env` (Browser with injected env)
|
|
32
|
+
*
|
|
33
|
+
* @param model - The model name (e.g., 'llama-3.3-70b-versatile')
|
|
34
|
+
* @param config - Optional configuration (excluding apiKey which is auto-detected)
|
|
35
|
+
* @returns Configured Groq summarize adapter instance with resolved types
|
|
36
|
+
* @throws Error if GROQ_API_KEY is not found in environment
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Automatically uses GROQ_API_KEY from environment
|
|
41
|
+
* const adapter = groqSummarize('llama-3.3-70b-versatile');
|
|
42
|
+
*
|
|
43
|
+
* await summarize({
|
|
44
|
+
* adapter,
|
|
45
|
+
* text: "Long article text..."
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
function groqSummarize(model, config) {
|
|
50
|
+
return createGroqSummarize(model, getGroqApiKeyFromEnv(), config);
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { createGroqSummarize, groqSummarize };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=summarize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarize.js","names":[],"sources":["../../../src/adapters/summarize.ts"],"sourcesContent":["import { ChatStreamSummarizeAdapter } from '@tanstack/ai/adapters'\nimport { getGroqApiKeyFromEnv } from '../utils/client'\nimport { GroqTextAdapter } from './text'\nimport type { InferTextProviderOptions } from '@tanstack/ai/adapters'\nimport type { GROQ_CHAT_MODELS } from '../model-meta'\nimport type { GroqClientConfig } from '../utils/client'\n\n/**\n * Configuration for Groq summarize adapter\n */\nexport interface GroqSummarizeConfig extends GroqClientConfig {}\n\n/** Model type for Groq summarization */\nexport type GroqSummarizeModel = (typeof GROQ_CHAT_MODELS)[number]\n\n/**\n * Creates a Groq summarize 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')\n * @param apiKey - Your Groq API key\n * @param config - Optional additional configuration\n * @returns Configured Groq summarize adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGroqSummarize('llama-3.3-70b-versatile', \"gsk_...\");\n * ```\n */\nexport function createGroqSummarize<TModel extends GroqSummarizeModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GroqSummarizeConfig, 'apiKey'>,\n): ChatStreamSummarizeAdapter<\n TModel,\n InferTextProviderOptions<GroqTextAdapter<TModel>>\n> {\n return new ChatStreamSummarizeAdapter(\n new GroqTextAdapter({ apiKey, ...config }, model),\n model,\n 'groq',\n )\n}\n\n/**\n * Creates a Groq summarize 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')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Groq summarize 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 = groqSummarize('llama-3.3-70b-versatile');\n *\n * await summarize({\n * adapter,\n * text: \"Long article text...\"\n * });\n * ```\n */\nexport function groqSummarize<TModel extends GroqSummarizeModel>(\n model: TModel,\n config?: Omit<GroqSummarizeConfig, 'apiKey'>,\n): ChatStreamSummarizeAdapter<\n TModel,\n InferTextProviderOptions<GroqTextAdapter<TModel>>\n> {\n return createGroqSummarize(model, getGroqApiKeyFromEnv(), config)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA6BA,SAAgB,oBACd,OACA,QACA,QAIA;CACA,OAAO,IAAI,2BACT,IAAI,gBAAgB;EAAE;EAAQ,GAAG;CAAO,GAAG,KAAK,GAChD,OACA,MACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,cACd,OACA,QAIA;CACA,OAAO,oBAAoB,OAAO,qBAAqB,GAAG,MAAM;AAClE"}
|
|
@@ -1,69 +1,97 @@
|
|
|
1
|
+
import { getGroqApiKeyFromEnv, withGroqDefaults } from "../utils/client.js";
|
|
2
|
+
import { makeGroqStructuredOutputCompatible } from "../utils/schema-converter.js";
|
|
1
3
|
import OpenAI from "openai";
|
|
2
4
|
import { OpenAIBaseChatCompletionsTextAdapter } from "@tanstack/openai-base";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
5
|
+
//#region src/adapters/text.ts
|
|
6
|
+
/**
|
|
7
|
+
* Groq Text (Chat) Adapter
|
|
8
|
+
*
|
|
9
|
+
* Tree-shakeable adapter for Groq chat/text completion. Groq exposes an
|
|
10
|
+
* OpenAI-compatible Chat Completions endpoint at `/openai/v1`, so we drive
|
|
11
|
+
* it with the OpenAI SDK via a `baseURL` override (the same pattern as
|
|
12
|
+
* `ai-grok`).
|
|
13
|
+
*
|
|
14
|
+
* Quirk: when usage is present on a stream, Groq historically delivered it
|
|
15
|
+
* under `chunk.x_groq.usage` rather than `chunk.usage`. The override below
|
|
16
|
+
* promotes it to the standard location so the base's RUN_FINISHED usage
|
|
17
|
+
* accounting works unchanged.
|
|
18
|
+
*/
|
|
19
|
+
var GroqTextAdapter = class extends OpenAIBaseChatCompletionsTextAdapter {
|
|
20
|
+
kind = "text";
|
|
21
|
+
name = "groq";
|
|
22
|
+
constructor(config, model) {
|
|
23
|
+
super(model, "groq", new OpenAI(withGroqDefaults(config)));
|
|
24
|
+
}
|
|
25
|
+
makeStructuredOutputCompatible(schema, originalRequired) {
|
|
26
|
+
return makeGroqStructuredOutputCompatible(schema, originalRequired);
|
|
27
|
+
}
|
|
28
|
+
async *processStreamChunks(stream, options, aguiState) {
|
|
29
|
+
yield* super.processStreamChunks(promoteGroqUsage(stream), options, aguiState);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Surfaces Groq's reasoning deltas during streaming structured output.
|
|
33
|
+
* Groq emits `delta.reasoning` (or legacy `delta.reasoning_content`) on
|
|
34
|
+
* reasoning models when the caller sets `reasoning_format: 'parsed'` in
|
|
35
|
+
* modelOptions. The base's chatStream and structuredOutputStream both
|
|
36
|
+
* route reasoning through this hook.
|
|
37
|
+
*/
|
|
38
|
+
extractReasoning(chunk) {
|
|
39
|
+
const delta = chunk.choices[0]?.delta;
|
|
40
|
+
const raw = delta?.reasoning ?? delta?.reasoning_content;
|
|
41
|
+
if (typeof raw === "string" && raw.length > 0) return { text: raw };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Groq's API rejects `response_format: json_schema` together with `tools`
|
|
45
|
+
* + `stream` (returns 400 — see Groq Structured Outputs docs:
|
|
46
|
+
* "Streaming and tool use are not currently supported with Structured
|
|
47
|
+
* Outputs."). Force the engine onto the legacy finalization path even
|
|
48
|
+
* though the OpenAI Chat Completions base would otherwise opt in.
|
|
49
|
+
*/
|
|
50
|
+
supportsCombinedToolsAndSchema() {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Promotes Groq's non-standard `x_groq.usage` to the standard `chunk.usage`
|
|
56
|
+
* slot the base reads. Pass-through for chunks that already carry usage at
|
|
57
|
+
* the documented location.
|
|
58
|
+
*/
|
|
47
59
|
async function* promoteGroqUsage(stream) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
for await (const chunk of stream) {
|
|
61
|
+
const groqChunk = chunk;
|
|
62
|
+
if (!chunk.usage && groqChunk.x_groq?.usage) yield {
|
|
63
|
+
...chunk,
|
|
64
|
+
usage: groqChunk.x_groq.usage
|
|
65
|
+
};
|
|
66
|
+
else yield chunk;
|
|
67
|
+
}
|
|
56
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates a Groq text adapter with explicit API key.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const adapter = createGroqText('llama-3.3-70b-versatile', "gsk_...");
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
57
77
|
function createGroqText(model, apiKey, config) {
|
|
58
|
-
|
|
78
|
+
return new GroqTextAdapter({
|
|
79
|
+
apiKey,
|
|
80
|
+
...config
|
|
81
|
+
}, model);
|
|
59
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a Groq text adapter with API key from `GROQ_API_KEY`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const adapter = groqText('llama-3.3-70b-versatile');
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
60
91
|
function groqText(model, config) {
|
|
61
|
-
|
|
62
|
-
return createGroqText(model, apiKey, config);
|
|
92
|
+
return createGroqText(model, getGroqApiKeyFromEnv(), config);
|
|
63
93
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
//# sourceMappingURL=text.js.map
|
|
94
|
+
//#endregion
|
|
95
|
+
export { GroqTextAdapter, createGroqText, groqText };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { getGroqApiKeyFromEnv, withGroqDefaults } from '../utils/client'\nimport { makeGroqStructuredOutputCompatible } from '../utils/schema-converter'\nimport type { Modality, TextOptions } from '@tanstack/ai'\nimport type {\n GROQ_CHAT_MODELS,\n GroqChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type { GroqMessageMetadataByModality } from '../message-types'\nimport type { GroqClientConfig } from '../utils/client'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GroqChatModelToolCapabilitiesByName\n ? NonNullable<GroqChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Configuration for Groq text adapter\n */\nexport interface GroqTextConfig extends GroqClientConfig {}\n\n/**\n * Re-export of the public provider options type\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. Groq exposes an\n * OpenAI-compatible Chat Completions endpoint at `/openai/v1`, so we drive\n * it with the OpenAI SDK via a `baseURL` override (the same pattern as\n * `ai-grok`).\n *\n * Quirk: when usage is present on a stream, Groq historically delivered it\n * under `chunk.x_groq.usage` rather than `chunk.usage`. The override below\n * promotes it to the standard location so the base's RUN_FINISHED usage\n * accounting works unchanged.\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 OpenAIBaseChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n GroqMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'groq' as const\n\n constructor(config: GroqTextConfig, model: TModel) {\n super(model, 'groq', new OpenAI(withGroqDefaults(config)))\n }\n\n protected override makeStructuredOutputCompatible(\n schema: Record<string, any>,\n originalRequired?: Array<string>,\n ): Record<string, any> {\n return makeGroqStructuredOutputCompatible(schema, originalRequired)\n }\n\n protected override async *processStreamChunks(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n options: TextOptions,\n aguiState: {\n runId: string\n threadId: string\n messageId: string\n hasEmittedRunStarted: boolean\n },\n ) {\n yield* super.processStreamChunks(\n promoteGroqUsage(stream),\n options,\n aguiState,\n )\n }\n\n /**\n * Surfaces Groq's reasoning deltas during streaming structured output.\n * Groq emits `delta.reasoning` (or legacy `delta.reasoning_content`) on\n * reasoning models when the caller sets `reasoning_format: 'parsed'` in\n * modelOptions. The base's chatStream and structuredOutputStream both\n * route reasoning through this hook.\n */\n protected override extractReasoning(\n chunk: OpenAI.Chat.Completions.ChatCompletionChunk,\n ): { text: string } | undefined {\n const delta = chunk.choices[0]?.delta as\n | { reasoning?: unknown; reasoning_content?: unknown }\n | undefined\n const raw = delta?.reasoning ?? delta?.reasoning_content\n if (typeof raw === 'string' && raw.length > 0) {\n return { text: raw }\n }\n return undefined\n }\n\n /**\n * Groq's API rejects `response_format: json_schema` together with `tools`\n * + `stream` (returns 400 — see Groq Structured Outputs docs:\n * \"Streaming and tool use are not currently supported with Structured\n * Outputs.\"). Force the engine onto the legacy finalization path even\n * though the OpenAI Chat Completions base would otherwise opt in.\n */\n override supportsCombinedToolsAndSchema(): boolean {\n return false\n }\n}\n\n/**\n * Promotes Groq's non-standard `x_groq.usage` to the standard `chunk.usage`\n * slot the base reads. Pass-through for chunks that already carry usage at\n * the documented location.\n */\nasync function* promoteGroqUsage(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n): AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk> {\n for await (const chunk of stream) {\n const groqChunk = chunk as typeof chunk & {\n x_groq?: { usage?: OpenAI.Chat.Completions.ChatCompletionChunk['usage'] }\n }\n if (!chunk.usage && groqChunk.x_groq?.usage) {\n yield { ...chunk, usage: groqChunk.x_groq.usage }\n } else {\n yield chunk\n }\n }\n}\n\n/**\n * Creates a Groq text adapter with explicit API key.\n *\n * @example\n * ```typescript\n * const adapter = createGroqText('llama-3.3-70b-versatile', \"gsk_...\");\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 API key from `GROQ_API_KEY`.\n *\n * @example\n * ```typescript\n * const adapter = groqText('llama-3.3-70b-versatile');\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"],"
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../src/adapters/text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { getGroqApiKeyFromEnv, withGroqDefaults } from '../utils/client'\nimport { makeGroqStructuredOutputCompatible } from '../utils/schema-converter'\nimport type { Modality, TextOptions } from '@tanstack/ai'\nimport type {\n GROQ_CHAT_MODELS,\n GroqChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type { GroqMessageMetadataByModality } from '../message-types'\nimport type { GroqClientConfig } from '../utils/client'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GroqChatModelToolCapabilitiesByName\n ? NonNullable<GroqChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Configuration for Groq text adapter\n */\nexport interface GroqTextConfig extends GroqClientConfig {}\n\n/**\n * Re-export of the public provider options type\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. Groq exposes an\n * OpenAI-compatible Chat Completions endpoint at `/openai/v1`, so we drive\n * it with the OpenAI SDK via a `baseURL` override (the same pattern as\n * `ai-grok`).\n *\n * Quirk: when usage is present on a stream, Groq historically delivered it\n * under `chunk.x_groq.usage` rather than `chunk.usage`. The override below\n * promotes it to the standard location so the base's RUN_FINISHED usage\n * accounting works unchanged.\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 OpenAIBaseChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n GroqMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'groq' as const\n\n constructor(config: GroqTextConfig, model: TModel) {\n super(model, 'groq', new OpenAI(withGroqDefaults(config)))\n }\n\n protected override makeStructuredOutputCompatible(\n schema: Record<string, any>,\n originalRequired?: Array<string>,\n ): Record<string, any> {\n return makeGroqStructuredOutputCompatible(schema, originalRequired)\n }\n\n protected override async *processStreamChunks(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n options: TextOptions,\n aguiState: {\n runId: string\n threadId: string\n messageId: string\n hasEmittedRunStarted: boolean\n },\n ) {\n yield* super.processStreamChunks(\n promoteGroqUsage(stream),\n options,\n aguiState,\n )\n }\n\n /**\n * Surfaces Groq's reasoning deltas during streaming structured output.\n * Groq emits `delta.reasoning` (or legacy `delta.reasoning_content`) on\n * reasoning models when the caller sets `reasoning_format: 'parsed'` in\n * modelOptions. The base's chatStream and structuredOutputStream both\n * route reasoning through this hook.\n */\n protected override extractReasoning(\n chunk: OpenAI.Chat.Completions.ChatCompletionChunk,\n ): { text: string } | undefined {\n const delta = chunk.choices[0]?.delta as\n | { reasoning?: unknown; reasoning_content?: unknown }\n | undefined\n const raw = delta?.reasoning ?? delta?.reasoning_content\n if (typeof raw === 'string' && raw.length > 0) {\n return { text: raw }\n }\n return undefined\n }\n\n /**\n * Groq's API rejects `response_format: json_schema` together with `tools`\n * + `stream` (returns 400 — see Groq Structured Outputs docs:\n * \"Streaming and tool use are not currently supported with Structured\n * Outputs.\"). Force the engine onto the legacy finalization path even\n * though the OpenAI Chat Completions base would otherwise opt in.\n */\n override supportsCombinedToolsAndSchema(): boolean {\n return false\n }\n}\n\n/**\n * Promotes Groq's non-standard `x_groq.usage` to the standard `chunk.usage`\n * slot the base reads. Pass-through for chunks that already carry usage at\n * the documented location.\n */\nasync function* promoteGroqUsage(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n): AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk> {\n for await (const chunk of stream) {\n const groqChunk = chunk as typeof chunk & {\n x_groq?: { usage?: OpenAI.Chat.Completions.ChatCompletionChunk['usage'] }\n }\n if (!chunk.usage && groqChunk.x_groq?.usage) {\n yield { ...chunk, usage: groqChunk.x_groq.usage }\n } else {\n yield chunk\n }\n }\n}\n\n/**\n * Creates a Groq text adapter with explicit API key.\n *\n * @example\n * ```typescript\n * const adapter = createGroqText('llama-3.3-70b-versatile', \"gsk_...\");\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 API key from `GROQ_API_KEY`.\n *\n * @example\n * ```typescript\n * const adapter = groqText('llama-3.3-70b-versatile');\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"],"mappings":";;;;;;;;;;;;;;;;;;AA0CA,IAAa,kBAAb,cAOU,qCAMR;CACA,OAAyB;CACzB,OAAyB;CAEzB,YAAY,QAAwB,OAAe;EACjD,MAAM,OAAO,QAAQ,IAAI,OAAO,iBAAiB,MAAM,CAAC,CAAC;CAC3D;CAEA,+BACE,QACA,kBACqB;EACrB,OAAO,mCAAmC,QAAQ,gBAAgB;CACpE;CAEA,OAA0B,oBACxB,QACA,SACA,WAMA;EACA,OAAO,MAAM,oBACX,iBAAiB,MAAM,GACvB,SACA,SACF;CACF;;;;;;;;CASA,iBACE,OAC8B;EAC9B,MAAM,QAAQ,MAAM,QAAQ,EAAE,EAAE;EAGhC,MAAM,MAAM,OAAO,aAAa,OAAO;EACvC,IAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,GAC1C,OAAO,EAAE,MAAM,IAAI;CAGvB;;;;;;;;CASA,iCAAmD;EACjD,OAAO;CACT;AACF;;;;;;AAOA,gBAAgB,iBACd,QAC4D;CAC5D,WAAW,MAAM,SAAS,QAAQ;EAChC,MAAM,YAAY;EAGlB,IAAI,CAAC,MAAM,SAAS,UAAU,QAAQ,OACpC,MAAM;GAAE,GAAG;GAAO,OAAO,UAAU,OAAO;EAAM;OAEhD,MAAM;CAEV;AACF;;;;;;;;;AAUA,SAAgB,eAGd,OACA,QACA,QACyB;CACzB,OAAO,IAAI,gBAAgB;EAAE;EAAQ,GAAG;CAAO,GAAG,KAAK;AACzD;;;;;;;;;AAUA,SAAgB,SACd,OACA,QACyB;CAEzB,OAAO,eAAe,OADP,qBACc,GAAQ,MAAM;AAC7C"}
|