@tanstack/ai 0.53.0 → 0.54.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.
Files changed (60) hide show
  1. package/README.md +14 -13
  2. package/dist/esm/activities/chat/index.js +5 -3
  3. package/dist/esm/activities/chat/index.js.map +1 -1
  4. package/dist/esm/activities/generateLiveVideo/adapter.d.ts +69 -0
  5. package/dist/esm/activities/generateLiveVideo/adapter.js +23 -0
  6. package/dist/esm/activities/generateLiveVideo/adapter.js.map +1 -0
  7. package/dist/esm/activities/generateLiveVideo/index.d.ts +99 -0
  8. package/dist/esm/activities/generateLiveVideo/index.js +162 -0
  9. package/dist/esm/activities/generateLiveVideo/index.js.map +1 -0
  10. package/dist/esm/activities/generateVideo/index.js +3 -1
  11. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  12. package/dist/esm/activities/generateWorld/adapter.d.ts +69 -0
  13. package/dist/esm/activities/generateWorld/adapter.js +23 -0
  14. package/dist/esm/activities/generateWorld/adapter.js.map +1 -0
  15. package/dist/esm/activities/generateWorld/index.d.ts +99 -0
  16. package/dist/esm/activities/generateWorld/index.js +162 -0
  17. package/dist/esm/activities/generateWorld/index.js.map +1 -0
  18. package/dist/esm/activities/index.d.ts +8 -2
  19. package/dist/esm/activities/index.js +11 -7
  20. package/dist/esm/activities/middleware/types.d.ts +1 -1
  21. package/dist/esm/client.d.ts +4 -2
  22. package/dist/esm/client.js +3 -1
  23. package/dist/esm/client.js.map +1 -1
  24. package/dist/esm/index.d.ts +4 -2
  25. package/dist/esm/index.js +3 -1
  26. package/dist/esm/middlewares/otel.js +3 -1
  27. package/dist/esm/middlewares/otel.js.map +1 -1
  28. package/dist/esm/types.d.ts +112 -0
  29. package/package.json +2 -2
  30. package/skills/ai-core/adapter-configuration/SKILL.md +90 -42
  31. package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +39 -21
  32. package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +5 -0
  33. package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +14 -6
  34. package/skills/ai-core/adapter-configuration/references/grok-adapter.md +33 -25
  35. package/skills/ai-core/adapter-configuration/references/groq-adapter.md +7 -2
  36. package/skills/ai-core/adapter-configuration/references/ollama-adapter.md +25 -12
  37. package/skills/ai-core/adapter-configuration/references/openai-adapter.md +19 -9
  38. package/skills/ai-core/adapter-configuration/references/openrouter-adapter.md +34 -21
  39. package/skills/ai-core/ag-ui-protocol/SKILL.md +16 -10
  40. package/skills/ai-core/chat-experience/SKILL.md +228 -108
  41. package/skills/ai-core/client-persistence/SKILL.md +21 -9
  42. package/skills/ai-core/custom-backend-integration/SKILL.md +86 -52
  43. package/skills/ai-core/debug-logging/SKILL.md +100 -18
  44. package/skills/ai-core/locks/SKILL.md +35 -7
  45. package/skills/ai-core/media-generation/SKILL.md +114 -49
  46. package/skills/ai-core/middleware/SKILL.md +174 -69
  47. package/skills/ai-core/structured-outputs/SKILL.md +98 -49
  48. package/skills/ai-core/tool-calling/SKILL.md +245 -158
  49. package/src/activities/chat/index.ts +6 -7
  50. package/src/activities/generateLiveVideo/adapter.ts +99 -0
  51. package/src/activities/generateLiveVideo/index.ts +339 -0
  52. package/src/activities/generateVideo/index.ts +3 -4
  53. package/src/activities/generateWorld/adapter.ts +96 -0
  54. package/src/activities/generateWorld/index.ts +339 -0
  55. package/src/activities/index.ts +44 -0
  56. package/src/activities/middleware/types.ts +2 -0
  57. package/src/client.ts +8 -0
  58. package/src/index.ts +8 -0
  59. package/src/middlewares/otel.ts +2 -0
  60. 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
- const stream = chat({
49
- adapter: openaiText('gpt-5.2'),
50
- messages,
51
- modelOptions: {
52
- temperature: 0.7,
53
- max_output_tokens: 1000,
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,17 +113,16 @@ 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
- const adapterWithKey = openaiText('gpt-5.2', {
121
- apiKey: 'sk-...',
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`:
@@ -137,26 +140,32 @@ input or configuration:
137
140
 
138
141
  ```typescript
139
142
  import { chat, toServerSentEventsResponse } from '@tanstack/ai'
140
- import type { TextAdapter } from '@tanstack/ai/adapters'
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: Record<string, () => TextAdapter> = {
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
- export function handleChat(providerModel: string, messages: Array<any>) {
153
- const createAdapter = adapters[providerModel]
154
- if (!createAdapter) {
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: createAdapter(),
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 (claude-sonnet-4-6 and newer)
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-4-6'),
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', // 'max' | 'high' | 'medium' | 'low'
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` | `max_tokens` |
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
- supportsCombinedToolsAndSchema?(modelOptions?: TProviderOptions): boolean
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` for Grok 4 family (gated by `GROK_COMBINED_TOOLS_AND_SCHEMA_MODELS`), `false` otherwise |
347
- | `groqText` | `false` (Groq API rejects schema + tools + stream) |
348
- | `openRouterText` / `openRouterResponsesText` | `false` (per-call resolution is a follow-up) |
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', apiKey, { ...gateway })
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 | Context Window | Max Output | Notes |
25
- | ------------------- | -------------- | ---------- | ------------------------------------------- |
26
- | `claude-fable-5` | 1M | 128K | Most capable; thinking always on (adaptive) |
27
- | `claude-sonnet-5` | 1M | 128K | Best balance; adaptive thinking by default |
28
- | `claude-opus-4-8` | 1M | 128K | Opus tier; adaptive thinking, no sampling |
29
- | `claude-opus-4-7` | 1M | 128K | Older Opus; adaptive thinking, no sampling |
30
- | `claude-opus-4-6` | 200K | 128K | Older Opus, adaptive + budget thinking |
31
- | `claude-sonnet-4-6` | 1M | 64K | Previous gen balanced, adaptive + budget |
32
- | `claude-sonnet-4-5` | 200K | 64K | Previous gen balanced |
33
- | `claude-opus-4-5` | 200K | 32K | Previous gen most capable |
34
- | `claude-opus-4-1` | 200K | 64K | Deprecated (retires 2026-08-05) |
35
- | `claude-haiku-4-5` | 200K | 64K | Fast and affordable |
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) and the `-fast`
39
- variant ids were removed — every registered id resolves against the
40
- first-party Anthropic API.
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
- thinking: {
60
- type: 'adaptive',
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
- thinkingConfig: {
52
- thinkingLevel: 'THINKING_LEVEL_HIGH',
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: 'HARM_CATEGORY_HATE_SPEECH',
58
- threshold: 'BLOCK_MEDIUM_AND_ABOVE',
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 | Context Window | Notes |
27
- | ----------------------------- | -------------- | ---------------------------- |
28
- | `grok-4-1-fast-reasoning` | 2M | Latest, fast reasoning |
29
- | `grok-4-1-fast-non-reasoning` | 2M | Latest, no reasoning |
30
- | `grok-code-fast-1` | 256K | Code-specialized, reasoning |
31
- | `grok-4` | 256K | Full reasoning, tool calling |
32
- | `grok-4-fast-reasoning` | 2M | Fast reasoning variant |
33
- | `grok-3` | 131K | Previous gen, no reasoning |
34
- | `grok-3-mini` | 131K | Budget reasoning |
35
- | `grok-2-vision-1212` | 32K | Vision input |
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 uses an OpenAI-compatible API. Options are straightforward:
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
- frequency_penalty: 0.5,
52
- presence_penalty: 0.5,
53
- stop: ['\n\n'],
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-4-1-fast-non-reasoning` and `grok-4-fast-non-reasoning` explicitly
72
- do NOT support reasoning. Other grok-4+ models do.
73
- - `grok-2-vision-1212` is the only model with image input support in the
74
- older generation.
75
- - The grok-4-1 fast models have a massive 2M context window.
76
- - Provider options are simpler than OpenAI's (no Responses API features,
77
- no structured outputs config, no metadata).
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 | Notes |
28
- | ------------ | -------------------------------- | ----------------------- |
29
- | Llama 4 | `llama4`, `llama4:scout` | Latest Meta models |
30
- | Llama 3.3 | `llama3.3`, `llama3.3:70b` | Strong general purpose |
31
- | Qwen 3 | `qwen3`, `qwen3:32b` | Reasoning capable |
32
- | DeepSeek R1 | `deepseek-r1`, `deepseek-r1:70b` | Reasoning focused |
33
- | Gemma 3 | `gemma3`, `gemma3:27b` | Google's open model |
34
- | Phi 4 | `phi4`, `phi4:14b` | Microsoft's small model |
35
- | Mistral | `mistral`, `mistral-large` | Mistral AI models |
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
- // With explicit host
69
- const adapter = ollamaText('llama3.3', {
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 | Context Window | Max Output | Notes |
32
- | --------------------- | -------------- | ---------- | -------------------------------------- |
33
- | `gpt-5.4` | 400K | 128K | Flagship, reasoning, image input |
34
- | `gpt-5.4-pro` | 400K | 128K | Higher reasoning, no structured output |
35
- | `gpt-5.4-chat-latest` | 128K | 16K | Chat-optimized variant |
36
- | `gpt-5.1` | 400K | 128K | Previous flagship, image I/O |
37
- | `gpt-5` | 400K | 128K | Previous gen flagship |
38
- | `gpt-5-mini` | 400K | 128K | Cost-efficient |
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.4'),
54
+ adapter: openaiText('gpt-5.5'),
45
55
  messages,
46
56
  modelOptions: {
47
57
  // Sampling