@tanstack/ai-llmgateway 0.0.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.
@@ -0,0 +1,79 @@
1
+ import { ChatStreamSummarizeAdapter } from '@tanstack/ai/adapters'
2
+ import { getLLMGatewayApiKeyFromEnv } from '../utils/client'
3
+ import { LLMGatewayTextAdapter } from './text'
4
+ import type { InferTextProviderOptions } from '@tanstack/ai/adapters'
5
+ import type { LLMGatewayModelId } from '../model-meta'
6
+ import type { LLMGatewayClientConfig } from '../utils/client'
7
+
8
+ /**
9
+ * Configuration for LLM Gateway summarize adapter
10
+ */
11
+ export interface LLMGatewaySummarizeConfig extends LLMGatewayClientConfig {}
12
+
13
+ /** Model type for LLM Gateway summarization */
14
+ export type LLMGatewaySummarizeModel = LLMGatewayModelId
15
+
16
+ /**
17
+ * Creates an LLM Gateway summarize adapter with explicit API key.
18
+ * Type resolution happens here at the call site.
19
+ *
20
+ * @param model - The model id (e.g., 'gpt-5.6-terra')
21
+ * @param apiKey - Your LLM Gateway API key
22
+ * @param config - Optional additional configuration
23
+ * @returns Configured LLM Gateway summarize adapter instance with resolved types
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const adapter = createLLMGatewaySummarize('gpt-5.6-terra', "llmgtwy_...");
28
+ * ```
29
+ */
30
+ export function createLLMGatewaySummarize<
31
+ TModel extends LLMGatewaySummarizeModel,
32
+ >(
33
+ model: TModel,
34
+ apiKey: string,
35
+ config?: Omit<LLMGatewaySummarizeConfig, 'apiKey'>,
36
+ ): ChatStreamSummarizeAdapter<
37
+ TModel,
38
+ InferTextProviderOptions<LLMGatewayTextAdapter<TModel>>
39
+ > {
40
+ return new ChatStreamSummarizeAdapter(
41
+ new LLMGatewayTextAdapter({ apiKey, ...config }, model),
42
+ model,
43
+ 'llmgateway',
44
+ )
45
+ }
46
+
47
+ /**
48
+ * Creates an LLM Gateway summarize adapter with automatic API key detection
49
+ * from environment variables. Type resolution happens here at the call site.
50
+ *
51
+ * Looks for `LLM_GATEWAY_API_KEY` in:
52
+ * - `process.env` (Node.js)
53
+ * - `window.env` (Browser with injected env)
54
+ *
55
+ * @param model - The model id (e.g., 'gpt-5.6-terra')
56
+ * @param config - Optional configuration (excluding apiKey which is auto-detected)
57
+ * @returns Configured LLM Gateway summarize adapter instance with resolved types
58
+ * @throws Error if LLM_GATEWAY_API_KEY is not found in environment
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * // Automatically uses LLM_GATEWAY_API_KEY from environment
63
+ * const adapter = llmGatewaySummarize('gpt-5.6-terra');
64
+ *
65
+ * await summarize({
66
+ * adapter,
67
+ * text: "Long article text..."
68
+ * });
69
+ * ```
70
+ */
71
+ export function llmGatewaySummarize<TModel extends LLMGatewaySummarizeModel>(
72
+ model: TModel,
73
+ config?: Omit<LLMGatewaySummarizeConfig, 'apiKey'>,
74
+ ): ChatStreamSummarizeAdapter<
75
+ TModel,
76
+ InferTextProviderOptions<LLMGatewayTextAdapter<TModel>>
77
+ > {
78
+ return createLLMGatewaySummarize(model, getLLMGatewayApiKeyFromEnv(), config)
79
+ }
@@ -0,0 +1,119 @@
1
+ import OpenAI from 'openai'
2
+ import { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'
3
+ import {
4
+ getLLMGatewayApiKeyFromEnv,
5
+ withLLMGatewayDefaults,
6
+ } from '../utils/client'
7
+ import type { Modality } from '@tanstack/ai'
8
+ import type {
9
+ LLMGatewayChatModelToolCapabilitiesByName,
10
+ LLMGatewayModelId,
11
+ ResolveInputModalities,
12
+ ResolveProviderOptions,
13
+ } from '../model-meta'
14
+ import type { LLMGatewayMessageMetadataByModality } from '../message-types'
15
+ import type { LLMGatewayClientConfig } from '../utils/client'
16
+
17
+ type ResolveToolCapabilities<TModel extends string> =
18
+ TModel extends keyof LLMGatewayChatModelToolCapabilitiesByName
19
+ ? NonNullable<LLMGatewayChatModelToolCapabilitiesByName[TModel]>
20
+ : readonly []
21
+
22
+ /**
23
+ * Configuration for LLM Gateway text adapter
24
+ */
25
+ export interface LLMGatewayTextConfig extends LLMGatewayClientConfig {}
26
+
27
+ /**
28
+ * Re-export of the public provider options type
29
+ */
30
+ export type { ExternalTextProviderOptions as LLMGatewayTextProviderOptions } from '../text/text-provider-options'
31
+
32
+ /**
33
+ * LLM Gateway Text (Chat) Adapter
34
+ *
35
+ * Tree-shakeable adapter for LLM Gateway chat/text completion. LLM Gateway
36
+ * exposes one OpenAI-compatible Chat Completions endpoint that routes to
37
+ * hundreds of models across many providers, so the adapter drives it with
38
+ * the OpenAI SDK via a `baseURL` override (the same pattern as `ai-grok`
39
+ * and `ai-groq`).
40
+ *
41
+ * Model ids are open-ended: curated ids get per-model type metadata, and
42
+ * any other id from https://llmgateway.io/models works with text-only
43
+ * defaults. A `provider/model` id (e.g. `openai/gpt-5.5`) pins routing to
44
+ * that provider; a bare id lets the gateway pick.
45
+ */
46
+ export class LLMGatewayTextAdapter<
47
+ TModel extends LLMGatewayModelId,
48
+ TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,
49
+ TInputModalities extends ReadonlyArray<Modality> =
50
+ ResolveInputModalities<TModel>,
51
+ TToolCapabilities extends ReadonlyArray<string> =
52
+ ResolveToolCapabilities<TModel>,
53
+ > extends OpenAIBaseChatCompletionsTextAdapter<
54
+ TModel,
55
+ TProviderOptions,
56
+ TInputModalities,
57
+ LLMGatewayMessageMetadataByModality,
58
+ TToolCapabilities
59
+ > {
60
+ override readonly kind = 'text' as const
61
+ override readonly name = 'llmgateway' as const
62
+
63
+ constructor(config: LLMGatewayTextConfig, model: TModel) {
64
+ super(model, 'llmgateway', new OpenAI(withLLMGatewayDefaults(config)))
65
+ }
66
+
67
+ /**
68
+ * Surfaces reasoning deltas during streaming. LLM Gateway normalizes
69
+ * upstream reasoning output to `delta.reasoning_content` on the OpenAI
70
+ * Chat Completions wire format (the DeepSeek-style field most
71
+ * OpenAI-compatible providers emit); some routed providers emit
72
+ * `delta.reasoning` instead, so both are read.
73
+ */
74
+ protected override extractReasoning(
75
+ chunk: OpenAI.Chat.Completions.ChatCompletionChunk,
76
+ ): { text: string } | undefined {
77
+ const delta = chunk.choices[0]?.delta as
78
+ | { reasoning?: unknown; reasoning_content?: unknown }
79
+ | undefined
80
+ const raw = delta?.reasoning_content ?? delta?.reasoning
81
+ if (typeof raw === 'string' && raw.length > 0) {
82
+ return { text: raw }
83
+ }
84
+ return undefined
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Creates an LLM Gateway text adapter with explicit API key.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const adapter = createLLMGatewayText('gpt-5.6-terra', "llmgtwy_...");
94
+ * ```
95
+ */
96
+ export function createLLMGatewayText<TModel extends LLMGatewayModelId>(
97
+ model: TModel,
98
+ apiKey: string,
99
+ config?: Omit<LLMGatewayTextConfig, 'apiKey'>,
100
+ ): LLMGatewayTextAdapter<TModel> {
101
+ return new LLMGatewayTextAdapter({ apiKey, ...config }, model)
102
+ }
103
+
104
+ /**
105
+ * Creates an LLM Gateway text adapter with API key from
106
+ * `LLM_GATEWAY_API_KEY`.
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const adapter = llmGatewayText('gpt-5.6-terra');
111
+ * ```
112
+ */
113
+ export function llmGatewayText<TModel extends LLMGatewayModelId>(
114
+ model: TModel,
115
+ config?: Omit<LLMGatewayTextConfig, 'apiKey'>,
116
+ ): LLMGatewayTextAdapter<TModel> {
117
+ const apiKey = getLLMGatewayApiKeyFromEnv()
118
+ return createLLMGatewayText(model, apiKey, config)
119
+ }
package/src/index.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @module @tanstack/ai-llmgateway
3
+ *
4
+ * LLM Gateway provider adapter for TanStack AI.
5
+ * Provides tree-shakeable adapters for LLM Gateway's OpenAI-compatible Chat
6
+ * Completions API, which routes one endpoint to hundreds of models across
7
+ * many providers.
8
+ */
9
+
10
+ // Text (Chat) adapter
11
+ export {
12
+ LLMGatewayTextAdapter,
13
+ createLLMGatewayText,
14
+ llmGatewayText,
15
+ type LLMGatewayTextConfig,
16
+ type LLMGatewayTextProviderOptions,
17
+ } from './adapters/text'
18
+
19
+ // Summarize - thin factory functions over @tanstack/ai's ChatStreamSummarizeAdapter
20
+ export {
21
+ createLLMGatewaySummarize,
22
+ llmGatewaySummarize,
23
+ type LLMGatewaySummarizeConfig,
24
+ type LLMGatewaySummarizeModel,
25
+ } from './adapters/summarize'
26
+
27
+ // Types
28
+ export type {
29
+ LLMGatewayChatModelProviderOptionsByName,
30
+ LLMGatewayChatModelToolCapabilitiesByName,
31
+ LLMGatewayModelInputModalitiesByName,
32
+ ResolveProviderOptions,
33
+ ResolveInputModalities,
34
+ LLMGatewayChatModels,
35
+ LLMGatewayModelId,
36
+ } from './model-meta'
37
+ export { LLMGATEWAY_CHAT_MODELS } from './model-meta'
38
+ export type {
39
+ LLMGatewayTextMetadata,
40
+ LLMGatewayImageMetadata,
41
+ LLMGatewayAudioMetadata,
42
+ LLMGatewayVideoMetadata,
43
+ LLMGatewayDocumentMetadata,
44
+ LLMGatewayMessageMetadataByModality,
45
+ } from './message-types'
46
+
47
+ // Utils
48
+ export {
49
+ getLLMGatewayApiKeyFromEnv,
50
+ withLLMGatewayDefaults,
51
+ type LLMGatewayClientConfig,
52
+ } from './utils/client'
@@ -0,0 +1,130 @@
1
+ /**
2
+ * LLM Gateway-specific message types for the Chat Completions API.
3
+ *
4
+ * LLM Gateway's wire format is OpenAI Chat Completions — the gateway
5
+ * translates it to each routed provider's native format server-side. These
6
+ * type definitions describe that wire shape directly; the adapter drives
7
+ * the endpoint with the OpenAI SDK pointed at the gateway's base URL.
8
+ *
9
+ * @see https://docs.llmgateway.io
10
+ */
11
+
12
+ export interface ChatCompletionNamedToolChoice {
13
+ /** Always `function` for a named tool choice. */
14
+ type: 'function'
15
+ function: {
16
+ /** The name of the function to call. */
17
+ name: string
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Controls which (if any) tool is called by the model.
23
+ *
24
+ * - `none` — the model will not call any tool and instead generates a message
25
+ * - `auto` — the model can pick between generating a message or calling tools
26
+ * - `required` — the model must call one or more tools
27
+ * - Named tool choice — forces the model to call a specific tool
28
+ */
29
+ export type ChatCompletionToolChoiceOption =
30
+ | 'none'
31
+ | 'auto'
32
+ | 'required'
33
+ | ChatCompletionNamedToolChoice
34
+
35
+ export interface ResponseFormatText {
36
+ /** The type of response format being defined. Always `text`. */
37
+ type: 'text'
38
+ }
39
+
40
+ export interface ResponseFormatJsonSchemaJsonSchema {
41
+ /**
42
+ * The name of the response format. Must be a-z, A-Z, 0-9, or contain
43
+ * underscores and dashes, with a maximum length of 64.
44
+ */
45
+ name: string
46
+
47
+ /**
48
+ * A description of what the response format is for, used by the model to
49
+ * determine how to respond in the format.
50
+ */
51
+ description?: string
52
+
53
+ /**
54
+ * The schema for the response format, described as a JSON Schema object.
55
+ * @see https://json-schema.org/
56
+ */
57
+ schema?: { [key: string]: unknown }
58
+
59
+ /**
60
+ * Whether to enable strict schema adherence when generating the output. If
61
+ * set to true, the model will always follow the exact schema defined in the
62
+ * `schema` field. Only a subset of JSON Schema is supported when `strict`
63
+ * is `true`.
64
+ */
65
+ strict?: boolean | null
66
+ }
67
+
68
+ export interface ResponseFormatJsonSchema {
69
+ /** Structured Outputs configuration options, including a JSON Schema. */
70
+ json_schema: ResponseFormatJsonSchemaJsonSchema
71
+
72
+ /** The type of response format being defined. Always `json_schema`. */
73
+ type: 'json_schema'
74
+ }
75
+
76
+ export interface ResponseFormatJsonObject {
77
+ /** The type of response format being defined. Always `json_object`. */
78
+ type: 'json_object'
79
+ }
80
+
81
+ /**
82
+ * Metadata for LLM Gateway document content parts.
83
+ */
84
+ export interface LLMGatewayDocumentMetadata {}
85
+
86
+ /**
87
+ * Metadata for LLM Gateway text content parts.
88
+ * Currently no specific metadata options for text.
89
+ */
90
+ export interface LLMGatewayTextMetadata {}
91
+
92
+ /**
93
+ * Metadata for LLM Gateway image content parts.
94
+ * Controls how the model processes and analyzes images.
95
+ */
96
+ export interface LLMGatewayImageMetadata {
97
+ /**
98
+ * Specifies the detail level of the image.
99
+ * - 'auto': Let the model decide based on image size and content
100
+ * - 'low': Use low resolution processing (faster, cheaper, less detail)
101
+ * - 'high': Use high resolution processing (slower, more expensive, more detail)
102
+ *
103
+ * @default 'auto'
104
+ */
105
+ detail?: 'auto' | 'low' | 'high'
106
+ }
107
+
108
+ /**
109
+ * Metadata for LLM Gateway audio content parts.
110
+ * Note: audio input support depends on the routed model.
111
+ */
112
+ export interface LLMGatewayAudioMetadata {}
113
+
114
+ /**
115
+ * Metadata for LLM Gateway video content parts.
116
+ * Note: video input support depends on the routed model.
117
+ */
118
+ export interface LLMGatewayVideoMetadata {}
119
+
120
+ /**
121
+ * Map of modality types to their LLM Gateway-specific metadata types.
122
+ * Used for type inference when constructing multimodal messages.
123
+ */
124
+ export interface LLMGatewayMessageMetadataByModality {
125
+ text: LLMGatewayTextMetadata
126
+ image: LLMGatewayImageMetadata
127
+ audio: LLMGatewayAudioMetadata
128
+ video: LLMGatewayVideoMetadata
129
+ document: LLMGatewayDocumentMetadata
130
+ }