@tanstack/ai 0.53.0 → 0.55.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 +14 -13
- package/dist/esm/activities/chat/index.js +22 -4
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +21 -1
- package/dist/esm/activities/chat/messages.js +50 -1
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +17 -0
- package/dist/esm/activities/chat/stream/processor.js +27 -0
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/generateLiveVideo/adapter.d.ts +69 -0
- package/dist/esm/activities/generateLiveVideo/adapter.js +23 -0
- package/dist/esm/activities/generateLiveVideo/adapter.js.map +1 -0
- package/dist/esm/activities/generateLiveVideo/index.d.ts +99 -0
- package/dist/esm/activities/generateLiveVideo/index.js +162 -0
- package/dist/esm/activities/generateLiveVideo/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/index.js +3 -1
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateWorld/adapter.d.ts +69 -0
- package/dist/esm/activities/generateWorld/adapter.js +23 -0
- package/dist/esm/activities/generateWorld/adapter.js.map +1 -0
- package/dist/esm/activities/generateWorld/index.d.ts +99 -0
- package/dist/esm/activities/generateWorld/index.js +162 -0
- package/dist/esm/activities/generateWorld/index.js.map +1 -0
- package/dist/esm/activities/index.d.ts +8 -2
- package/dist/esm/activities/index.js +11 -7
- package/dist/esm/activities/middleware/types.d.ts +1 -1
- package/dist/esm/client.d.ts +4 -2
- package/dist/esm/client.js +3 -1
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.js +3 -1
- package/dist/esm/middlewares/otel.js +3 -1
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/types.d.ts +112 -0
- package/package.json +3 -3
- package/skills/ai-core/adapter-configuration/SKILL.md +91 -43
- package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +39 -21
- package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +5 -0
- package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +14 -6
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +33 -25
- package/skills/ai-core/adapter-configuration/references/groq-adapter.md +7 -2
- package/skills/ai-core/adapter-configuration/references/ollama-adapter.md +25 -12
- package/skills/ai-core/adapter-configuration/references/openai-adapter.md +19 -9
- package/skills/ai-core/adapter-configuration/references/openrouter-adapter.md +34 -21
- package/skills/ai-core/ag-ui-protocol/SKILL.md +16 -10
- package/skills/ai-core/chat-experience/SKILL.md +228 -108
- package/skills/ai-core/client-persistence/SKILL.md +21 -9
- package/skills/ai-core/custom-backend-integration/SKILL.md +86 -52
- package/skills/ai-core/debug-logging/SKILL.md +100 -18
- package/skills/ai-core/locks/SKILL.md +35 -7
- package/skills/ai-core/media-generation/SKILL.md +136 -61
- package/skills/ai-core/middleware/SKILL.md +174 -69
- package/skills/ai-core/structured-outputs/SKILL.md +98 -49
- package/skills/ai-core/tool-calling/SKILL.md +245 -158
- package/src/activities/chat/index.ts +29 -7
- package/src/activities/chat/messages.ts +60 -0
- package/src/activities/chat/stream/processor.ts +31 -0
- package/src/activities/generateLiveVideo/adapter.ts +99 -0
- package/src/activities/generateLiveVideo/index.ts +339 -0
- package/src/activities/generateVideo/index.ts +3 -4
- package/src/activities/generateWorld/adapter.ts +96 -0
- package/src/activities/generateWorld/index.ts +339 -0
- package/src/activities/index.ts +44 -0
- package/src/activities/middleware/types.ts +2 -0
- package/src/client.ts +8 -0
- package/src/index.ts +8 -0
- package/src/middlewares/otel.ts +2 -0
- package/src/types.ts +128 -0
|
@@ -45,16 +45,20 @@ Create an adapter and use it with `chat()`:
|
|
|
45
45
|
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
|
|
46
46
|
import { openaiText } from '@tanstack/ai-openai'
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
export async function POST(request: Request) {
|
|
49
|
+
const { messages } = await request.json()
|
|
50
|
+
|
|
51
|
+
const stream = chat({
|
|
52
|
+
adapter: openaiText('gpt-5.2'),
|
|
53
|
+
messages,
|
|
54
|
+
modelOptions: {
|
|
55
|
+
temperature: 0.7,
|
|
56
|
+
max_output_tokens: 1000,
|
|
57
|
+
},
|
|
58
|
+
})
|
|
56
59
|
|
|
57
|
-
return toServerSentEventsResponse(stream)
|
|
60
|
+
return toServerSentEventsResponse(stream)
|
|
61
|
+
}
|
|
58
62
|
```
|
|
59
63
|
|
|
60
64
|
The adapter factory function takes the model name as a string literal and an
|
|
@@ -95,7 +99,7 @@ The text adapter is the primary one for chat/completions:
|
|
|
95
99
|
|
|
96
100
|
```typescript
|
|
97
101
|
// Each factory takes model as first arg, optional config as second
|
|
98
|
-
import { openaiText } from '@tanstack/ai-openai'
|
|
102
|
+
import { openaiText, createOpenaiChat } from '@tanstack/ai-openai'
|
|
99
103
|
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
100
104
|
import { geminiText } from '@tanstack/ai-gemini'
|
|
101
105
|
import { grokText } from '@tanstack/ai-grok'
|
|
@@ -109,24 +113,23 @@ import { byteplusText } from '@tanstack/ai-byteplus'
|
|
|
109
113
|
const adapter = openaiText('gpt-5.2')
|
|
110
114
|
const adapter2 = anthropicText('claude-sonnet-4-6')
|
|
111
115
|
const adapter3 = geminiText('gemini-2.5-pro')
|
|
112
|
-
const adapter4 = grokText('grok-4')
|
|
116
|
+
const adapter4 = grokText('grok-4.6')
|
|
113
117
|
const adapter5 = groqText('llama-3.3-70b-versatile')
|
|
114
118
|
const adapter6 = openRouterText('anthropic/claude-sonnet-4')
|
|
115
|
-
const adapter7 = ollamaText('llama3.3')
|
|
119
|
+
const adapter7 = ollamaText('llama3.3:latest')
|
|
116
120
|
const adapter8 = bedrockText('us.anthropic.claude-3-7-sonnet-20250219-v1:0')
|
|
117
121
|
const adapter9 = byteplusText('seed-2-0-lite-260428')
|
|
118
122
|
|
|
119
|
-
// Optional: pass explicit API key
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
})
|
|
123
|
+
// Optional: pass an explicit API key via the create* sibling
|
|
124
|
+
// (the plain factory reads it from the environment)
|
|
125
|
+
const adapterWithKey = createOpenaiChat('gpt-5.2', 'sk-...')
|
|
123
126
|
```
|
|
124
127
|
|
|
125
128
|
`@tanstack/ai-bedrock` (Amazon Bedrock) branches on `config.api`:
|
|
126
129
|
|
|
127
130
|
- `bedrockText(model)` or `bedrockText(model, { api: 'converse' })` (the default) — Bedrock's native Converse API via `@aws-sdk/client-bedrock-runtime` (adapter name `bedrock-converse`). Reaches the broad catalog: Claude, Nova, Llama, Mistral, DeepSeek, and more.
|
|
128
131
|
- `bedrockText(model, { api: 'chat' })` — OpenAI-compatible Chat Completions endpoint (adapter name `bedrock`). Open-weight models only (gpt-oss, DeepSeek V3.x, Gemma, Qwen, etc.). Does NOT reach Claude, Nova, or Llama.
|
|
129
|
-
- `bedrockText(model, { api: 'responses' })` — OpenAI-compatible Responses API, mantle-only (adapter name `bedrock-responses`). Currently gpt-oss
|
|
132
|
+
- `bedrockText(model, { api: 'responses' })` — OpenAI-compatible Responses API, mantle-only (adapter name `bedrock-responses`). Currently gpt-oss and Gemma 4.
|
|
130
133
|
|
|
131
134
|
Use `createBedrockText(model, apiKey, config?)` to pass the key explicitly. Auth resolves from `BEDROCK_API_KEY` / `AWS_BEARER_TOKEN_BEDROCK`, or SigV4 via the standard AWS credential chain (no extra packages needed — handled by `@aws-sdk/client-bedrock-runtime`).
|
|
132
135
|
|
|
@@ -137,26 +140,32 @@ input or configuration:
|
|
|
137
140
|
|
|
138
141
|
```typescript
|
|
139
142
|
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
|
|
140
|
-
import type {
|
|
143
|
+
import type { ModelMessage } from '@tanstack/ai'
|
|
141
144
|
import { openaiText } from '@tanstack/ai-openai'
|
|
142
145
|
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
143
146
|
import { geminiText } from '@tanstack/ai-gemini'
|
|
144
147
|
|
|
145
148
|
// Define a map of provider+model to adapter factory calls
|
|
146
|
-
const adapters
|
|
149
|
+
const adapters = {
|
|
147
150
|
'openai/gpt-5.2': () => openaiText('gpt-5.2'),
|
|
148
151
|
'anthropic/claude-sonnet-4-6': () => anthropicText('claude-sonnet-4-6'),
|
|
149
152
|
'gemini/gemini-2.5-pro': () => geminiText('gemini-2.5-pro'),
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
function isKnownProviderModel(key: string): key is keyof typeof adapters {
|
|
156
|
+
return key in adapters
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function handleChat(
|
|
160
|
+
providerModel: string,
|
|
161
|
+
messages: Array<ModelMessage>,
|
|
162
|
+
) {
|
|
163
|
+
if (!isKnownProviderModel(providerModel)) {
|
|
155
164
|
throw new Error(`Unknown provider/model: ${providerModel}`)
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
const stream = chat({
|
|
159
|
-
adapter:
|
|
168
|
+
adapter: adapters[providerModel](),
|
|
160
169
|
messages,
|
|
161
170
|
})
|
|
162
171
|
|
|
@@ -174,6 +183,10 @@ import { openaiText } from '@tanstack/ai-openai'
|
|
|
174
183
|
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
175
184
|
import { geminiText } from '@tanstack/ai-gemini'
|
|
176
185
|
|
|
186
|
+
const messages = [
|
|
187
|
+
{ role: 'user' as const, content: 'Plan a database migration.' },
|
|
188
|
+
]
|
|
189
|
+
|
|
177
190
|
// OpenAI: reasoning with effort and summary
|
|
178
191
|
const openaiStream = chat({
|
|
179
192
|
adapter: openaiText('gpt-5.2'),
|
|
@@ -199,16 +212,18 @@ const anthropicStream = chat({
|
|
|
199
212
|
},
|
|
200
213
|
})
|
|
201
214
|
|
|
202
|
-
// Anthropic: adaptive thinking (
|
|
215
|
+
// Anthropic: adaptive thinking (Sonnet 5, Fable 5, Opus 4.7+) — depth is
|
|
216
|
+
// tuned with output_config.effort instead of a token budget
|
|
203
217
|
const adaptiveStream = chat({
|
|
204
|
-
adapter: anthropicText('claude-sonnet-
|
|
218
|
+
adapter: anthropicText('claude-sonnet-5'),
|
|
205
219
|
messages,
|
|
206
220
|
modelOptions: {
|
|
207
221
|
max_tokens: 16000,
|
|
208
222
|
thinking: {
|
|
209
223
|
type: 'adaptive',
|
|
224
|
+
display: 'summarized', // stream the reasoning text (default 'omitted')
|
|
210
225
|
},
|
|
211
|
-
effort: 'high', // '
|
|
226
|
+
output_config: { effort: 'high' }, // 'low' | 'medium' | 'high' | 'xhigh' | 'max'
|
|
212
227
|
},
|
|
213
228
|
})
|
|
214
229
|
|
|
@@ -263,6 +278,14 @@ inside `modelOptions` using each provider's **native** key. They are not
|
|
|
263
278
|
top-level fields on `chat()`/`ai()`/`generate()`.
|
|
264
279
|
|
|
265
280
|
```typescript
|
|
281
|
+
import { chat } from '@tanstack/ai'
|
|
282
|
+
import { openaiText } from '@tanstack/ai-openai'
|
|
283
|
+
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
284
|
+
import { geminiText } from '@tanstack/ai-gemini'
|
|
285
|
+
import { ollamaText } from '@tanstack/ai-ollama'
|
|
286
|
+
|
|
287
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
288
|
+
|
|
266
289
|
// OpenAI — native keys
|
|
267
290
|
chat({
|
|
268
291
|
adapter: openaiText('gpt-5.2'),
|
|
@@ -285,8 +308,9 @@ chat({
|
|
|
285
308
|
})
|
|
286
309
|
|
|
287
310
|
// Ollama — NESTED under modelOptions.options
|
|
311
|
+
// (use the `family:tag` id — a bare `llama3.3` falls back to untyped options)
|
|
288
312
|
chat({
|
|
289
|
-
adapter: ollamaText('llama3.3'),
|
|
313
|
+
adapter: ollamaText('llama3.3:latest'),
|
|
290
314
|
messages,
|
|
291
315
|
modelOptions: {
|
|
292
316
|
options: { temperature: 0.7, top_p: 0.9, num_predict: 1000 },
|
|
@@ -301,7 +325,7 @@ Per-provider sampling keys (all live inside `modelOptions`):
|
|
|
301
325
|
| OpenAI | `temperature` | `top_p` | `max_output_tokens` |
|
|
302
326
|
| Anthropic | `temperature` | `top_p` | `max_tokens` |
|
|
303
327
|
| Gemini | `temperature` | `topP` | `maxOutputTokens` |
|
|
304
|
-
| Grok (xAI) | `temperature` | `top_p` | `
|
|
328
|
+
| Grok (xAI) | `temperature` | `top_p` | `max_output_tokens` |
|
|
305
329
|
| Groq | `temperature` | `top_p` | `max_completion_tokens` |
|
|
306
330
|
| OpenRouter (chat) | `temperature` | `topP` | `maxCompletionTokens` |
|
|
307
331
|
| Ollama | `temperature` | `top_p` | `num_predict` (nested in `options`) |
|
|
@@ -326,7 +350,16 @@ some sampling options use provider-native names. Ollama nests all sampling under
|
|
|
326
350
|
Adapters can declare an optional capability method:
|
|
327
351
|
|
|
328
352
|
```ts
|
|
329
|
-
|
|
353
|
+
import { AnthropicTextAdapter } from '@tanstack/ai-anthropic'
|
|
354
|
+
|
|
355
|
+
// The TextAdapter contract:
|
|
356
|
+
// supportsCombinedToolsAndSchema?: (modelOptions?: TProviderOptions) => boolean
|
|
357
|
+
// Subclasses override it to narrow the capability:
|
|
358
|
+
class LegacyPathAnthropic extends AnthropicTextAdapter<'claude-sonnet-4-6'> {
|
|
359
|
+
override supportsCombinedToolsAndSchema(): boolean {
|
|
360
|
+
return false
|
|
361
|
+
}
|
|
362
|
+
}
|
|
330
363
|
```
|
|
331
364
|
|
|
332
365
|
When `true`, the engine wires `outputSchema` into the regular
|
|
@@ -338,16 +371,16 @@ runs.
|
|
|
338
371
|
|
|
339
372
|
Current per-adapter status (#605):
|
|
340
373
|
|
|
341
|
-
| Adapter | Returns
|
|
342
|
-
| -------------------------------------------- |
|
|
343
|
-
| `openaiText` / `openaiChatCompletions` | `true` (all supported models)
|
|
344
|
-
| `anthropicText` | `true` for Claude 4.5+ (gated by `ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS`), `false` otherwise
|
|
345
|
-
| `geminiText` | `true` for Gemini 3.x (gated by `GEMINI_COMBINED_TOOLS_AND_SCHEMA_MODELS`), `false` otherwise
|
|
346
|
-
| `grokText` | `true`
|
|
347
|
-
| `groqText` | `false` (Groq API rejects schema + tools + stream)
|
|
348
|
-
| `openRouterText` / `openRouterResponsesText` | `
|
|
349
|
-
| `ollamaText` | `false` (constrained-decoding vs tool-call grammar conflict)
|
|
350
|
-
| `byteplusText` | Per model — `true` only for the 10 ids in `BYTEPLUS_STRUCTURED_OUTPUT_CHAT_MODELS`, `false` otherwise
|
|
374
|
+
| Adapter | Returns |
|
|
375
|
+
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
376
|
+
| `openaiText` / `openaiChatCompletions` | `true` (all supported models) |
|
|
377
|
+
| `anthropicText` | `true` for Claude 4.5+ (gated by `ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS`), `false` otherwise |
|
|
378
|
+
| `geminiText` | `true` for Gemini 3.x (gated by `GEMINI_COMBINED_TOOLS_AND_SCHEMA_MODELS`), `false` otherwise |
|
|
379
|
+
| `grokText` | `true` (all chat models — inherits the OpenAI Responses base; no per-model gate) |
|
|
380
|
+
| `groqText` | `false` (Groq API rejects schema + tools + stream) |
|
|
381
|
+
| `openRouterText` / `openRouterResponsesText` | Per model — `true` only when the model and every `modelOptions.models` fallback are in `OPENROUTER_COMBINED_TOOLS_AND_SCHEMA_MODELS` |
|
|
382
|
+
| `ollamaText` | `false` (constrained-decoding vs tool-call grammar conflict) |
|
|
383
|
+
| `byteplusText` | Per model — `true` only for the 10 ids in `BYTEPLUS_STRUCTURED_OUTPUT_CHAT_MODELS`, `false` otherwise |
|
|
351
384
|
|
|
352
385
|
Subclasses can override to narrow the capability. When extending an
|
|
353
386
|
adapter for a custom model that doesn't support the combination, return
|
|
@@ -371,7 +404,9 @@ dedicated package required.
|
|
|
371
404
|
|
|
372
405
|
```typescript
|
|
373
406
|
import { openaiCompatible } from '@tanstack/ai-openai/compatible'
|
|
374
|
-
import { createModel } from '@tanstack/ai'
|
|
407
|
+
import { chat, createModel } from '@tanstack/ai'
|
|
408
|
+
|
|
409
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
375
410
|
|
|
376
411
|
// Provider-factory: configure baseURL + apiKey + models ONCE,
|
|
377
412
|
// then select a model per call (the model arg is a type-safe union).
|
|
@@ -400,6 +435,9 @@ For a single model, use the one-shot helper:
|
|
|
400
435
|
|
|
401
436
|
```typescript
|
|
402
437
|
import { openaiCompatibleText } from '@tanstack/ai-openai/compatible'
|
|
438
|
+
import { chat } from '@tanstack/ai'
|
|
439
|
+
|
|
440
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
403
441
|
|
|
404
442
|
chat({
|
|
405
443
|
adapter: openaiCompatibleText('deepseek-chat', {
|
|
@@ -428,13 +466,17 @@ ElevenLabs `baseUrl`/`headers`). The vendor names still work; when both are
|
|
|
428
466
|
set, `baseURL` and `defaultHeaders` win.
|
|
429
467
|
|
|
430
468
|
```typescript
|
|
469
|
+
import { createGeminiChat } from '@tanstack/ai-gemini'
|
|
470
|
+
|
|
431
471
|
const gateway = {
|
|
432
472
|
baseURL: 'https://gateway.example.com/google-ai-studio',
|
|
433
473
|
defaultHeaders: {
|
|
434
474
|
'cf-aig-authorization': `Bearer ${process.env.GATEWAY_TOKEN}`,
|
|
435
475
|
},
|
|
436
476
|
}
|
|
437
|
-
createGeminiChat('gemini-3.8-flash',
|
|
477
|
+
createGeminiChat('gemini-3.8-flash', process.env.GOOGLE_API_KEY!, {
|
|
478
|
+
...gateway,
|
|
479
|
+
})
|
|
438
480
|
```
|
|
439
481
|
|
|
440
482
|
## Common Mistakes
|
|
@@ -444,13 +486,19 @@ createGeminiChat('gemini-3.8-flash', apiKey, { ...gateway })
|
|
|
444
486
|
The legacy `openai()` (and `anthropic()`, etc.) monolithic adapters are
|
|
445
487
|
deprecated. They take the model in `chat()`, not in the factory.
|
|
446
488
|
|
|
447
|
-
```typescript
|
|
448
|
-
// WRONG: Legacy monolithic adapter pattern
|
|
489
|
+
```typescript ignore
|
|
490
|
+
// WRONG: Legacy monolithic adapter pattern (no longer exported)
|
|
449
491
|
import { openai } from '@tanstack/ai-openai'
|
|
450
492
|
chat({ adapter: openai(), model: 'gpt-5.2', messages })
|
|
493
|
+
```
|
|
451
494
|
|
|
495
|
+
```typescript
|
|
452
496
|
// CORRECT: Tree-shakeable adapter, model in factory
|
|
497
|
+
import { chat } from '@tanstack/ai'
|
|
453
498
|
import { openaiText } from '@tanstack/ai-openai'
|
|
499
|
+
|
|
500
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
501
|
+
|
|
454
502
|
chat({ adapter: openaiText('gpt-5.2'), messages })
|
|
455
503
|
```
|
|
456
504
|
|
|
@@ -21,45 +21,58 @@ import { anthropicText } from '@tanstack/ai-anthropic'
|
|
|
21
21
|
|
|
22
22
|
## Key Chat Models
|
|
23
23
|
|
|
24
|
-
| Model
|
|
25
|
-
|
|
|
26
|
-
| `claude-fable-5`
|
|
27
|
-
| `claude-
|
|
28
|
-
| `claude-opus-
|
|
29
|
-
| `claude-opus-
|
|
30
|
-
| `claude-
|
|
31
|
-
| `claude-
|
|
32
|
-
| `claude-
|
|
33
|
-
| `claude-opus-4-
|
|
34
|
-
| `claude-
|
|
35
|
-
| `claude-
|
|
24
|
+
| Model | Context Window | Max Output | Notes |
|
|
25
|
+
| -------------------- | -------------- | ---------- | ------------------------------------------- |
|
|
26
|
+
| `claude-fable-5-1` | 1M | 128K | Newest; thinking always on (adaptive) |
|
|
27
|
+
| `claude-fable-5` | 1M | 128K | Most capable; thinking always on (adaptive) |
|
|
28
|
+
| `claude-opus-5` | 1M | 128K | Opus tier; budget thinking + sampling |
|
|
29
|
+
| `claude-opus-5-fast` | 1M | 128K | Fast-mode Opus 5; same options as opus-5 |
|
|
30
|
+
| `claude-sonnet-5` | 1M | 128K | Best balance; adaptive thinking by default |
|
|
31
|
+
| `claude-opus-4-8` | 1M | 128K | Opus tier; adaptive thinking, no sampling |
|
|
32
|
+
| `claude-opus-4-7` | 1M | 128K | Older Opus; adaptive thinking, no sampling |
|
|
33
|
+
| `claude-opus-4-6` | 200K | 128K | Older Opus, adaptive + budget thinking |
|
|
34
|
+
| `claude-sonnet-4-6` | 1M | 64K | Previous gen balanced, adaptive + budget |
|
|
35
|
+
| `claude-sonnet-4-5` | 200K | 64K | Previous gen balanced |
|
|
36
|
+
| `claude-opus-4-5` | 200K | 32K | Previous gen most capable |
|
|
37
|
+
| `claude-opus-4-1` | 200K | 64K | Deprecated (retires 2026-08-05) |
|
|
38
|
+
| `claude-haiku-4-5` | 200K | 64K | Fast and affordable |
|
|
36
39
|
|
|
37
40
|
Note: Model IDs use the format `claude-sonnet-5`, `claude-opus-4-8`, etc.
|
|
38
|
-
Retired models (Claude 3.x, Sonnet 3.7, Opus 4 / Sonnet 4)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
Retired models (Claude 3.x, Sonnet 3.7, Opus 4 / Sonnet 4) were removed —
|
|
42
|
+
every registered id resolves against the first-party Anthropic API.
|
|
43
|
+
`claude-opus-5-fast` is the only `-fast` id that remains.
|
|
44
|
+
|
|
45
|
+
`output_config.effort` is typed only on the adaptive-era models
|
|
46
|
+
(`claude-opus-4-7`, `claude-opus-4-8`, `claude-sonnet-5`, `claude-fable-5`,
|
|
47
|
+
`claude-fable-5-1`). There is no top-level `effort` option on any model;
|
|
48
|
+
`claude-opus-4-6` / `claude-sonnet-4-6` accept `thinking: { type: 'adaptive' }`
|
|
49
|
+
but no effort knob.
|
|
41
50
|
|
|
42
51
|
## Provider-Specific modelOptions
|
|
43
52
|
|
|
44
53
|
```typescript
|
|
54
|
+
import { chat } from '@tanstack/ai'
|
|
55
|
+
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
56
|
+
|
|
57
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
58
|
+
|
|
45
59
|
chat({
|
|
46
60
|
adapter: anthropicText('claude-sonnet-4-6'),
|
|
47
61
|
messages,
|
|
48
62
|
modelOptions: {
|
|
49
63
|
// Sampling
|
|
50
64
|
temperature: 0.7,
|
|
51
|
-
top_p: 0.9, // cannot be combined with temperature
|
|
65
|
+
// top_p: 0.9, // cannot be combined with temperature
|
|
52
66
|
max_tokens: 16000,
|
|
53
67
|
// Extended thinking (budget-based)
|
|
54
68
|
thinking: {
|
|
55
69
|
type: 'enabled',
|
|
56
70
|
budget_tokens: 8000, // must be >= 1024 and < max_tokens
|
|
57
71
|
},
|
|
58
|
-
// Adaptive thinking (claude-sonnet-4-6, claude-opus-4-6+)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
effort: 'high', // 'max' | 'high' | 'medium' | 'low'
|
|
72
|
+
// Adaptive thinking (claude-sonnet-4-6, claude-opus-4-6+) — the
|
|
73
|
+
// alternative to the budget shape above; effort is tuned via
|
|
74
|
+
// output_config.effort on the adaptive-era models (see below)
|
|
75
|
+
// thinking: { type: 'adaptive' },
|
|
63
76
|
// Service tier
|
|
64
77
|
service_tier: 'auto', // 'auto' | 'standard_only'
|
|
65
78
|
// Stop sequences
|
|
@@ -99,6 +112,11 @@ ANTHROPIC_API_KEY
|
|
|
99
112
|
The per-model types restrict `modelOptions` on the newest models:
|
|
100
113
|
|
|
101
114
|
```typescript
|
|
115
|
+
import { chat } from '@tanstack/ai'
|
|
116
|
+
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
117
|
+
|
|
118
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
119
|
+
|
|
102
120
|
chat({
|
|
103
121
|
adapter: anthropicText('claude-sonnet-5'), // or 'claude-fable-5', 'claude-opus-4-8'
|
|
104
122
|
messages,
|
|
@@ -62,6 +62,11 @@ Media models: `BYTEPLUS_VIDEO_MODELS` (Seedance —
|
|
|
62
62
|
## Provider-Specific modelOptions
|
|
63
63
|
|
|
64
64
|
```typescript
|
|
65
|
+
import { chat } from '@tanstack/ai'
|
|
66
|
+
import { byteplusText } from '@tanstack/ai-byteplus'
|
|
67
|
+
|
|
68
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
69
|
+
|
|
65
70
|
chat({
|
|
66
71
|
adapter: byteplusText('dola-seed-2-1-turbo-260628'),
|
|
67
72
|
messages,
|
|
@@ -38,6 +38,15 @@ Most Gemini text models accept `text`, `image`, `audio`, `video`, and `document`
|
|
|
38
38
|
## Provider-Specific modelOptions
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
|
+
import { chat } from '@tanstack/ai'
|
|
42
|
+
import {
|
|
43
|
+
geminiText,
|
|
44
|
+
HarmBlockThreshold,
|
|
45
|
+
HarmCategory,
|
|
46
|
+
} from '@tanstack/ai-gemini'
|
|
47
|
+
|
|
48
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
49
|
+
|
|
41
50
|
chat({
|
|
42
51
|
adapter: geminiText('gemini-2.5-pro'),
|
|
43
52
|
messages,
|
|
@@ -47,15 +56,14 @@ chat({
|
|
|
47
56
|
includeThoughts: true,
|
|
48
57
|
thinkingBudget: 4096,
|
|
49
58
|
},
|
|
50
|
-
// Thinking (level-based, advanced models)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
},
|
|
59
|
+
// Thinking (level-based, advanced models) — the alternative to the
|
|
60
|
+
// budget shape above:
|
|
61
|
+
// thinkingConfig: { thinkingLevel: 'THINKING_LEVEL_HIGH' },
|
|
54
62
|
// Safety settings
|
|
55
63
|
safetySettings: [
|
|
56
64
|
{
|
|
57
|
-
category:
|
|
58
|
-
threshold:
|
|
65
|
+
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
|
|
66
|
+
threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
|
|
59
67
|
},
|
|
60
68
|
],
|
|
61
69
|
// Tool config
|
|
@@ -23,34 +23,41 @@ import { grokImage } from '@tanstack/ai-grok'
|
|
|
23
23
|
|
|
24
24
|
## Key Chat Models
|
|
25
25
|
|
|
26
|
-
| Model
|
|
27
|
-
|
|
|
28
|
-
| `grok-4
|
|
29
|
-
| `grok-4
|
|
30
|
-
| `grok-
|
|
31
|
-
| `grok-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Image model: `grok-2-image-1212`
|
|
26
|
+
| Model | Context Window | Notes |
|
|
27
|
+
| ---------------- | -------------- | -------------------------------------------------------- |
|
|
28
|
+
| `grok-4.6` | 500K | Latest; reasoning, tools, structured output; document in |
|
|
29
|
+
| `grok-4.5` | 500K | Reasoning, tools, structured output; document in |
|
|
30
|
+
| `grok-4.3` | 1M | Reasoning, tools, structured output; text + image in |
|
|
31
|
+
| `grok-build-0.1` | 256K | Code-specialized; `reasoning` option is not accepted |
|
|
32
|
+
|
|
33
|
+
`GROK_CHAT_MODELS` is exactly these four ids. Image models
|
|
34
|
+
(`GROK_IMAGE_MODELS`): `grok-2-image-1212`, `grok-imagine-image`,
|
|
35
|
+
`grok-imagine-image-2.0`, `grok-imagine-image-quality`.
|
|
38
36
|
|
|
39
37
|
## Provider-Specific modelOptions
|
|
40
38
|
|
|
41
|
-
Grok
|
|
39
|
+
Grok speaks the OpenAI **Responses** API (the adapter uses the OpenAI SDK
|
|
40
|
+
against `https://api.x.ai/v1`), so option names follow that API:
|
|
42
41
|
|
|
43
42
|
```typescript
|
|
43
|
+
import { chat } from '@tanstack/ai'
|
|
44
|
+
import { grokText } from '@tanstack/ai-grok'
|
|
45
|
+
|
|
46
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
47
|
+
|
|
44
48
|
chat({
|
|
45
|
-
adapter: grokText('grok-4'),
|
|
49
|
+
adapter: grokText('grok-4.6'),
|
|
46
50
|
messages,
|
|
47
51
|
modelOptions: {
|
|
52
|
+
// Sampling (Responses API names)
|
|
48
53
|
temperature: 0.7,
|
|
49
|
-
max_tokens: 4096,
|
|
50
54
|
top_p: 0.9,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
max_output_tokens: 4096,
|
|
56
|
+
// Reasoning (reasoning-capable models)
|
|
57
|
+
reasoning: { effort: 'high' }, // 'none' | 'low' | 'medium' | 'high'
|
|
58
|
+
// Response storage (adapter default: false)
|
|
59
|
+
store: false,
|
|
60
|
+
// End-user id for abuse monitoring
|
|
54
61
|
user: 'user-123',
|
|
55
62
|
},
|
|
56
63
|
})
|
|
@@ -68,10 +75,11 @@ The adapter uses the OpenAI SDK with xAI's base URL (`https://api.x.ai/v1`).
|
|
|
68
75
|
## Gotchas
|
|
69
76
|
|
|
70
77
|
- Uses the OpenAI SDK under the hood with a custom `baseURL`.
|
|
71
|
-
- `grok-
|
|
72
|
-
|
|
73
|
-
- `grok-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
- All four chat models support reasoning; `grok-build-0.1` is the exception
|
|
79
|
+
in that it rejects the `reasoning` option (`GrokBuildProviderOptions`).
|
|
80
|
+
- `grok-4.5` / `grok-4.6` accept `text`, `image`, and `document` input;
|
|
81
|
+
`grok-4.3` / `grok-build-0.1` accept `text` and `image`.
|
|
82
|
+
- Provider options are a subset of OpenAI's Responses options:
|
|
83
|
+
`temperature`, `top_p`, `max_output_tokens`, `reasoning`, `store`,
|
|
84
|
+
`include`, `user`. There is no `max_tokens`, `frequency_penalty`,
|
|
85
|
+
`presence_penalty`, `stop`, or `metadata`.
|
|
@@ -38,6 +38,11 @@ Guard models: `meta-llama/llama-guard-4-12b`, `meta-llama/llama-prompt-guard-2-8
|
|
|
38
38
|
## Provider-Specific modelOptions
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
|
+
import { chat } from '@tanstack/ai'
|
|
42
|
+
import { groqText } from '@tanstack/ai-groq'
|
|
43
|
+
|
|
44
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
45
|
+
|
|
41
46
|
chat({
|
|
42
47
|
adapter: groqText('llama-3.3-70b-versatile'),
|
|
43
48
|
messages,
|
|
@@ -49,7 +54,7 @@ chat({
|
|
|
49
54
|
// Response format
|
|
50
55
|
response_format: {
|
|
51
56
|
type: 'json_schema',
|
|
52
|
-
json_schema: {/*
|
|
57
|
+
json_schema: { name: 'answer', schema: {/* JSON Schema */} },
|
|
53
58
|
},
|
|
54
59
|
// Sampling
|
|
55
60
|
temperature: 0.7,
|
|
@@ -67,7 +72,7 @@ chat({
|
|
|
67
72
|
// Citations
|
|
68
73
|
citation_options: 'enabled',
|
|
69
74
|
// Documents for context
|
|
70
|
-
documents: [{ text: '...' }],
|
|
75
|
+
documents: [{ source: { type: 'text', text: '...' } }],
|
|
71
76
|
// Search settings (for web search tool)
|
|
72
77
|
search_settings: {/* SearchSettings */},
|
|
73
78
|
// Service tier
|
|
@@ -24,15 +24,20 @@ import { ollamaText } from '@tanstack/ai-ollama'
|
|
|
24
24
|
Ollama runs models locally. The adapter supports a large catalog of models.
|
|
25
25
|
Key families include:
|
|
26
26
|
|
|
27
|
-
| Model Family | Example Names
|
|
28
|
-
| ------------ |
|
|
29
|
-
| Llama 4 | `llama4`, `llama4:
|
|
30
|
-
| Llama 3.3 | `llama3.3`, `llama3.3:70b`
|
|
31
|
-
| Qwen 3 | `qwen3`, `qwen3:32b`
|
|
32
|
-
| DeepSeek R1 | `deepseek-r1`, `deepseek-r1:70b`
|
|
33
|
-
| Gemma 3 | `gemma3`, `gemma3:27b`
|
|
34
|
-
| Phi 4 | `phi4`, `phi4:14b`
|
|
35
|
-
| Mistral | `mistral`, `mistral-large`
|
|
27
|
+
| Model Family | Example Names | Notes |
|
|
28
|
+
| ------------ | ---------------------------------------- | ----------------------- |
|
|
29
|
+
| Llama 4 | `llama4:latest`, `llama4:16x17b` | Latest Meta models |
|
|
30
|
+
| Llama 3.3 | `llama3.3:latest`, `llama3.3:70b` | Strong general purpose |
|
|
31
|
+
| Qwen 3 | `qwen3:latest`, `qwen3:32b` | Reasoning capable |
|
|
32
|
+
| DeepSeek R1 | `deepseek-r1:latest`, `deepseek-r1:70b` | Reasoning focused |
|
|
33
|
+
| Gemma 3 | `gemma3:latest`, `gemma3:27b` | Google's open model |
|
|
34
|
+
| Phi 4 | `phi4:latest`, `phi4:14b` | Microsoft's small model |
|
|
35
|
+
| Mistral | `mistral:latest`, `mistral-large:latest` | Mistral AI models |
|
|
36
|
+
|
|
37
|
+
Typed ids are always `family:tag` (`OLLAMA_TEXT_MODELS`). `ollamaText()`
|
|
38
|
+
accepts any string, but a bare `llama3.3` falls outside the typed catalog and
|
|
39
|
+
`modelOptions` degrades to the raw Ollama `ChatRequest` (which then demands a
|
|
40
|
+
`model` field). Use `llama3.3:latest`.
|
|
36
41
|
|
|
37
42
|
Models must be pulled first: `ollama pull llama3.3`
|
|
38
43
|
|
|
@@ -48,8 +53,10 @@ Ollama's own request shape) — `temperature`, `top_p`, and `num_predict`
|
|
|
48
53
|
import { chat } from '@tanstack/ai'
|
|
49
54
|
import { ollamaText } from '@tanstack/ai-ollama'
|
|
50
55
|
|
|
56
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
57
|
+
|
|
51
58
|
const stream = chat({
|
|
52
|
-
adapter: ollamaText('llama3.3'),
|
|
59
|
+
adapter: ollamaText('llama3.3:latest'),
|
|
53
60
|
messages,
|
|
54
61
|
modelOptions: {
|
|
55
62
|
options: {
|
|
@@ -64,9 +71,15 @@ const stream = chat({
|
|
|
64
71
|
|
|
65
72
|
## Configuration
|
|
66
73
|
|
|
74
|
+
`ollamaText(model)` takes no config — it reads `OLLAMA_HOST`. To point at
|
|
75
|
+
another server (or pass headers / `baseURL` for a gateway), use
|
|
76
|
+
`createOllamaChat(model, hostOrConfig)`:
|
|
77
|
+
|
|
67
78
|
```typescript
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
import { createOllamaChat } from '@tanstack/ai-ollama'
|
|
80
|
+
|
|
81
|
+
// With explicit host (ollamaText() reads OLLAMA_HOST instead)
|
|
82
|
+
const adapter = createOllamaChat('llama3.3:latest', {
|
|
70
83
|
host: 'http://my-server:11434',
|
|
71
84
|
})
|
|
72
85
|
```
|
|
@@ -28,20 +28,30 @@ import { openaiSpeech } from '@tanstack/ai-openai'
|
|
|
28
28
|
|
|
29
29
|
## Key Chat Models
|
|
30
30
|
|
|
31
|
-
| Model
|
|
32
|
-
|
|
|
33
|
-
| `gpt-
|
|
34
|
-
| `gpt-5.
|
|
35
|
-
| `gpt-5.
|
|
36
|
-
| `gpt-5.
|
|
37
|
-
| `gpt-5`
|
|
38
|
-
| `gpt-5
|
|
31
|
+
| Model | Context Window | Max Output | Notes |
|
|
32
|
+
| -------------- | -------------- | ---------- | ---------------------------------------------- |
|
|
33
|
+
| `gpt-6-astra` | 1M | 128K | Newest; reasoning, tools, image input |
|
|
34
|
+
| `gpt-5.6` | 1M | 128K | Reasoning, tools, image input |
|
|
35
|
+
| `gpt-5.5` | 1M | 128K | Flagship used in examples; text/image/document |
|
|
36
|
+
| `gpt-5.5-pro` | 1M | 128K | Higher reasoning tier |
|
|
37
|
+
| `gpt-5.4-mini` | 400K | 128K | Cost-efficient (no bare `gpt-5.4` chat id) |
|
|
38
|
+
| `gpt-5.2` | 400K | 128K | Previous flagship; text/image/document |
|
|
39
|
+
| `gpt-5-mini` | 400K | 128K | Budget |
|
|
40
|
+
|
|
41
|
+
`OPENAI_CHAT_MODELS` is the full list (also `gpt-6-astra-pro`, the
|
|
42
|
+
`gpt-5.6-luna/sol/terra` family, `gpt-5.4-nano`, `gpt-5.2-pro`,
|
|
43
|
+
`gpt-5.1`, `gpt-5`, the `o3`/`o4-mini` reasoning models, and `gpt-4.1`/`gpt-4o`).
|
|
39
44
|
|
|
40
45
|
## Provider-Specific modelOptions
|
|
41
46
|
|
|
42
47
|
```typescript
|
|
48
|
+
import { chat } from '@tanstack/ai'
|
|
49
|
+
import { openaiText } from '@tanstack/ai-openai'
|
|
50
|
+
|
|
51
|
+
const messages = [{ role: 'user' as const, content: 'Hello' }]
|
|
52
|
+
|
|
43
53
|
chat({
|
|
44
|
-
adapter: openaiText('gpt-5.
|
|
54
|
+
adapter: openaiText('gpt-5.5'),
|
|
45
55
|
messages,
|
|
46
56
|
modelOptions: {
|
|
47
57
|
// Sampling
|