@tanstack/ai 0.58.0 → 0.61.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 (144) hide show
  1. package/dist/esm/activities/chat/adapter.d.ts +9 -0
  2. package/dist/esm/activities/chat/adapter.js +1 -0
  3. package/dist/esm/activities/chat/adapter.js.map +1 -1
  4. package/dist/esm/activities/chat/agents/define-agent.d.ts +81 -0
  5. package/dist/esm/activities/chat/agents/define-agent.js +34 -0
  6. package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
  7. package/dist/esm/activities/chat/agents/route.d.ts +53 -0
  8. package/dist/esm/activities/chat/agents/route.js +59 -0
  9. package/dist/esm/activities/chat/agents/route.js.map +1 -0
  10. package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
  11. package/dist/esm/activities/chat/agents/spawn.js +490 -0
  12. package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
  13. package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
  14. package/dist/esm/activities/chat/agents/turn.js +78 -0
  15. package/dist/esm/activities/chat/agents/turn.js.map +1 -0
  16. package/dist/esm/activities/chat/index.d.ts +13 -3
  17. package/dist/esm/activities/chat/index.js +462 -26
  18. package/dist/esm/activities/chat/index.js.map +1 -1
  19. package/dist/esm/activities/chat/messages.d.ts +7 -1
  20. package/dist/esm/activities/chat/messages.js +99 -19
  21. package/dist/esm/activities/chat/messages.js.map +1 -1
  22. package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
  23. package/dist/esm/activities/chat/middleware/run-store.js +8 -1
  24. package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
  25. package/dist/esm/activities/chat/middleware/types.d.ts +47 -1
  26. package/dist/esm/activities/chat/middleware/types.js.map +1 -1
  27. package/dist/esm/activities/chat/stream/message-updaters.js +9 -2
  28. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  29. package/dist/esm/activities/chat/stream/processor.d.ts +46 -1
  30. package/dist/esm/activities/chat/stream/processor.js +294 -18
  31. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  32. package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
  33. package/dist/esm/activities/chat/tools/tool-calls.js +56 -5
  34. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  35. package/dist/esm/activities/embed/adapter.d.ts +7 -0
  36. package/dist/esm/activities/embed/adapter.js +1 -0
  37. package/dist/esm/activities/embed/adapter.js.map +1 -1
  38. package/dist/esm/activities/embed/index.js +2 -0
  39. package/dist/esm/activities/embed/index.js.map +1 -1
  40. package/dist/esm/activities/files/adapter.d.ts +97 -0
  41. package/dist/esm/activities/files/adapter.js +45 -0
  42. package/dist/esm/activities/files/adapter.js.map +1 -0
  43. package/dist/esm/activities/files/index.d.ts +66 -0
  44. package/dist/esm/activities/files/index.js +78 -0
  45. package/dist/esm/activities/files/index.js.map +1 -0
  46. package/dist/esm/activities/generateAudio/index.js +1 -1
  47. package/dist/esm/activities/generateImage/adapter.d.ts +8 -0
  48. package/dist/esm/activities/generateImage/adapter.js +1 -0
  49. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  50. package/dist/esm/activities/generateImage/index.js +3 -1
  51. package/dist/esm/activities/generateImage/index.js.map +1 -1
  52. package/dist/esm/activities/generateLiveVideo/index.js +1 -1
  53. package/dist/esm/activities/generateSpeech/index.js +1 -1
  54. package/dist/esm/activities/generateTranscription/index.js +1 -1
  55. package/dist/esm/activities/generateVideo/adapter.d.ts +8 -0
  56. package/dist/esm/activities/generateVideo/adapter.js +1 -0
  57. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  58. package/dist/esm/activities/generateVideo/index.js +3 -0
  59. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  60. package/dist/esm/activities/generateVoice/index.js +1 -1
  61. package/dist/esm/activities/generateWorld/adapter.d.ts +4 -2
  62. package/dist/esm/activities/generateWorld/adapter.js.map +1 -1
  63. package/dist/esm/activities/generateWorld/index.d.ts +4 -3
  64. package/dist/esm/activities/generateWorld/index.js +6 -5
  65. package/dist/esm/activities/generateWorld/index.js.map +1 -1
  66. package/dist/esm/activities/index.d.ts +9 -3
  67. package/dist/esm/activities/index.js +17 -13
  68. package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -0
  69. package/dist/esm/activities/summarize/chat-stream-summarize.js +8 -8
  70. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
  71. package/dist/esm/activities/summarize/index.js +1 -1
  72. package/dist/esm/client.d.ts +7 -36
  73. package/dist/esm/client.js +5 -37
  74. package/dist/esm/client.js.map +1 -1
  75. package/dist/esm/index.d.ts +8 -2
  76. package/dist/esm/index.js +9 -4
  77. package/dist/esm/middlewares/content-guard.js.map +1 -1
  78. package/dist/esm/types.d.ts +179 -98
  79. package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
  80. package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
  81. package/dist/esm/utilities/ag-ui-usage.js +66 -3
  82. package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
  83. package/dist/esm/utilities/ag-ui-wire.js +90 -13
  84. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  85. package/dist/esm/utilities/content-source.d.ts +60 -0
  86. package/dist/esm/utilities/content-source.js +85 -0
  87. package/dist/esm/utilities/content-source.js.map +1 -0
  88. package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
  89. package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
  90. package/dist/esm/utilities/provider-executed.d.ts +7 -0
  91. package/dist/esm/utilities/provider-executed.js +10 -1
  92. package/dist/esm/utilities/provider-executed.js.map +1 -1
  93. package/dist/esm/utilities/spec-event-keys.js +13 -8
  94. package/dist/esm/utilities/spec-event-keys.js.map +1 -1
  95. package/dist/esm/utilities/subagent-wire.d.ts +36 -0
  96. package/dist/esm/utilities/subagent-wire.js +131 -0
  97. package/dist/esm/utilities/subagent-wire.js.map +1 -0
  98. package/dist/esm/utilities/tool-result.d.ts +12 -2
  99. package/dist/esm/utilities/tool-result.js +23 -3
  100. package/dist/esm/utilities/tool-result.js.map +1 -1
  101. package/package.json +3 -3
  102. package/skills/ai-core/adapter-configuration/SKILL.md +62 -0
  103. package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
  104. package/skills/ai-core/chat-experience/SKILL.md +14 -0
  105. package/skills/ai-core/media-generation/SKILL.md +10 -2
  106. package/skills/ai-core/middleware/SKILL.md +7 -4
  107. package/src/activities/chat/adapter.ts +10 -0
  108. package/src/activities/chat/agents/define-agent.ts +121 -0
  109. package/src/activities/chat/agents/route.ts +115 -0
  110. package/src/activities/chat/agents/spawn.ts +806 -0
  111. package/src/activities/chat/agents/turn.ts +151 -0
  112. package/src/activities/chat/index.ts +734 -30
  113. package/src/activities/chat/messages.ts +137 -16
  114. package/src/activities/chat/middleware/run-store.ts +56 -7
  115. package/src/activities/chat/middleware/types.ts +47 -0
  116. package/src/activities/chat/stream/message-updaters.ts +24 -2
  117. package/src/activities/chat/stream/processor.ts +452 -30
  118. package/src/activities/chat/tools/tool-calls.ts +83 -11
  119. package/src/activities/embed/adapter.ts +7 -0
  120. package/src/activities/embed/index.ts +5 -0
  121. package/src/activities/files/adapter.ts +120 -0
  122. package/src/activities/files/index.ts +113 -0
  123. package/src/activities/generateImage/adapter.ts +8 -0
  124. package/src/activities/generateImage/index.ts +4 -0
  125. package/src/activities/generateVideo/adapter.ts +8 -0
  126. package/src/activities/generateVideo/index.ts +7 -0
  127. package/src/activities/generateWorld/adapter.ts +4 -2
  128. package/src/activities/generateWorld/index.ts +7 -6
  129. package/src/activities/index.ts +40 -1
  130. package/src/activities/summarize/chat-stream-summarize.ts +22 -12
  131. package/src/client.ts +29 -35
  132. package/src/index.ts +39 -0
  133. package/src/middlewares/content-guard.ts +7 -5
  134. package/src/types.ts +226 -103
  135. package/src/utilities/adapter-yield-chunk.ts +10 -2
  136. package/src/utilities/ag-ui-usage.test.ts +38 -0
  137. package/src/utilities/ag-ui-usage.ts +98 -11
  138. package/src/utilities/ag-ui-wire.ts +134 -16
  139. package/src/utilities/content-source.ts +138 -0
  140. package/src/utilities/normalize-stream-chunk.ts +10 -2
  141. package/src/utilities/provider-executed.ts +13 -0
  142. package/src/utilities/spec-event-keys.ts +34 -7
  143. package/src/utilities/subagent-wire.ts +184 -0
  144. package/src/utilities/tool-result.ts +38 -2
package/src/types.ts CHANGED
@@ -19,12 +19,22 @@ import type {
19
19
  UsageCostBreakdown,
20
20
  } from '@tanstack/ai-event-client'
21
21
  import type {
22
+ ActivityDeltaEvent as AGUIActivityDeltaEvent,
23
+ ActivitySnapshotEvent as AGUIActivitySnapshotEvent,
24
+ AudioPart as AGUIAudioPart,
22
25
  BaseEvent as AGUIBaseEvent,
26
+ ContentPart as AGUIContentPart,
23
27
  CustomEvent as AGUICustomEvent,
28
+ DataSource as AGUIDataSource,
29
+ DocumentPart as AGUIDocumentPart,
30
+ FileSource as AGUIFileSource,
31
+ ImagePart as AGUIImagePart,
24
32
  Interrupt as AGUIInterrupt,
25
33
  MessagesSnapshotEvent as AGUIMessagesSnapshotEvent,
26
34
  ReasoningEncryptedValueEvent as AGUIReasoningEncryptedValueEvent,
27
35
  ReasoningEndEvent as AGUIReasoningEndEvent,
36
+ RawEvent as AGUIRawEvent,
37
+ ReasoningMessageChunkEvent as AGUIReasoningMessageChunkEvent,
28
38
  ReasoningMessageContentEvent as AGUIReasoningMessageContentEvent,
29
39
  ReasoningMessageEndEvent as AGUIReasoningMessageEndEvent,
30
40
  ReasoningMessageStartEvent as AGUIReasoningMessageStartEvent,
@@ -38,19 +48,31 @@ import type {
38
48
  StateSnapshotEvent as AGUIStateSnapshotEvent,
39
49
  StepFinishedEvent as AGUIStepFinishedEvent,
40
50
  StepStartedEvent as AGUIStepStartedEvent,
51
+ SubagentErrorEvent as AGUISubagentErrorEvent,
52
+ SubagentFinishedEvent as AGUISubagentFinishedEvent,
53
+ SubagentFinishedSuspendedOutcome as AGUISubagentFinishedSuspendedOutcome,
54
+ SubagentInfo as AGUISubagentInfo,
55
+ SubagentRunId as AGUISubagentRunId,
56
+ SubagentStartedEvent as AGUISubagentStartedEvent,
57
+ TextMessageChunkEvent as AGUITextMessageChunkEvent,
41
58
  TextMessageContentEvent as AGUITextMessageContentEvent,
42
59
  TextMessageEndEvent as AGUITextMessageEndEvent,
43
60
  TextMessageStartEvent as AGUITextMessageStartEvent,
61
+ ToolCall as AGUIToolCall,
44
62
  ToolCallArgsEvent as AGUIToolCallArgsEvent,
63
+ ToolCallChunkEvent as AGUIToolCallChunkEvent,
45
64
  ToolCallEndEvent as AGUIToolCallEndEvent,
46
65
  ToolCallResultEvent as AGUIToolCallResultEvent,
47
66
  ToolCallStartEvent as AGUIToolCallStartEvent,
67
+ UrlSource as AGUIUrlSource,
68
+ VideoPart as AGUIVideoPart,
48
69
  EventType,
49
70
  } from '@ag-ui/core'
50
71
  import type {
51
72
  SpecTokenUsage,
52
73
  TokenUsageLeftover,
53
74
  } from './utilities/ag-ui-usage'
75
+ import type { SubagentWireInfo } from './utilities/subagent-wire'
54
76
 
55
77
  // Re-export ProviderTool so the type is reachable from `@tanstack/ai`'s root
56
78
  // entry via `export * from './types'` without forcing the subpath import.
@@ -163,13 +185,11 @@ export type InferSchemaType<T> =
163
185
  ? TInput
164
186
  : unknown
165
187
 
166
- export interface ToolCall<TMetadata = unknown> {
167
- id: string
168
- type: 'function'
169
- function: {
170
- name: string
171
- arguments: string // JSON string
172
- }
188
+ /** AG-UI `ToolCall` with typed metadata. `function.arguments` is a JSON string. */
189
+ export interface ToolCall<TMetadata = unknown> extends Omit<
190
+ AGUIToolCall,
191
+ 'metadata'
192
+ > {
173
193
  /** Provider-specific metadata to carry through the tool call lifecycle.
174
194
  * Typed per-adapter via `TToolCallMetadata`. For example,
175
195
  * `@tanstack/ai-gemini` sets this to `{ thoughtSignature?: string }`. */
@@ -201,106 +221,84 @@ export interface ProviderExecutedToolMetadata {
201
221
  // ============================================================================
202
222
 
203
223
  /**
204
- * Supported input modality types for multimodal content.
205
- * - 'text': Plain text content
206
- * - 'image': Image content (base64 or URL)
207
- * - 'audio': Audio content (base64 or URL)
208
- * - 'video': Video content (base64 or URL)
209
- * - 'document': Document content like PDFs (base64 or URL)
224
+ * Supported input modality types for multimodal content: the `type` of each
225
+ * AG-UI `ContentPart` (text, image, audio, video, document).
210
226
  */
211
- export type Modality = 'text' | 'image' | 'audio' | 'video' | 'document'
227
+ export type Modality = AGUIContentPart['type']
212
228
 
213
229
  /**
214
- * Source specification for inline data content (base64).
215
- * Requires a mimeType to ensure providers receive proper content type information.
230
+ * Inline base64 content. AG-UI `DataSource`: `mimeType` is required.
216
231
  */
217
- export interface ContentPartDataSource {
218
- /**
219
- * Indicates this is inline data content.
220
- */
221
- type: 'data'
222
- /**
223
- * The base64-encoded content value.
224
- */
225
- value: string
226
- /**
227
- * The MIME type of the content (e.g., 'image/png', 'audio/wav').
228
- * Required for data sources to ensure proper handling by providers.
229
- */
230
- mimeType: string
231
- }
232
+ export interface ContentPartDataSource extends AGUIDataSource {}
232
233
 
233
234
  /**
234
- * Source specification for URL-based content.
235
- * mimeType is optional as it can often be inferred from the URL or response headers.
235
+ * URL-referenced content. AG-UI `UrlSource`: `mimeType` is optional.
236
236
  */
237
- export interface ContentPartUrlSource {
238
- /**
239
- * Indicates this is URL-referenced content.
240
- */
241
- type: 'url'
242
- /**
243
- * HTTP(S) URL or data URI pointing to the content.
244
- */
245
- value: string
237
+ export interface ContentPartUrlSource extends AGUIUrlSource {}
238
+
239
+ /**
240
+ * A provider-issued file handle (Files API). AG-UI `FileSource`: the handle
241
+ * is opaque, do not fetch or parse it.
242
+ *
243
+ * The media is uploaded once via a `files` adapter (`openaiFiles()`,
244
+ * `anthropicFiles()`, `geminiFiles()`, `grokFiles()`, `falFiles()`) and
245
+ * referenced here by the returned handle instead of re-sending base64 or a
246
+ * public URL on each request. Only the provider that minted a handle can
247
+ * resolve it. Adapters that cannot consume file handles at all are rejected
248
+ * by the activity-layer preflight before mapping starts.
249
+ */
250
+ export interface ContentPartFileSource<
251
+ TProvider extends string = string,
252
+ > extends AGUIFileSource {
246
253
  /**
247
- * Optional MIME type hint for cases where providers can't infer it from the URL.
254
+ * The adapter name of the provider that issued the handle (`'openai'`,
255
+ * `'gemini'`, ...), the same id TanStack reports as the usage provider.
256
+ * When present, an adapter rejects a handle another provider issued.
248
257
  */
249
- mimeType?: string
258
+ provider?: TProvider
250
259
  }
251
260
 
252
261
  /**
253
- * Source specification for multimodal content.
254
- * Discriminated union supporting both inline data (base64) and URL-based content.
255
- * - For 'data' sources: mimeType is required
256
- * - For 'url' sources: mimeType is optional
262
+ * Where a media part's bytes come from: inline data, a URL, or a provider
263
+ * file handle. Same members as AG-UI `PartSource`.
257
264
  */
258
- export type ContentPartSource = ContentPartDataSource | ContentPartUrlSource
265
+ export type ContentPartSource =
266
+ | ContentPartDataSource
267
+ | ContentPartUrlSource
268
+ | ContentPartFileSource
259
269
 
260
270
  /**
261
- * Image content part for multimodal messages.
271
+ * Image content part for multimodal messages. AG-UI `ImagePart` with typed metadata.
262
272
  * @template TMetadata - Provider-specific metadata type (e.g., OpenAI's detail level)
263
273
  */
264
- export interface ImagePart<TMetadata = unknown> {
265
- type: 'image'
266
- /** Source of the image content */
267
- source: ContentPartSource
274
+ export interface ImagePart<TMetadata = unknown> extends AGUIImagePart {
268
275
  /** Provider-specific metadata (e.g., OpenAI's detail: 'auto' | 'low' | 'high') */
269
276
  metadata?: TMetadata
270
277
  }
271
278
 
272
279
  /**
273
- * Audio content part for multimodal messages.
280
+ * Audio content part for multimodal messages. AG-UI `AudioPart` with typed metadata.
274
281
  * @template TMetadata - Provider-specific metadata type
275
282
  */
276
- export interface AudioPart<TMetadata = unknown> {
277
- type: 'audio'
278
- /** Source of the audio content */
279
- source: ContentPartSource
283
+ export interface AudioPart<TMetadata = unknown> extends AGUIAudioPart {
280
284
  /** Provider-specific metadata (e.g., format, sample rate) */
281
285
  metadata?: TMetadata
282
286
  }
283
287
 
284
288
  /**
285
- * Video content part for multimodal messages.
289
+ * Video content part for multimodal messages. AG-UI `VideoPart` with typed metadata.
286
290
  * @template TMetadata - Provider-specific metadata type
287
291
  */
288
- export interface VideoPart<TMetadata = unknown> {
289
- type: 'video'
290
- /** Source of the video content */
291
- source: ContentPartSource
292
+ export interface VideoPart<TMetadata = unknown> extends AGUIVideoPart {
292
293
  /** Provider-specific metadata (e.g., duration, resolution) */
293
294
  metadata?: TMetadata
294
295
  }
295
296
 
296
297
  /**
297
- * Document content part for multimodal messages (e.g., PDFs).
298
+ * Document content part for multimodal messages (e.g., PDFs). AG-UI `DocumentPart` with typed metadata.
298
299
  * @template TMetadata - Provider-specific metadata type (e.g., Anthropic's media_type)
299
300
  */
300
- export interface DocumentPart<TMetadata = unknown> {
301
- type: 'document'
302
- /** Source of the document content */
303
- source: ContentPartSource
301
+ export interface DocumentPart<TMetadata = unknown> extends AGUIDocumentPart {
304
302
  /** Provider-specific metadata (e.g., media_type for PDFs) */
305
303
  metadata?: TMetadata
306
304
  }
@@ -492,6 +490,37 @@ export interface StructuredOutputPart<TData = unknown> {
492
490
  errorMessage?: string
493
491
  }
494
492
 
493
+ export type SubagentStatus = 'running' | 'finished' | 'error' | 'suspended'
494
+
495
+ /**
496
+ * One child invocation as the client sees it. AG-UI `SubagentInfo` names the
497
+ * child; the other AG-UI fields come from its `SUBAGENT_STARTED`,
498
+ * `SUBAGENT_FINISHED` and `SUBAGENT_ERROR` events. `id` is the AG-UI
499
+ * `subagentRunId`. `status`, `parentRunId` and `messages` are client state the
500
+ * spec does not model.
501
+ */
502
+ export interface SubagentHandleData
503
+ extends
504
+ AGUISubagentInfo,
505
+ Pick<
506
+ AGUISubagentStartedEvent,
507
+ 'parentSubagentRunId' | 'parentToolCallId' | 'metadata'
508
+ > {
509
+ id: AGUISubagentRunId
510
+ status: SubagentStatus
511
+ /** The parent chat run that started this child. */
512
+ parentRunId?: string
513
+ /** Interrupts this child raised, while `status` is `'suspended'`. */
514
+ interruptIds?: AGUISubagentFinishedSuspendedOutcome['interruptIds']
515
+ messages: Array<UIMessage>
516
+ error?: Pick<AGUISubagentErrorEvent, 'message' | 'code'>
517
+ }
518
+
519
+ export interface SubagentPart {
520
+ type: 'subagent'
521
+ subagent: SubagentHandleData
522
+ }
523
+
495
524
  export interface UIResourcePart {
496
525
  type: 'ui-resource'
497
526
  /** The ui:// resource object in MCP-native shape — fed straight to the renderer. */
@@ -520,6 +549,7 @@ export type MessagePart<TData = unknown> =
520
549
  | ThinkingPart
521
550
  | StructuredOutputPart<TData>
522
551
  | UIResourcePart
552
+ | SubagentPart
523
553
 
524
554
  /**
525
555
  * Shape of `metadata.tanstack` on a message.
@@ -528,6 +558,10 @@ export type MessagePart<TData = unknown> =
528
558
  export interface TanStackMessageMetadata {
529
559
  createdAt?: string
530
560
  model?: string
561
+ /** Parent chat run that produced this assistant message. */
562
+ runId?: string
563
+ /** Card data on a child wire message. See `uiMessagesToWire`. */
564
+ subagent?: SubagentWireInfo
531
565
  /** Thinking signature for a `role: 'reasoning'` fan-out message. */
532
566
  signature?: string
533
567
  /** Per-tool-call provider metadata keyed by tool call id (e.g. Gemini thoughtSignature). */
@@ -1113,6 +1147,12 @@ export interface TextOptions<
1113
1147
  * Surfaced for observability/middleware; not consumed by the LLM call.
1114
1148
  */
1115
1149
  parentRunId?: string
1150
+ /**
1151
+ * AG-UI subagent run id when this chat runs as a child of another run.
1152
+ * A child `chat()` passes `ctx.subagentRunId`. Middleware reads it as
1153
+ * `ctx.subagentRunId`. Absent on a top-level run.
1154
+ */
1155
+ subagentRunId?: string
1116
1156
 
1117
1157
  /** Application state mirrored in a STATE_SNAPSHOT before an interrupt terminal. */
1118
1158
  state?: unknown
@@ -1285,15 +1325,12 @@ export interface TextMessageEndEvent extends AGUITextMessageEndEvent {}
1285
1325
  /**
1286
1326
  * Emitted when a tool call starts.
1287
1327
  *
1288
- * @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId?`
1289
- *
1290
- * Field shapes are taken from AG-UI via `Pick` (not `extends`) so Zod
1291
- * `.passthrough()` index signatures do not pollute the StreamChunk
1292
- * discriminated union — required for {@link KnownCustomEvent} narrowing.
1328
+ * @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId?`,
1329
+ * `subagentRunId?`
1293
1330
  */
1294
- export interface ToolCallStartEvent extends Pick<
1331
+ export interface ToolCallStartEvent extends Omit<
1295
1332
  AGUIToolCallStartEvent,
1296
- 'toolCallId' | 'toolCallName' | 'parentMessageId' | 'timestamp' | 'rawEvent'
1333
+ 'type'
1297
1334
  > {
1298
1335
  type: 'TOOL_CALL_START'
1299
1336
  /** Alias of `toolCallName`. Kept so existing stream readers still compile. */
@@ -1312,14 +1349,9 @@ export interface ToolCallArgsEvent extends AGUIToolCallArgsEvent {}
1312
1349
  /**
1313
1350
  * Emitted when a tool call completes.
1314
1351
  *
1315
- * @ag-ui/core provides: `toolCallId`
1316
- *
1317
- * Same `Pick` (not `extends`) rationale as {@link ToolCallStartEvent}.
1352
+ * @ag-ui/core provides: `toolCallId`, `subagentRunId?`
1318
1353
  */
1319
- export interface ToolCallEndEvent extends Pick<
1320
- AGUIToolCallEndEvent,
1321
- 'toolCallId' | 'timestamp' | 'rawEvent'
1322
- > {
1354
+ export interface ToolCallEndEvent extends Omit<AGUIToolCallEndEvent, 'type'> {
1323
1355
  type: 'TOOL_CALL_END'
1324
1356
  /** Parsed tool arguments when the adapter already parsed them. */
1325
1357
  input?: unknown
@@ -1377,15 +1409,9 @@ export interface StateDeltaEvent extends AGUIStateDeltaEvent {}
1377
1409
  /**
1378
1410
  * Custom event for extensibility.
1379
1411
  *
1380
- * @ag-ui/core provides: `name`, `value`
1381
- *
1382
- * Uses `Pick` (not `extends`) so the Zod passthrough index signature does not
1383
- * erase discriminant property access on {@link KnownCustomEvent} unions.
1412
+ * @ag-ui/core provides: `name`, `value`, `subagentRunId?`
1384
1413
  */
1385
- export interface CustomEvent extends Pick<
1386
- AGUICustomEvent,
1387
- 'name' | 'value' | 'timestamp' | 'rawEvent'
1388
- > {
1414
+ export interface CustomEvent extends Omit<AGUICustomEvent, 'type'> {
1389
1415
  type: 'CUSTOM'
1390
1416
  metadata?: Record<string, any>
1391
1417
  }
@@ -1671,6 +1697,24 @@ export interface ReasoningEndEvent extends AGUIReasoningEndEvent {}
1671
1697
  */
1672
1698
  export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValueEvent {}
1673
1699
 
1700
+ /** AG-UI 1.0 ActivitySnapshotEvent shape. */
1701
+ export interface ActivitySnapshotEvent extends AGUIActivitySnapshotEvent {}
1702
+
1703
+ /** AG-UI 1.0 ActivityDeltaEvent shape. */
1704
+ export interface ActivityDeltaEvent extends AGUIActivityDeltaEvent {}
1705
+
1706
+ /** AG-UI 1.0 RawEvent shape. */
1707
+ export interface RawEvent extends AGUIRawEvent {}
1708
+
1709
+ /** AG-UI 1.0 TextMessageChunkEvent shape. */
1710
+ export interface TextMessageChunkEvent extends AGUITextMessageChunkEvent {}
1711
+
1712
+ /** AG-UI 1.0 ToolCallChunkEvent shape. */
1713
+ export interface ToolCallChunkEvent extends AGUIToolCallChunkEvent {}
1714
+
1715
+ /** AG-UI 1.0 ReasoningMessageChunkEvent shape. */
1716
+ export interface ReasoningMessageChunkEvent extends AGUIReasoningMessageChunkEvent {}
1717
+
1674
1718
  // ============================================================================
1675
1719
  // AG-UI Event Union
1676
1720
  // ============================================================================
@@ -1679,6 +1723,12 @@ export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValu
1679
1723
  * Union of all AG-UI events.
1680
1724
  */
1681
1725
  export type AGUIEvent =
1726
+ | ActivitySnapshotEvent
1727
+ | ActivityDeltaEvent
1728
+ | RawEvent
1729
+ | TextMessageChunkEvent
1730
+ | ToolCallChunkEvent
1731
+ | ReasoningMessageChunkEvent
1682
1732
  | RunStartedEvent
1683
1733
  | RunFinishedEvent
1684
1734
  | RunErrorEvent
@@ -1701,6 +1751,32 @@ export type AGUIEvent =
1701
1751
  | ReasoningMessageEndEvent
1702
1752
  | ReasoningEndEvent
1703
1753
  | ReasoningEncryptedValueEvent
1754
+ | SubagentStartedEvent
1755
+ | SubagentFinishedEvent
1756
+ | SubagentErrorEvent
1757
+
1758
+ /**
1759
+ * A child agent started. The later chunks for that child carry the same
1760
+ * `subagentRunId`.
1761
+ *
1762
+ * @ag-ui/core provides: `subagentRunId`, `name`, `description?`,
1763
+ * `parentSubagentRunId?`, `parentToolCallId?`, `parentMessageId?`, `metadata?`
1764
+ */
1765
+ export interface SubagentStartedEvent extends AGUISubagentStartedEvent {}
1766
+
1767
+ /**
1768
+ * A child agent's segment of this run ended.
1769
+ *
1770
+ * @ag-ui/core provides: `subagentRunId`, `result?`, `outcome?`
1771
+ */
1772
+ export interface SubagentFinishedEvent extends AGUISubagentFinishedEvent {}
1773
+
1774
+ /**
1775
+ * A child agent failed. The parent run can continue.
1776
+ *
1777
+ * @ag-ui/core provides: `subagentRunId`, `message`, `code?`
1778
+ */
1779
+ export interface SubagentErrorEvent extends AGUISubagentErrorEvent {}
1704
1780
 
1705
1781
  /**
1706
1782
  * Chunk returned by the SDK during streaming chat completions.
@@ -2245,7 +2321,7 @@ export interface VideoUrlResult {
2245
2321
  // ============================================================================
2246
2322
 
2247
2323
  /**
2248
- * Options for world generation (live, prompt-steerable sessions).
2324
+ * Options for world generation (live session or finished job).
2249
2325
  *
2250
2326
  * @experimental World generation is an experimental feature and may change.
2251
2327
  */
@@ -2257,8 +2333,10 @@ export interface WorldGenerationOptions<
2257
2333
  /** Natural-language description of the world or scene */
2258
2334
  prompt: string
2259
2335
  /**
2260
- * Provider mint options. Reactor resolution/seed/audio are browser
2261
- * `sendCommand` fields, not token-mint fields.
2336
+ * Provider-specific options. Live adapters (Reactor) use mint fields here.
2337
+ * Job adapters (World Labs) use image/video inputs, `wait`, and poll.
2338
+ * Reactor resolution/seed/audio are browser `sendCommand` fields, not
2339
+ * token-mint fields.
2262
2340
  */
2263
2341
  modelOptions?: TProviderOptions
2264
2342
  /**
@@ -2275,28 +2353,73 @@ export interface WorldGenerationOptions<
2275
2353
  abortSignal?: AbortSignal
2276
2354
  }
2277
2355
 
2356
+ /**
2357
+ * Assets from a finished world job. Live session adapters omit this.
2358
+ * URLs are often signed CDN links. They can expire and may need a proxy
2359
+ * to fetch from a browser.
2360
+ *
2361
+ * @experimental World generation is an experimental feature and may change.
2362
+ */
2363
+ export interface WorldGenerationAssets {
2364
+ /** Auto-generated scene description */
2365
+ caption?: string
2366
+ /** Preview image URL */
2367
+ thumbnailUrl?: string
2368
+ splats?: {
2369
+ /** Quality-key map of splat URLs (`100k`, `500k`, `full_res`, …) */
2370
+ spzUrls?: Record<string, string>
2371
+ metricScaleFactor?: number
2372
+ groundPlaneOffset?: number
2373
+ }
2374
+ mesh?: {
2375
+ colliderMeshUrl?: string
2376
+ hqMeshUrl?: string
2377
+ fullResMeshUrl?: string
2378
+ }
2379
+ imagery?: {
2380
+ panoUrl?: string
2381
+ }
2382
+ }
2383
+
2278
2384
  /**
2279
2385
  * Result of world generation. JSON-serializable so a server route can return
2280
- * it to a browser. The browser uses `token` + `model` to open the live
2281
- * session (set the prompt, start streaming, steer mid-run).
2386
+ * it to a browser.
2387
+ *
2388
+ * Live adapters (Reactor): `status: 'ready'` with `token` and token
2389
+ * `expiresAt`. The browser uses `token` + `model` to open the session.
2390
+ *
2391
+ * Job adapters (World Labs): `status: 'ready'` with viewer `url` and
2392
+ * `worldId`, or `status: 'waiting'` with `operationId` and no `url`.
2393
+ * `expiresAt` on a job is operation expiry, not a session token.
2282
2394
  *
2283
2395
  * @experimental World generation is an experimental feature and may change.
2284
2396
  */
2285
2397
  export interface WorldGenerationResult {
2286
2398
  /** Unique identifier for this generation */
2287
2399
  id: string
2288
- /** Model used for generation (provider connect slug) */
2400
+ /** Model used for generation (provider connect slug or model id) */
2289
2401
  model: string
2290
- /** Short-lived session token for the client connection */
2291
- token: string
2292
- /** Token expiry as milliseconds since epoch */
2293
- expiresAt: number
2294
- /** Prompt the client should send when it starts the session */
2402
+ /** Short-lived session token for a live client connection */
2403
+ token?: string
2404
+ /**
2405
+ * Expiry as milliseconds since epoch. Live adapters: session token.
2406
+ * Job adapters: operation expiry when the provider sends it.
2407
+ */
2408
+ expiresAt?: number
2409
+ /** Prompt used to generate the world, or the prompt the client should send */
2295
2410
  prompt: string
2296
- /** Session status after the server half finishes */
2411
+ /** Status after the server half finishes */
2297
2412
  status: 'ready' | 'waiting'
2298
2413
  /** Provider session id, when the adapter created one */
2299
2414
  sessionId?: string
2415
+ /** Viewer URL for a finished world job (not an asset download URL) */
2416
+ url?: string
2417
+ /** Provider world id for a finished or in-progress job */
2418
+ worldId?: string
2419
+ /** Provider operation id for a long-running world job */
2420
+ operationId?: string
2421
+ /** Assets when a world job has finished and the provider returned them */
2422
+ assets?: WorldGenerationAssets
2300
2423
  /** Token usage / billing, when the adapter can report it */
2301
2424
  usage?: TokenUsage
2302
2425
  }
@@ -4,11 +4,12 @@ import type { ContentPart, StreamChunk, ToolOutputState } from '../types'
4
4
  /**
5
5
  * Adapter / engine yield before normalize. Public StreamChunk is spec-only.
6
6
  * This type still allows the old extra fields.
7
+ * Extras never override a spec field (see WithAdapterExtras).
7
8
  */
8
- export type AdapterYieldChunk = StreamChunk & {
9
+ type AdapterExtras = {
9
10
  model?: string
10
11
  finishReason?: 'stop' | 'length' | 'content_filter' | 'tool_calls' | null
11
- // `any` so TokenUsage adapter yields stay assignable after public usage[]
12
+ // `any` so TokenUsage adapter yields stay assignable after public usage[].
12
13
  usage?: any
13
14
  content?: string
14
15
  args?: string
@@ -28,3 +29,10 @@ export type AdapterYieldChunk = StreamChunk & {
28
29
  threadId?: string
29
30
  runId?: string
30
31
  }
32
+
33
+ // Preserve spec fields when an adapter extra uses the same name.
34
+ type WithAdapterExtras<T> = T extends StreamChunk
35
+ ? T & Omit<AdapterExtras, keyof T>
36
+ : never
37
+
38
+ export type AdapterYieldChunk = WithAdapterExtras<StreamChunk>
@@ -192,3 +192,41 @@ describe('rebuildTokenUsage', () => {
192
192
  })
193
193
  })
194
194
  })
195
+
196
+ it('maps cache-write usage in both directions', () => {
197
+ const usage: TokenUsage = {
198
+ promptTokens: 12,
199
+ completionTokens: 3,
200
+ totalTokens: 15,
201
+ promptTokensDetails: { cachedTokens: 4, cacheWriteTokens: 5 },
202
+ }
203
+ const wire = toSpecTokenUsage(usage)
204
+ expect(wire.usage).toEqual([
205
+ {
206
+ inputTokens: 12,
207
+ outputTokens: 3,
208
+ totalTokens: 15,
209
+ cachedInputTokens: 4,
210
+ cacheWriteInputTokens: 5,
211
+ },
212
+ ])
213
+ // Old readers only know the leftover field, so it stays there too.
214
+ expect(wire.leftover).toEqual({
215
+ promptTokensDetails: { cacheWriteTokens: 5 },
216
+ })
217
+ expect(fromSpecTokenUsage(wire.usage, wire.leftover)).toEqual(usage)
218
+ expect(fromSpecTokenUsage(wire.usage)).toEqual(usage)
219
+ })
220
+
221
+ it('sums every spec usage entry', () => {
222
+ expect(
223
+ fromSpecTokenUsage([
224
+ { inputTokens: 1, outputTokens: 2, totalTokens: 3 },
225
+ { inputTokens: 4, outputTokens: 5, totalTokens: 9 },
226
+ ]),
227
+ ).toEqual({
228
+ promptTokens: 5,
229
+ completionTokens: 7,
230
+ totalTokens: 12,
231
+ })
232
+ })