@tanstack/ai 0.0.1

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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/esm/base-adapter.d.ts +35 -0
  4. package/dist/esm/base-adapter.js +12 -0
  5. package/dist/esm/base-adapter.js.map +1 -0
  6. package/dist/esm/core/chat-common-options.d.ts +52 -0
  7. package/dist/esm/core/chat.d.ts +30 -0
  8. package/dist/esm/core/chat.js +533 -0
  9. package/dist/esm/core/chat.js.map +1 -0
  10. package/dist/esm/core/embedding.d.ts +8 -0
  11. package/dist/esm/core/embedding.js +33 -0
  12. package/dist/esm/core/embedding.js.map +1 -0
  13. package/dist/esm/core/summarize.d.ts +9 -0
  14. package/dist/esm/core/summarize.js +36 -0
  15. package/dist/esm/core/summarize.js.map +1 -0
  16. package/dist/esm/event-client.d.ts +311 -0
  17. package/dist/esm/event-client.js +62 -0
  18. package/dist/esm/event-client.js.map +1 -0
  19. package/dist/esm/index.d.ts +16 -0
  20. package/dist/esm/index.js +50 -0
  21. package/dist/esm/index.js.map +1 -0
  22. package/dist/esm/message-converters.d.ts +52 -0
  23. package/dist/esm/message-converters.js +162 -0
  24. package/dist/esm/message-converters.js.map +1 -0
  25. package/dist/esm/stream/index.d.ts +11 -0
  26. package/dist/esm/stream/json-parser.d.ts +38 -0
  27. package/dist/esm/stream/json-parser.js +28 -0
  28. package/dist/esm/stream/json-parser.js.map +1 -0
  29. package/dist/esm/stream/message-updaters.d.ts +44 -0
  30. package/dist/esm/stream/message-updaters.js +141 -0
  31. package/dist/esm/stream/message-updaters.js.map +1 -0
  32. package/dist/esm/stream/processor.d.ts +242 -0
  33. package/dist/esm/stream/processor.js +693 -0
  34. package/dist/esm/stream/processor.js.map +1 -0
  35. package/dist/esm/stream/strategies.d.ts +43 -0
  36. package/dist/esm/stream/strategies.js +54 -0
  37. package/dist/esm/stream/strategies.js.map +1 -0
  38. package/dist/esm/stream/types.d.ts +71 -0
  39. package/dist/esm/tools/tool-calls.d.ts +112 -0
  40. package/dist/esm/tools/tool-calls.js +302 -0
  41. package/dist/esm/tools/tool-calls.js.map +1 -0
  42. package/dist/esm/tools/tool-definition.d.ts +125 -0
  43. package/dist/esm/tools/tool-definition.js +25 -0
  44. package/dist/esm/tools/tool-definition.js.map +1 -0
  45. package/dist/esm/tools/zod-converter.d.ts +30 -0
  46. package/dist/esm/tools/zod-converter.js +36 -0
  47. package/dist/esm/tools/zod-converter.js.map +1 -0
  48. package/dist/esm/types.d.ts +619 -0
  49. package/dist/esm/utilities/agent-loop-strategies.d.ts +59 -0
  50. package/dist/esm/utilities/agent-loop-strategies.js +23 -0
  51. package/dist/esm/utilities/agent-loop-strategies.js.map +1 -0
  52. package/dist/esm/utilities/chat-options.d.ts +6 -0
  53. package/dist/esm/utilities/chat-options.js +7 -0
  54. package/dist/esm/utilities/chat-options.js.map +1 -0
  55. package/dist/esm/utilities/messages.d.ts +30 -0
  56. package/dist/esm/utilities/messages.js +7 -0
  57. package/dist/esm/utilities/messages.js.map +1 -0
  58. package/dist/esm/utilities/stream-to-response.d.ts +48 -0
  59. package/dist/esm/utilities/stream-to-response.js +62 -0
  60. package/dist/esm/utilities/stream-to-response.js.map +1 -0
  61. package/package.json +65 -0
  62. package/src/base-adapter.ts +85 -0
  63. package/src/core/chat-common-options.ts +55 -0
  64. package/src/core/chat.ts +771 -0
  65. package/src/core/embedding.ts +54 -0
  66. package/src/core/summarize.ts +56 -0
  67. package/src/event-client.ts +389 -0
  68. package/src/index.ts +68 -0
  69. package/src/message-converters.ts +285 -0
  70. package/src/stream/index.ts +41 -0
  71. package/src/stream/json-parser.ts +58 -0
  72. package/src/stream/message-updaters.ts +275 -0
  73. package/src/stream/processor.ts +1092 -0
  74. package/src/stream/strategies.ts +78 -0
  75. package/src/stream/types.ts +94 -0
  76. package/src/tools/tool-calls.ts +471 -0
  77. package/src/tools/tool-definition.ts +206 -0
  78. package/src/tools/zod-converter.ts +85 -0
  79. package/src/types.ts +872 -0
  80. package/src/utilities/agent-loop-strategies.ts +85 -0
  81. package/src/utilities/chat-options.ts +35 -0
  82. package/src/utilities/messages.ts +63 -0
  83. package/src/utilities/stream-to-response.ts +116 -0
package/src/types.ts ADDED
@@ -0,0 +1,872 @@
1
+ import type { CommonOptions } from './core/chat-common-options'
2
+ import type { z } from 'zod'
3
+ import type { ToolCallState, ToolResultState } from './stream/types'
4
+
5
+ export interface ToolCall {
6
+ id: string
7
+ type: 'function'
8
+ function: {
9
+ name: string
10
+ arguments: string // JSON string
11
+ }
12
+ }
13
+
14
+ // ============================================================================
15
+ // Multimodal Content Types
16
+ // ============================================================================
17
+
18
+ /**
19
+ * Supported input modality types for multimodal content.
20
+ * - 'text': Plain text content
21
+ * - 'image': Image content (base64 or URL)
22
+ * - 'audio': Audio content (base64 or URL)
23
+ * - 'video': Video content (base64 or URL)
24
+ * - 'document': Document content like PDFs (base64 or URL)
25
+ */
26
+ export type Modality = 'text' | 'image' | 'audio' | 'video' | 'document'
27
+
28
+ /**
29
+ * Source specification for multimodal content.
30
+ * Supports both inline data (base64) and URL-based content.
31
+ */
32
+ export interface ContentPartSource {
33
+ /**
34
+ * The type of source:
35
+ * - 'data': Inline data (typically base64 encoded)
36
+ * - 'url': URL reference to the content
37
+ */
38
+ type: 'data' | 'url'
39
+ /**
40
+ * The actual content value:
41
+ * - For 'data': base64-encoded string
42
+ * - For 'url': HTTP(S) URL or data URI
43
+ */
44
+ value: string
45
+ }
46
+
47
+ /**
48
+ * Image content part for multimodal messages.
49
+ * @template TMetadata - Provider-specific metadata type (e.g., OpenAI's detail level)
50
+ */
51
+ export interface ImagePart<TMetadata = unknown> {
52
+ type: 'image'
53
+ /** Source of the image content */
54
+ source: ContentPartSource
55
+ /** Provider-specific metadata (e.g., OpenAI's detail: 'auto' | 'low' | 'high') */
56
+ metadata?: TMetadata
57
+ }
58
+
59
+ /**
60
+ * Audio content part for multimodal messages.
61
+ * @template TMetadata - Provider-specific metadata type
62
+ */
63
+ export interface AudioPart<TMetadata = unknown> {
64
+ type: 'audio'
65
+ /** Source of the audio content */
66
+ source: ContentPartSource
67
+ /** Provider-specific metadata (e.g., format, sample rate) */
68
+ metadata?: TMetadata
69
+ }
70
+
71
+ /**
72
+ * Video content part for multimodal messages.
73
+ * @template TMetadata - Provider-specific metadata type
74
+ */
75
+ export interface VideoPart<TMetadata = unknown> {
76
+ type: 'video'
77
+ /** Source of the video content */
78
+ source: ContentPartSource
79
+ /** Provider-specific metadata (e.g., duration, resolution) */
80
+ metadata?: TMetadata
81
+ }
82
+
83
+ /**
84
+ * Document content part for multimodal messages (e.g., PDFs).
85
+ * @template TMetadata - Provider-specific metadata type (e.g., Anthropic's media_type)
86
+ */
87
+ export interface DocumentPart<TMetadata = unknown> {
88
+ type: 'document'
89
+ /** Source of the document content */
90
+ source: ContentPartSource
91
+ /** Provider-specific metadata (e.g., media_type for PDFs) */
92
+ metadata?: TMetadata
93
+ }
94
+
95
+ /**
96
+ * Union type for all multimodal content parts.
97
+ * @template TImageMeta - Provider-specific image metadata type
98
+ * @template TAudioMeta - Provider-specific audio metadata type
99
+ * @template TVideoMeta - Provider-specific video metadata type
100
+ * @template TDocumentMeta - Provider-specific document metadata type
101
+ */
102
+ export type ContentPart<
103
+ TImageMeta = unknown,
104
+ TAudioMeta = unknown,
105
+ TVideoMeta = unknown,
106
+ TDocumentMeta = unknown,
107
+ > =
108
+ | TextPart
109
+ | ImagePart<TImageMeta>
110
+ | AudioPart<TAudioMeta>
111
+ | VideoPart<TVideoMeta>
112
+ | DocumentPart<TDocumentMeta>
113
+
114
+ /**
115
+ * Helper type to filter ContentPart union to only include specific modalities.
116
+ * Used to constrain message content based on model capabilities.
117
+ */
118
+ export type ContentPartForModalities<
119
+ TModalities extends Modality,
120
+ TImageMeta = unknown,
121
+ TAudioMeta = unknown,
122
+ TVideoMeta = unknown,
123
+ TDocumentMeta = unknown,
124
+ > = Extract<
125
+ ContentPart<TImageMeta, TAudioMeta, TVideoMeta, TDocumentMeta>,
126
+ { type: TModalities }
127
+ >
128
+
129
+ /**
130
+ * Helper type to convert a readonly array of modalities to a union type.
131
+ * e.g., readonly ['text', 'image'] -> 'text' | 'image'
132
+ */
133
+ export type ModalitiesArrayToUnion<T extends ReadonlyArray<Modality>> =
134
+ T[number]
135
+
136
+ /**
137
+ * Type for message content constrained by supported modalities.
138
+ * When modalities is ['text', 'image'], only TextPart and ImagePart are allowed in the array.
139
+ */
140
+ export type ConstrainedContent<
141
+ TModalities extends ReadonlyArray<Modality>,
142
+ TImageMeta = unknown,
143
+ TAudioMeta = unknown,
144
+ TVideoMeta = unknown,
145
+ TDocumentMeta = unknown,
146
+ > =
147
+ | string
148
+ | null
149
+ | Array<
150
+ ContentPartForModalities<
151
+ ModalitiesArrayToUnion<TModalities>,
152
+ TImageMeta,
153
+ TAudioMeta,
154
+ TVideoMeta,
155
+ TDocumentMeta
156
+ >
157
+ >
158
+
159
+ export interface ModelMessage<
160
+ TContent extends string | null | Array<ContentPart> =
161
+ | string
162
+ | null
163
+ | Array<ContentPart>,
164
+ > {
165
+ role: 'user' | 'assistant' | 'tool'
166
+ content: TContent
167
+ name?: string
168
+ toolCalls?: Array<ToolCall>
169
+ toolCallId?: string
170
+ }
171
+
172
+ /**
173
+ * Message parts - building blocks of UIMessage
174
+ */
175
+ export interface TextPart {
176
+ type: 'text'
177
+ content: string
178
+ }
179
+
180
+ export interface ToolCallPart {
181
+ type: 'tool-call'
182
+ id: string
183
+ name: string
184
+ arguments: string // JSON string (may be incomplete)
185
+ state: ToolCallState
186
+ /** Approval metadata if tool requires user approval */
187
+ approval?: {
188
+ id: string // Unique approval ID
189
+ needsApproval: boolean // Always true if present
190
+ approved?: boolean // User's decision (undefined until responded)
191
+ }
192
+ /** Tool execution output (for client tools or after approval) */
193
+ output?: any
194
+ }
195
+
196
+ export interface ToolResultPart {
197
+ type: 'tool-result'
198
+ toolCallId: string
199
+ content: string
200
+ state: ToolResultState
201
+ error?: string // Error message if state is "error"
202
+ }
203
+
204
+ export interface ThinkingPart {
205
+ type: 'thinking'
206
+ content: string
207
+ }
208
+
209
+ export type MessagePart =
210
+ | TextPart
211
+ | ToolCallPart
212
+ | ToolResultPart
213
+ | ThinkingPart
214
+
215
+ /**
216
+ * UIMessage - Domain-specific message format optimized for building chat UIs
217
+ * Contains parts that can be text, tool calls, or tool results
218
+ */
219
+ export interface UIMessage {
220
+ id: string
221
+ role: 'system' | 'user' | 'assistant'
222
+ parts: Array<MessagePart>
223
+ createdAt?: Date
224
+ }
225
+ /**
226
+ * A ModelMessage with content constrained to only allow content parts
227
+ * matching the specified input modalities.
228
+ */
229
+ export type ConstrainedModelMessage<
230
+ TModalities extends ReadonlyArray<Modality>,
231
+ TImageMeta = unknown,
232
+ TAudioMeta = unknown,
233
+ TVideoMeta = unknown,
234
+ TDocumentMeta = unknown,
235
+ > = Omit<ModelMessage, 'content'> & {
236
+ content: ConstrainedContent<
237
+ TModalities,
238
+ TImageMeta,
239
+ TAudioMeta,
240
+ TVideoMeta,
241
+ TDocumentMeta
242
+ >
243
+ }
244
+
245
+ /**
246
+ * Tool/Function definition for function calling.
247
+ *
248
+ * Tools allow the model to interact with external systems, APIs, or perform computations.
249
+ * The model will decide when to call tools based on the user's request and the tool descriptions.
250
+ *
251
+ * Tools use Zod schemas for runtime validation and type safety.
252
+ *
253
+ * @see https://platform.openai.com/docs/guides/function-calling
254
+ * @see https://docs.anthropic.com/claude/docs/tool-use
255
+ */
256
+ export interface Tool<
257
+ TInput extends z.ZodType = z.ZodType,
258
+ TOutput extends z.ZodType = z.ZodType,
259
+ TName extends string = string,
260
+ > {
261
+ /**
262
+ * Unique name of the tool (used by the model to call it).
263
+ *
264
+ * Should be descriptive and follow naming conventions (e.g., snake_case or camelCase).
265
+ * Must be unique within the tools array.
266
+ *
267
+ * @example "get_weather", "search_database", "sendEmail"
268
+ */
269
+ name: TName
270
+
271
+ /**
272
+ * Clear description of what the tool does.
273
+ *
274
+ * This is crucial - the model uses this to decide when to call the tool.
275
+ * Be specific about what the tool does, what parameters it needs, and what it returns.
276
+ *
277
+ * @example "Get the current weather in a given location. Returns temperature, conditions, and forecast."
278
+ */
279
+ description: string
280
+
281
+ /**
282
+ * Zod schema describing the tool's input parameters.
283
+ *
284
+ * Defines the structure and types of arguments the tool accepts.
285
+ * The model will generate arguments matching this schema.
286
+ * The schema is converted to JSON Schema for LLM providers.
287
+ *
288
+ * @see https://zod.dev/
289
+ *
290
+ * @example
291
+ * import { z } from 'zod';
292
+ *
293
+ * z.object({
294
+ * location: z.string().describe("City name or coordinates"),
295
+ * unit: z.enum(["celsius", "fahrenheit"]).optional()
296
+ * })
297
+ */
298
+ inputSchema?: TInput
299
+
300
+ /**
301
+ * Optional Zod schema for validating tool output.
302
+ *
303
+ * If provided, tool results will be validated against this schema before
304
+ * being sent back to the model. This catches bugs in tool implementations
305
+ * and ensures consistent output formatting.
306
+ *
307
+ * Note: This is client-side validation only - not sent to LLM providers.
308
+ *
309
+ * @example
310
+ * z.object({
311
+ * temperature: z.number(),
312
+ * conditions: z.string(),
313
+ * forecast: z.array(z.string()).optional()
314
+ * })
315
+ */
316
+ outputSchema?: TOutput
317
+
318
+ /**
319
+ * Optional function to execute when the model calls this tool.
320
+ *
321
+ * If provided, the SDK will automatically execute the function with the model's arguments
322
+ * and feed the result back to the model. This enables autonomous tool use loops.
323
+ *
324
+ * Can return any value - will be automatically stringified if needed.
325
+ *
326
+ * @param args - The arguments parsed from the model's tool call (validated against inputSchema)
327
+ * @returns Result to send back to the model (validated against outputSchema if provided)
328
+ *
329
+ * @example
330
+ * execute: async (args) => {
331
+ * const weather = await fetchWeather(args.location);
332
+ * return weather; // Can return object or string
333
+ * }
334
+ */
335
+ execute?: (args: any) => Promise<any> | any
336
+
337
+ /** If true, tool execution requires user approval before running. Works with both server and client tools. */
338
+ needsApproval?: boolean
339
+
340
+ /** Additional metadata for adapters or custom extensions */
341
+ metadata?: Record<string, any>
342
+ }
343
+
344
+ export interface ToolConfig {
345
+ [key: string]: Tool
346
+ }
347
+
348
+ /**
349
+ * Structured output format specification.
350
+ *
351
+ * Constrains the model's output to match a specific JSON structure.
352
+ * Useful for extracting structured data, form filling, or ensuring consistent response formats.
353
+ *
354
+ * @see https://platform.openai.com/docs/guides/structured-outputs
355
+ * @see https://sdk.vercel.ai/docs/ai-sdk-core/structured-outputs
356
+ *
357
+ * @template TData - TypeScript type of the expected data structure (for type safety)
358
+ */
359
+ export interface ResponseFormat<TData = any> {
360
+ /**
361
+ * Type of structured output.
362
+ *
363
+ * - "json_object": Forces the model to output valid JSON (any structure)
364
+ * - "json_schema": Validates output against a provided JSON Schema (strict structure)
365
+ *
366
+ * @see https://platform.openai.com/docs/api-reference/chat/create#chat-create-response_format
367
+ */
368
+ type: 'json_object' | 'json_schema'
369
+
370
+ /**
371
+ * JSON schema specification (required when type is "json_schema").
372
+ *
373
+ * Defines the exact structure the model's output must conform to.
374
+ * OpenAI's structured outputs will guarantee the output matches this schema.
375
+ */
376
+ json_schema?: {
377
+ /**
378
+ * Unique name for the schema.
379
+ *
380
+ * Used to identify the schema in logs and debugging.
381
+ * Should be descriptive (e.g., "user_profile", "search_results").
382
+ */
383
+ name: string
384
+
385
+ /**
386
+ * Optional description of what the schema represents.
387
+ *
388
+ * Helps document the purpose of this structured output.
389
+ *
390
+ * @example "User profile information including name, email, and preferences"
391
+ */
392
+ description?: string
393
+
394
+ /**
395
+ * JSON Schema definition for the expected output structure.
396
+ *
397
+ * Must be a valid JSON Schema (draft 2020-12 or compatible).
398
+ * The model's output will be validated against this schema.
399
+ *
400
+ * @see https://json-schema.org/
401
+ *
402
+ * @example
403
+ * {
404
+ * type: "object",
405
+ * properties: {
406
+ * name: { type: "string" },
407
+ * age: { type: "number" },
408
+ * email: { type: "string", format: "email" }
409
+ * },
410
+ * required: ["name", "email"],
411
+ * additionalProperties: false
412
+ * }
413
+ */
414
+ schema: Record<string, any>
415
+
416
+ /**
417
+ * Whether to enforce strict schema validation.
418
+ *
419
+ * When true (recommended), the model guarantees output will match the schema exactly.
420
+ * When false, the model will "best effort" match the schema.
421
+ *
422
+ * Default: true (for providers that support it)
423
+ *
424
+ * @see https://platform.openai.com/docs/guides/structured-outputs#strict-mode
425
+ */
426
+ strict?: boolean
427
+ }
428
+
429
+ /**
430
+ * Type-only property to carry the inferred data type.
431
+ *
432
+ * This is never set at runtime - it only exists for TypeScript type inference.
433
+ * Allows the SDK to know what type to expect when parsing the response.
434
+ *
435
+ * @internal
436
+ */
437
+ __data?: TData
438
+ }
439
+
440
+ /**
441
+ * State passed to agent loop strategy for determining whether to continue
442
+ */
443
+ export interface AgentLoopState {
444
+ /** Current iteration count (0-indexed) */
445
+ iterationCount: number
446
+ /** Current messages array */
447
+ messages: Array<ModelMessage>
448
+ /** Finish reason from the last response */
449
+ finishReason: string | null
450
+ }
451
+
452
+ /**
453
+ * Strategy function that determines whether the agent loop should continue
454
+ *
455
+ * @param state - Current state of the agent loop
456
+ * @returns true to continue looping, false to stop
457
+ *
458
+ * @example
459
+ * ```typescript
460
+ * // Continue for up to 5 iterations
461
+ * const strategy: AgentLoopStrategy = ({ iterationCount }) => iterationCount < 5;
462
+ * ```
463
+ */
464
+ export type AgentLoopStrategy = (state: AgentLoopState) => boolean
465
+
466
+ /**
467
+ * Options passed into the SDK and further piped to the AI provider.
468
+ */
469
+ export interface ChatOptions<
470
+ TModel extends string = string,
471
+ TProviderOptionsSuperset extends Record<string, any> = Record<string, any>,
472
+ TOutput extends ResponseFormat<any> | undefined = undefined,
473
+ TProviderOptionsForModel = TProviderOptionsSuperset,
474
+ > {
475
+ model: TModel
476
+ messages: Array<ModelMessage>
477
+ tools?: Array<Tool>
478
+ systemPrompts?: Array<string>
479
+ agentLoopStrategy?: AgentLoopStrategy
480
+ options?: CommonOptions
481
+ providerOptions?: TProviderOptionsForModel
482
+ request?: Request | RequestInit
483
+ output?: TOutput
484
+ /**
485
+ * Conversation ID for correlating client and server-side devtools events.
486
+ * When provided, server-side events will be linked to the client conversation in devtools.
487
+ */
488
+ conversationId?: string
489
+ /**
490
+ * AbortController for request cancellation.
491
+ *
492
+ * Allows you to cancel an in-progress request using an AbortController.
493
+ * Useful for implementing timeouts or user-initiated cancellations.
494
+ *
495
+ * @example
496
+ * const abortController = new AbortController();
497
+ * setTimeout(() => abortController.abort(), 5000); // Cancel after 5 seconds
498
+ * await chat({ ..., abortController });
499
+ *
500
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortController
501
+ */
502
+ abortController?: AbortController
503
+ }
504
+
505
+ export type StreamChunkType =
506
+ | 'content'
507
+ | 'tool_call'
508
+ | 'tool_result'
509
+ | 'done'
510
+ | 'error'
511
+ | 'approval-requested'
512
+ | 'tool-input-available'
513
+ | 'thinking'
514
+
515
+ export interface BaseStreamChunk {
516
+ type: StreamChunkType
517
+ id: string
518
+ model: string
519
+ timestamp: number
520
+ }
521
+
522
+ export interface ContentStreamChunk extends BaseStreamChunk {
523
+ type: 'content'
524
+ delta: string // The incremental content token
525
+ content: string // Full accumulated content so far
526
+ role?: 'assistant'
527
+ }
528
+
529
+ export interface ToolCallStreamChunk extends BaseStreamChunk {
530
+ type: 'tool_call'
531
+ toolCall: {
532
+ id: string
533
+ type: 'function'
534
+ function: {
535
+ name: string
536
+ arguments: string // Incremental JSON arguments
537
+ }
538
+ }
539
+ index: number
540
+ }
541
+
542
+ export interface ToolResultStreamChunk extends BaseStreamChunk {
543
+ type: 'tool_result'
544
+ toolCallId: string
545
+ content: string
546
+ }
547
+
548
+ export interface DoneStreamChunk extends BaseStreamChunk {
549
+ type: 'done'
550
+ finishReason: 'stop' | 'length' | 'content_filter' | 'tool_calls' | null
551
+ usage?: {
552
+ promptTokens: number
553
+ completionTokens: number
554
+ totalTokens: number
555
+ }
556
+ }
557
+
558
+ export interface ErrorStreamChunk extends BaseStreamChunk {
559
+ type: 'error'
560
+ error: {
561
+ message: string
562
+ code?: string
563
+ }
564
+ }
565
+
566
+ export interface ApprovalRequestedStreamChunk extends BaseStreamChunk {
567
+ type: 'approval-requested'
568
+ toolCallId: string
569
+ toolName: string
570
+ input: any
571
+ approval: {
572
+ id: string
573
+ needsApproval: true
574
+ }
575
+ }
576
+
577
+ export interface ToolInputAvailableStreamChunk extends BaseStreamChunk {
578
+ type: 'tool-input-available'
579
+ toolCallId: string
580
+ toolName: string
581
+ input: any
582
+ }
583
+
584
+ export interface ThinkingStreamChunk extends BaseStreamChunk {
585
+ type: 'thinking'
586
+ delta?: string // The incremental thinking token
587
+ content: string // Full accumulated thinking content so far
588
+ }
589
+
590
+ /**
591
+ * Chunk returned by the sdk during streaming chat completions.
592
+ */
593
+ export type StreamChunk =
594
+ | ContentStreamChunk
595
+ | ToolCallStreamChunk
596
+ | ToolResultStreamChunk
597
+ | DoneStreamChunk
598
+ | ErrorStreamChunk
599
+ | ApprovalRequestedStreamChunk
600
+ | ToolInputAvailableStreamChunk
601
+ | ThinkingStreamChunk
602
+
603
+ // Simple streaming format for basic chat completions
604
+ // Converted to StreamChunk format by convertChatCompletionStream()
605
+ export interface ChatCompletionChunk {
606
+ id: string
607
+ model: string
608
+ content: string
609
+ role?: 'assistant'
610
+ finishReason?: 'stop' | 'length' | 'content_filter' | null
611
+ usage?: {
612
+ promptTokens: number
613
+ completionTokens: number
614
+ totalTokens: number
615
+ }
616
+ }
617
+
618
+ export interface SummarizationOptions {
619
+ model: string
620
+ text: string
621
+ maxLength?: number
622
+ style?: 'bullet-points' | 'paragraph' | 'concise'
623
+ focus?: Array<string>
624
+ }
625
+
626
+ export interface SummarizationResult {
627
+ id: string
628
+ model: string
629
+ summary: string
630
+ usage: {
631
+ promptTokens: number
632
+ completionTokens: number
633
+ totalTokens: number
634
+ }
635
+ }
636
+
637
+ export interface EmbeddingOptions {
638
+ model: string
639
+ input: string | Array<string>
640
+ dimensions?: number
641
+ }
642
+
643
+ export interface EmbeddingResult {
644
+ id: string
645
+ model: string
646
+ embeddings: Array<Array<number>>
647
+ usage: {
648
+ promptTokens: number
649
+ totalTokens: number
650
+ }
651
+ }
652
+
653
+ /**
654
+ * Default metadata type for adapters that don't define custom metadata.
655
+ * Uses unknown for all modalities.
656
+ */
657
+ export interface DefaultMessageMetadataByModality {
658
+ image: unknown
659
+ audio: unknown
660
+ video: unknown
661
+ document: unknown
662
+ }
663
+
664
+ /**
665
+ * AI adapter interface with support for endpoint-specific models and provider options.
666
+ *
667
+ * Generic parameters:
668
+ * - TChatModels: Models that support chat/text completion
669
+ * - TEmbeddingModels: Models that support embeddings
670
+ * - TChatProviderOptions: Provider-specific options for chat endpoint
671
+ * - TEmbeddingProviderOptions: Provider-specific options for embedding endpoint
672
+ * - TModelProviderOptionsByName: Map from model name to its specific provider options
673
+ * - TModelInputModalitiesByName: Map from model name to its supported input modalities
674
+ * - TMessageMetadataByModality: Map from modality type to adapter-specific metadata types
675
+ */
676
+ export interface AIAdapter<
677
+ TChatModels extends ReadonlyArray<string> = ReadonlyArray<string>,
678
+ TEmbeddingModels extends ReadonlyArray<string> = ReadonlyArray<string>,
679
+ TChatProviderOptions extends Record<string, any> = Record<string, any>,
680
+ TEmbeddingProviderOptions extends Record<string, any> = Record<string, any>,
681
+ TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,
682
+ TModelInputModalitiesByName extends Record<
683
+ string,
684
+ ReadonlyArray<Modality>
685
+ > = Record<string, ReadonlyArray<Modality>>,
686
+ TMessageMetadataByModality extends {
687
+ image: unknown
688
+ audio: unknown
689
+ video: unknown
690
+ document: unknown
691
+ } = DefaultMessageMetadataByModality,
692
+ > {
693
+ name: string
694
+ /** Models that support chat/text completion */
695
+ models: TChatModels
696
+
697
+ /** Models that support embeddings */
698
+ embeddingModels?: TEmbeddingModels
699
+
700
+ // Type-only properties for provider options inference
701
+ _providerOptions?: TChatProviderOptions // Alias for _chatProviderOptions
702
+ _chatProviderOptions?: TChatProviderOptions
703
+ _embeddingProviderOptions?: TEmbeddingProviderOptions
704
+ /**
705
+ * Type-only map from model name to its specific provider options.
706
+ * Used by the core AI types to narrow providerOptions based on the selected model.
707
+ * Must be provided by all adapters.
708
+ */
709
+ _modelProviderOptionsByName: TModelProviderOptionsByName
710
+ /**
711
+ * Type-only map from model name to its supported input modalities.
712
+ * Used by the core AI types to narrow ContentPart types based on the selected model.
713
+ * Must be provided by all adapters.
714
+ */
715
+ _modelInputModalitiesByName?: TModelInputModalitiesByName
716
+ /**
717
+ * Type-only map from modality type to adapter-specific metadata types.
718
+ * Used to provide type-safe autocomplete for metadata on content parts.
719
+ */
720
+ _messageMetadataByModality?: TMessageMetadataByModality
721
+
722
+ // Structured streaming with JSON chunks (supports tool calls and rich content)
723
+ chatStream: (
724
+ options: ChatOptions<string, TChatProviderOptions>,
725
+ ) => AsyncIterable<StreamChunk>
726
+
727
+ // Summarization
728
+ summarize: (options: SummarizationOptions) => Promise<SummarizationResult>
729
+
730
+ // Embeddings
731
+ createEmbeddings: (options: EmbeddingOptions) => Promise<EmbeddingResult>
732
+ }
733
+
734
+ export interface AIAdapterConfig {
735
+ apiKey?: string
736
+ baseUrl?: string
737
+ timeout?: number
738
+ maxRetries?: number
739
+ headers?: Record<string, string>
740
+ }
741
+
742
+ export type ChatStreamOptionsUnion<
743
+ TAdapter extends AIAdapter<any, any, any, any, any, any, any>,
744
+ > =
745
+ TAdapter extends AIAdapter<
746
+ infer Models,
747
+ any,
748
+ any,
749
+ any,
750
+ infer ModelProviderOptions,
751
+ infer ModelInputModalities,
752
+ infer MessageMetadata
753
+ >
754
+ ? Models[number] extends infer TModel
755
+ ? TModel extends string
756
+ ? Omit<
757
+ ChatOptions,
758
+ 'model' | 'providerOptions' | 'responseFormat' | 'messages'
759
+ > & {
760
+ adapter: TAdapter
761
+ model: TModel
762
+ providerOptions?: TModel extends keyof ModelProviderOptions
763
+ ? ModelProviderOptions[TModel]
764
+ : never
765
+ /**
766
+ * Messages array with content constrained to the model's supported input modalities.
767
+ * For example, if a model only supports ['text', 'image'], you cannot pass audio or video content.
768
+ * Metadata types are also constrained based on the adapter's metadata type definitions.
769
+ */
770
+ messages: TModel extends keyof ModelInputModalities
771
+ ? ModelInputModalities[TModel] extends ReadonlyArray<Modality>
772
+ ? MessageMetadata extends {
773
+ image: infer TImageMeta
774
+ audio: infer TAudioMeta
775
+ video: infer TVideoMeta
776
+ document: infer TDocumentMeta
777
+ }
778
+ ? Array<
779
+ ConstrainedModelMessage<
780
+ ModelInputModalities[TModel],
781
+ TImageMeta,
782
+ TAudioMeta,
783
+ TVideoMeta,
784
+ TDocumentMeta
785
+ >
786
+ >
787
+ : Array<ConstrainedModelMessage<ModelInputModalities[TModel]>>
788
+ : Array<ModelMessage>
789
+ : Array<ModelMessage>
790
+ }
791
+ : never
792
+ : never
793
+ : never
794
+
795
+ /**
796
+ * Chat options constrained by a specific model's capabilities.
797
+ * Unlike ChatStreamOptionsUnion which creates a union over all models,
798
+ * this type takes a specific model and constrains messages accordingly.
799
+ */
800
+ export type ChatStreamOptionsForModel<
801
+ TAdapter extends AIAdapter<any, any, any, any, any, any, any>,
802
+ TModel extends string,
803
+ > =
804
+ TAdapter extends AIAdapter<
805
+ any,
806
+ any,
807
+ any,
808
+ any,
809
+ infer ModelProviderOptions,
810
+ infer ModelInputModalities,
811
+ infer MessageMetadata
812
+ >
813
+ ? Omit<
814
+ ChatOptions,
815
+ 'model' | 'providerOptions' | 'responseFormat' | 'messages'
816
+ > & {
817
+ adapter: TAdapter
818
+ model: TModel
819
+ providerOptions?: TModel extends keyof ModelProviderOptions
820
+ ? ModelProviderOptions[TModel]
821
+ : never
822
+ /**
823
+ * Messages array with content constrained to the model's supported input modalities.
824
+ * For example, if a model only supports ['text', 'image'], you cannot pass audio or video content.
825
+ * Metadata types are also constrained based on the adapter's metadata type definitions.
826
+ */
827
+ messages: TModel extends keyof ModelInputModalities
828
+ ? ModelInputModalities[TModel] extends ReadonlyArray<Modality>
829
+ ? MessageMetadata extends {
830
+ image: infer TImageMeta
831
+ audio: infer TAudioMeta
832
+ video: infer TVideoMeta
833
+ document: infer TDocumentMeta
834
+ }
835
+ ? Array<
836
+ ConstrainedModelMessage<
837
+ ModelInputModalities[TModel],
838
+ TImageMeta,
839
+ TAudioMeta,
840
+ TVideoMeta,
841
+ TDocumentMeta
842
+ >
843
+ >
844
+ : Array<ConstrainedModelMessage<ModelInputModalities[TModel]>>
845
+ : Array<ModelMessage>
846
+ : Array<ModelMessage>
847
+ }
848
+ : never
849
+
850
+ // Extract types from adapter (updated to 6 generics)
851
+ export type ExtractModelsFromAdapter<T> =
852
+ T extends AIAdapter<infer M, any, any, any, any, any> ? M[number] : never
853
+
854
+ /**
855
+ * Extract the supported input modalities for a specific model from an adapter.
856
+ */
857
+ export type ExtractModalitiesForModel<
858
+ TAdapter extends AIAdapter<any, any, any, any, any, any>,
859
+ TModel extends string,
860
+ > =
861
+ TAdapter extends AIAdapter<
862
+ any,
863
+ any,
864
+ any,
865
+ any,
866
+ any,
867
+ infer ModelInputModalities
868
+ >
869
+ ? TModel extends keyof ModelInputModalities
870
+ ? ModelInputModalities[TModel]
871
+ : ReadonlyArray<Modality>
872
+ : ReadonlyArray<Modality>