@tanstack/ai 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/activities/chat/agents/define-agent.d.ts +81 -0
- package/dist/esm/activities/chat/agents/define-agent.js +34 -0
- package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
- package/dist/esm/activities/chat/agents/route.d.ts +53 -0
- package/dist/esm/activities/chat/agents/route.js +59 -0
- package/dist/esm/activities/chat/agents/route.js.map +1 -0
- package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
- package/dist/esm/activities/chat/agents/spawn.js +490 -0
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
- package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
- package/dist/esm/activities/chat/agents/turn.js +78 -0
- package/dist/esm/activities/chat/agents/turn.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +13 -3
- package/dist/esm/activities/chat/index.js +345 -19
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +7 -1
- package/dist/esm/activities/chat/messages.js +94 -18
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
- package/dist/esm/activities/chat/middleware/run-store.js +8 -1
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +50 -3
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -0
- package/dist/esm/activities/chat/stream/processor.js +280 -7
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
- package/dist/esm/activities/chat/tools/tool-calls.js +56 -7
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/index.js +1 -1
- package/dist/esm/activities/generateLiveVideo/index.js +1 -1
- package/dist/esm/activities/generateSpeech/index.js +1 -1
- package/dist/esm/activities/generateTranscription/index.js +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/index.js +1 -1
- package/dist/esm/activities/index.d.ts +3 -0
- package/dist/esm/activities/index.js +5 -3
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +5 -36
- package/dist/esm/client.js +4 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +7 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/stream-to-response.js +12 -6
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +2 -1
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/types.d.ts +128 -89
- package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
- package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
- package/dist/esm/utilities/ag-ui-usage.js +66 -3
- package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
- package/dist/esm/utilities/ag-ui-wire.js +56 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/durability-batch.d.ts +8 -0
- package/dist/esm/utilities/durability-batch.js +45 -0
- package/dist/esm/utilities/durability-batch.js.map +1 -0
- package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
- package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
- package/dist/esm/utilities/spec-event-keys.js +13 -8
- package/dist/esm/utilities/spec-event-keys.js.map +1 -1
- package/dist/esm/utilities/subagent-wire.d.ts +36 -0
- package/dist/esm/utilities/subagent-wire.js +131 -0
- package/dist/esm/utilities/subagent-wire.js.map +1 -0
- package/package.json +4 -4
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/media-generation/SKILL.md +2 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/agents/define-agent.ts +121 -0
- package/src/activities/chat/agents/route.ts +115 -0
- package/src/activities/chat/agents/spawn.ts +806 -0
- package/src/activities/chat/agents/turn.ts +151 -0
- package/src/activities/chat/index.ts +540 -16
- package/src/activities/chat/messages.ts +125 -15
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +55 -2
- package/src/activities/chat/stream/processor.ts +428 -8
- package/src/activities/chat/tools/tool-calls.ts +92 -16
- package/src/activities/index.ts +15 -0
- package/src/client.ts +22 -35
- package/src/index.ts +23 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/stream-to-response.ts +16 -6
- package/src/strip-to-spec-middleware.ts +2 -1
- package/src/types.ts +177 -95
- package/src/utilities/adapter-yield-chunk.ts +10 -2
- package/src/utilities/ag-ui-usage.test.ts +38 -0
- package/src/utilities/ag-ui-usage.ts +98 -11
- package/src/utilities/ag-ui-wire.ts +74 -0
- package/src/utilities/durability-batch.ts +48 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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,68 @@ export interface ProviderExecutedToolMetadata {
|
|
|
201
221
|
// ============================================================================
|
|
202
222
|
|
|
203
223
|
/**
|
|
204
|
-
* Supported input modality types for multimodal content
|
|
205
|
-
* -
|
|
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 = '
|
|
227
|
+
export type Modality = AGUIContentPart['type']
|
|
212
228
|
|
|
213
229
|
/**
|
|
214
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
*/
|
|
245
|
-
value: string
|
|
246
|
-
/**
|
|
247
|
-
* Optional MIME type hint for cases where providers can't infer it from the URL.
|
|
248
|
-
*/
|
|
249
|
-
mimeType?: string
|
|
250
|
-
}
|
|
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
|
+
export interface ContentPartFileSource extends AGUIFileSource {}
|
|
251
244
|
|
|
252
245
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* - For 'data' sources: mimeType is required
|
|
256
|
-
* - For 'url' sources: mimeType is optional
|
|
246
|
+
* Where a media part's bytes come from: inline data, a URL, or a provider
|
|
247
|
+
* file handle. Same members as AG-UI `PartSource`.
|
|
257
248
|
*/
|
|
258
|
-
export type ContentPartSource =
|
|
249
|
+
export type ContentPartSource =
|
|
250
|
+
| ContentPartDataSource
|
|
251
|
+
| ContentPartUrlSource
|
|
252
|
+
| ContentPartFileSource
|
|
259
253
|
|
|
260
254
|
/**
|
|
261
|
-
* Image content part for multimodal messages.
|
|
255
|
+
* Image content part for multimodal messages. AG-UI `ImagePart` with typed metadata.
|
|
262
256
|
* @template TMetadata - Provider-specific metadata type (e.g., OpenAI's detail level)
|
|
263
257
|
*/
|
|
264
|
-
export interface ImagePart<TMetadata = unknown> {
|
|
265
|
-
type: 'image'
|
|
266
|
-
/** Source of the image content */
|
|
267
|
-
source: ContentPartSource
|
|
258
|
+
export interface ImagePart<TMetadata = unknown> extends AGUIImagePart {
|
|
268
259
|
/** Provider-specific metadata (e.g., OpenAI's detail: 'auto' | 'low' | 'high') */
|
|
269
260
|
metadata?: TMetadata
|
|
270
261
|
}
|
|
271
262
|
|
|
272
263
|
/**
|
|
273
|
-
* Audio content part for multimodal messages.
|
|
264
|
+
* Audio content part for multimodal messages. AG-UI `AudioPart` with typed metadata.
|
|
274
265
|
* @template TMetadata - Provider-specific metadata type
|
|
275
266
|
*/
|
|
276
|
-
export interface AudioPart<TMetadata = unknown> {
|
|
277
|
-
type: 'audio'
|
|
278
|
-
/** Source of the audio content */
|
|
279
|
-
source: ContentPartSource
|
|
267
|
+
export interface AudioPart<TMetadata = unknown> extends AGUIAudioPart {
|
|
280
268
|
/** Provider-specific metadata (e.g., format, sample rate) */
|
|
281
269
|
metadata?: TMetadata
|
|
282
270
|
}
|
|
283
271
|
|
|
284
272
|
/**
|
|
285
|
-
* Video content part for multimodal messages.
|
|
273
|
+
* Video content part for multimodal messages. AG-UI `VideoPart` with typed metadata.
|
|
286
274
|
* @template TMetadata - Provider-specific metadata type
|
|
287
275
|
*/
|
|
288
|
-
export interface VideoPart<TMetadata = unknown> {
|
|
289
|
-
type: 'video'
|
|
290
|
-
/** Source of the video content */
|
|
291
|
-
source: ContentPartSource
|
|
276
|
+
export interface VideoPart<TMetadata = unknown> extends AGUIVideoPart {
|
|
292
277
|
/** Provider-specific metadata (e.g., duration, resolution) */
|
|
293
278
|
metadata?: TMetadata
|
|
294
279
|
}
|
|
295
280
|
|
|
296
281
|
/**
|
|
297
|
-
* Document content part for multimodal messages (e.g., PDFs).
|
|
282
|
+
* Document content part for multimodal messages (e.g., PDFs). AG-UI `DocumentPart` with typed metadata.
|
|
298
283
|
* @template TMetadata - Provider-specific metadata type (e.g., Anthropic's media_type)
|
|
299
284
|
*/
|
|
300
|
-
export interface DocumentPart<TMetadata = unknown> {
|
|
301
|
-
type: 'document'
|
|
302
|
-
/** Source of the document content */
|
|
303
|
-
source: ContentPartSource
|
|
285
|
+
export interface DocumentPart<TMetadata = unknown> extends AGUIDocumentPart {
|
|
304
286
|
/** Provider-specific metadata (e.g., media_type for PDFs) */
|
|
305
287
|
metadata?: TMetadata
|
|
306
288
|
}
|
|
@@ -492,6 +474,37 @@ export interface StructuredOutputPart<TData = unknown> {
|
|
|
492
474
|
errorMessage?: string
|
|
493
475
|
}
|
|
494
476
|
|
|
477
|
+
export type SubagentStatus = 'running' | 'finished' | 'error' | 'suspended'
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* One child invocation as the client sees it. AG-UI `SubagentInfo` names the
|
|
481
|
+
* child; the other AG-UI fields come from its `SUBAGENT_STARTED`,
|
|
482
|
+
* `SUBAGENT_FINISHED` and `SUBAGENT_ERROR` events. `id` is the AG-UI
|
|
483
|
+
* `subagentRunId`. `status`, `parentRunId` and `messages` are client state the
|
|
484
|
+
* spec does not model.
|
|
485
|
+
*/
|
|
486
|
+
export interface SubagentHandleData
|
|
487
|
+
extends
|
|
488
|
+
AGUISubagentInfo,
|
|
489
|
+
Pick<
|
|
490
|
+
AGUISubagentStartedEvent,
|
|
491
|
+
'parentSubagentRunId' | 'parentToolCallId' | 'metadata'
|
|
492
|
+
> {
|
|
493
|
+
id: AGUISubagentRunId
|
|
494
|
+
status: SubagentStatus
|
|
495
|
+
/** The parent chat run that started this child. */
|
|
496
|
+
parentRunId?: string
|
|
497
|
+
/** Interrupts this child raised, while `status` is `'suspended'`. */
|
|
498
|
+
interruptIds?: AGUISubagentFinishedSuspendedOutcome['interruptIds']
|
|
499
|
+
messages: Array<UIMessage>
|
|
500
|
+
error?: Pick<AGUISubagentErrorEvent, 'message' | 'code'>
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export interface SubagentPart {
|
|
504
|
+
type: 'subagent'
|
|
505
|
+
subagent: SubagentHandleData
|
|
506
|
+
}
|
|
507
|
+
|
|
495
508
|
export interface UIResourcePart {
|
|
496
509
|
type: 'ui-resource'
|
|
497
510
|
/** The ui:// resource object in MCP-native shape — fed straight to the renderer. */
|
|
@@ -520,6 +533,7 @@ export type MessagePart<TData = unknown> =
|
|
|
520
533
|
| ThinkingPart
|
|
521
534
|
| StructuredOutputPart<TData>
|
|
522
535
|
| UIResourcePart
|
|
536
|
+
| SubagentPart
|
|
523
537
|
|
|
524
538
|
/**
|
|
525
539
|
* Shape of `metadata.tanstack` on a message.
|
|
@@ -528,6 +542,10 @@ export type MessagePart<TData = unknown> =
|
|
|
528
542
|
export interface TanStackMessageMetadata {
|
|
529
543
|
createdAt?: string
|
|
530
544
|
model?: string
|
|
545
|
+
/** Parent chat run that produced this assistant message. */
|
|
546
|
+
runId?: string
|
|
547
|
+
/** Card data on a child wire message. See `uiMessagesToWire`. */
|
|
548
|
+
subagent?: SubagentWireInfo
|
|
531
549
|
/** Thinking signature for a `role: 'reasoning'` fan-out message. */
|
|
532
550
|
signature?: string
|
|
533
551
|
/** Per-tool-call provider metadata keyed by tool call id (e.g. Gemini thoughtSignature). */
|
|
@@ -629,6 +647,22 @@ type RuntimeContextField<TContext> =
|
|
|
629
647
|
context: TContext
|
|
630
648
|
}
|
|
631
649
|
|
|
650
|
+
/**
|
|
651
|
+
* Options for a single `emitCustomEvent` call, on both the tool-execution and
|
|
652
|
+
* middleware contexts.
|
|
653
|
+
*/
|
|
654
|
+
export interface EmitCustomEventOptions {
|
|
655
|
+
/**
|
|
656
|
+
* Keep this event in the durability batch with later chunks.
|
|
657
|
+
* CUSTOM events flush as soon as they are emitted, so a progress
|
|
658
|
+
* indicator can render at emit time. Pass `{ batch: true }` for a
|
|
659
|
+
* high-volume stream that should share appends with later output.
|
|
660
|
+
* `process.stdout`, `process.stderr`, `sandbox.file`, and
|
|
661
|
+
* `sandbox.file.diff` already batch.
|
|
662
|
+
*/
|
|
663
|
+
batch?: boolean
|
|
664
|
+
}
|
|
665
|
+
|
|
632
666
|
/**
|
|
633
667
|
* Context passed to tool execute functions, providing capabilities like
|
|
634
668
|
* emitting custom events during execution.
|
|
@@ -649,6 +683,8 @@ export type ToolExecutionContext<TContext = unknown> =
|
|
|
649
683
|
*
|
|
650
684
|
* @param eventName - Name of the custom event
|
|
651
685
|
* @param value - Event payload value
|
|
686
|
+
* @param options - Pass `{ batch: true }` to keep this event in the
|
|
687
|
+
* durability batch instead of flushing it immediately
|
|
652
688
|
*
|
|
653
689
|
* @example
|
|
654
690
|
* ```ts
|
|
@@ -661,7 +697,11 @@ export type ToolExecutionContext<TContext = unknown> =
|
|
|
661
697
|
* })
|
|
662
698
|
* ```
|
|
663
699
|
*/
|
|
664
|
-
emitCustomEvent: (
|
|
700
|
+
emitCustomEvent: (
|
|
701
|
+
eventName: string,
|
|
702
|
+
value: Record<string, any>,
|
|
703
|
+
options?: EmitCustomEventOptions,
|
|
704
|
+
) => void
|
|
665
705
|
}
|
|
666
706
|
|
|
667
707
|
export type ToolExecuteFunction<
|
|
@@ -1091,6 +1131,12 @@ export interface TextOptions<
|
|
|
1091
1131
|
* Surfaced for observability/middleware; not consumed by the LLM call.
|
|
1092
1132
|
*/
|
|
1093
1133
|
parentRunId?: string
|
|
1134
|
+
/**
|
|
1135
|
+
* AG-UI subagent run id when this chat runs as a child of another run.
|
|
1136
|
+
* A child `chat()` passes `ctx.subagentRunId`. Middleware reads it as
|
|
1137
|
+
* `ctx.subagentRunId`. Absent on a top-level run.
|
|
1138
|
+
*/
|
|
1139
|
+
subagentRunId?: string
|
|
1094
1140
|
|
|
1095
1141
|
/** Application state mirrored in a STATE_SNAPSHOT before an interrupt terminal. */
|
|
1096
1142
|
state?: unknown
|
|
@@ -1263,15 +1309,12 @@ export interface TextMessageEndEvent extends AGUITextMessageEndEvent {}
|
|
|
1263
1309
|
/**
|
|
1264
1310
|
* Emitted when a tool call starts.
|
|
1265
1311
|
*
|
|
1266
|
-
* @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId
|
|
1267
|
-
*
|
|
1268
|
-
* Field shapes are taken from AG-UI via `Pick` (not `extends`) so Zod
|
|
1269
|
-
* `.passthrough()` index signatures do not pollute the StreamChunk
|
|
1270
|
-
* discriminated union — required for {@link KnownCustomEvent} narrowing.
|
|
1312
|
+
* @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId?`,
|
|
1313
|
+
* `subagentRunId?`
|
|
1271
1314
|
*/
|
|
1272
|
-
export interface ToolCallStartEvent extends
|
|
1315
|
+
export interface ToolCallStartEvent extends Omit<
|
|
1273
1316
|
AGUIToolCallStartEvent,
|
|
1274
|
-
'
|
|
1317
|
+
'type'
|
|
1275
1318
|
> {
|
|
1276
1319
|
type: 'TOOL_CALL_START'
|
|
1277
1320
|
/** Alias of `toolCallName`. Kept so existing stream readers still compile. */
|
|
@@ -1290,14 +1333,9 @@ export interface ToolCallArgsEvent extends AGUIToolCallArgsEvent {}
|
|
|
1290
1333
|
/**
|
|
1291
1334
|
* Emitted when a tool call completes.
|
|
1292
1335
|
*
|
|
1293
|
-
* @ag-ui/core provides: `toolCallId`
|
|
1294
|
-
*
|
|
1295
|
-
* Same `Pick` (not `extends`) rationale as {@link ToolCallStartEvent}.
|
|
1336
|
+
* @ag-ui/core provides: `toolCallId`, `subagentRunId?`
|
|
1296
1337
|
*/
|
|
1297
|
-
export interface ToolCallEndEvent extends
|
|
1298
|
-
AGUIToolCallEndEvent,
|
|
1299
|
-
'toolCallId' | 'timestamp' | 'rawEvent'
|
|
1300
|
-
> {
|
|
1338
|
+
export interface ToolCallEndEvent extends Omit<AGUIToolCallEndEvent, 'type'> {
|
|
1301
1339
|
type: 'TOOL_CALL_END'
|
|
1302
1340
|
/** Parsed tool arguments when the adapter already parsed them. */
|
|
1303
1341
|
input?: unknown
|
|
@@ -1355,15 +1393,9 @@ export interface StateDeltaEvent extends AGUIStateDeltaEvent {}
|
|
|
1355
1393
|
/**
|
|
1356
1394
|
* Custom event for extensibility.
|
|
1357
1395
|
*
|
|
1358
|
-
* @ag-ui/core provides: `name`, `value`
|
|
1359
|
-
*
|
|
1360
|
-
* Uses `Pick` (not `extends`) so the Zod passthrough index signature does not
|
|
1361
|
-
* erase discriminant property access on {@link KnownCustomEvent} unions.
|
|
1396
|
+
* @ag-ui/core provides: `name`, `value`, `subagentRunId?`
|
|
1362
1397
|
*/
|
|
1363
|
-
export interface CustomEvent extends
|
|
1364
|
-
AGUICustomEvent,
|
|
1365
|
-
'name' | 'value' | 'timestamp' | 'rawEvent'
|
|
1366
|
-
> {
|
|
1398
|
+
export interface CustomEvent extends Omit<AGUICustomEvent, 'type'> {
|
|
1367
1399
|
type: 'CUSTOM'
|
|
1368
1400
|
metadata?: Record<string, any>
|
|
1369
1401
|
}
|
|
@@ -1649,6 +1681,24 @@ export interface ReasoningEndEvent extends AGUIReasoningEndEvent {}
|
|
|
1649
1681
|
*/
|
|
1650
1682
|
export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValueEvent {}
|
|
1651
1683
|
|
|
1684
|
+
/** AG-UI 1.0 ActivitySnapshotEvent shape. */
|
|
1685
|
+
export interface ActivitySnapshotEvent extends AGUIActivitySnapshotEvent {}
|
|
1686
|
+
|
|
1687
|
+
/** AG-UI 1.0 ActivityDeltaEvent shape. */
|
|
1688
|
+
export interface ActivityDeltaEvent extends AGUIActivityDeltaEvent {}
|
|
1689
|
+
|
|
1690
|
+
/** AG-UI 1.0 RawEvent shape. */
|
|
1691
|
+
export interface RawEvent extends AGUIRawEvent {}
|
|
1692
|
+
|
|
1693
|
+
/** AG-UI 1.0 TextMessageChunkEvent shape. */
|
|
1694
|
+
export interface TextMessageChunkEvent extends AGUITextMessageChunkEvent {}
|
|
1695
|
+
|
|
1696
|
+
/** AG-UI 1.0 ToolCallChunkEvent shape. */
|
|
1697
|
+
export interface ToolCallChunkEvent extends AGUIToolCallChunkEvent {}
|
|
1698
|
+
|
|
1699
|
+
/** AG-UI 1.0 ReasoningMessageChunkEvent shape. */
|
|
1700
|
+
export interface ReasoningMessageChunkEvent extends AGUIReasoningMessageChunkEvent {}
|
|
1701
|
+
|
|
1652
1702
|
// ============================================================================
|
|
1653
1703
|
// AG-UI Event Union
|
|
1654
1704
|
// ============================================================================
|
|
@@ -1657,6 +1707,12 @@ export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValu
|
|
|
1657
1707
|
* Union of all AG-UI events.
|
|
1658
1708
|
*/
|
|
1659
1709
|
export type AGUIEvent =
|
|
1710
|
+
| ActivitySnapshotEvent
|
|
1711
|
+
| ActivityDeltaEvent
|
|
1712
|
+
| RawEvent
|
|
1713
|
+
| TextMessageChunkEvent
|
|
1714
|
+
| ToolCallChunkEvent
|
|
1715
|
+
| ReasoningMessageChunkEvent
|
|
1660
1716
|
| RunStartedEvent
|
|
1661
1717
|
| RunFinishedEvent
|
|
1662
1718
|
| RunErrorEvent
|
|
@@ -1679,6 +1735,32 @@ export type AGUIEvent =
|
|
|
1679
1735
|
| ReasoningMessageEndEvent
|
|
1680
1736
|
| ReasoningEndEvent
|
|
1681
1737
|
| ReasoningEncryptedValueEvent
|
|
1738
|
+
| SubagentStartedEvent
|
|
1739
|
+
| SubagentFinishedEvent
|
|
1740
|
+
| SubagentErrorEvent
|
|
1741
|
+
|
|
1742
|
+
/**
|
|
1743
|
+
* A child agent started. The later chunks for that child carry the same
|
|
1744
|
+
* `subagentRunId`.
|
|
1745
|
+
*
|
|
1746
|
+
* @ag-ui/core provides: `subagentRunId`, `name`, `description?`,
|
|
1747
|
+
* `parentSubagentRunId?`, `parentToolCallId?`, `parentMessageId?`, `metadata?`
|
|
1748
|
+
*/
|
|
1749
|
+
export interface SubagentStartedEvent extends AGUISubagentStartedEvent {}
|
|
1750
|
+
|
|
1751
|
+
/**
|
|
1752
|
+
* A child agent's segment of this run ended.
|
|
1753
|
+
*
|
|
1754
|
+
* @ag-ui/core provides: `subagentRunId`, `result?`, `outcome?`
|
|
1755
|
+
*/
|
|
1756
|
+
export interface SubagentFinishedEvent extends AGUISubagentFinishedEvent {}
|
|
1757
|
+
|
|
1758
|
+
/**
|
|
1759
|
+
* A child agent failed. The parent run can continue.
|
|
1760
|
+
*
|
|
1761
|
+
* @ag-ui/core provides: `subagentRunId`, `message`, `code?`
|
|
1762
|
+
*/
|
|
1763
|
+
export interface SubagentErrorEvent extends AGUISubagentErrorEvent {}
|
|
1682
1764
|
|
|
1683
1765
|
/**
|
|
1684
1766
|
* Chunk returned by the SDK during streaming chat completions.
|
|
@@ -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
|
-
|
|
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
|
+
})
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
+
import type { TokenUsage as SpecTokenUsage } from '@ag-ui/core'
|
|
1
2
|
import type { TokenUsage } from '../types'
|
|
2
3
|
|
|
3
4
|
/** AG-UI spec `usage[]` item (provider/model labels + token counts only). */
|
|
4
|
-
export
|
|
5
|
-
provider?: string
|
|
6
|
-
model?: string
|
|
7
|
-
inputTokens?: number
|
|
8
|
-
outputTokens?: number
|
|
9
|
-
totalTokens?: number
|
|
10
|
-
reasoningTokens?: number
|
|
11
|
-
cachedInputTokens?: number
|
|
12
|
-
}
|
|
5
|
+
export type { TokenUsage as SpecTokenUsage } from '@ag-ui/core'
|
|
13
6
|
|
|
14
7
|
export interface ToSpecTokenUsageOptions {
|
|
15
8
|
provider?: string
|
|
@@ -68,11 +61,16 @@ export function toSpecTokenUsage(
|
|
|
68
61
|
if (cachedInputTokens !== undefined) {
|
|
69
62
|
spec.cachedInputTokens = cachedInputTokens
|
|
70
63
|
}
|
|
64
|
+
if (promptTokensDetails?.cacheWriteTokens !== undefined) {
|
|
65
|
+
spec.cacheWriteInputTokens = promptTokensDetails.cacheWriteTokens
|
|
66
|
+
}
|
|
71
67
|
const reasoningTokens = completionTokensDetails?.reasoningTokens
|
|
72
68
|
if (reasoningTokens !== undefined) {
|
|
73
69
|
spec.reasoningTokens = reasoningTokens
|
|
74
70
|
}
|
|
75
71
|
|
|
72
|
+
// cacheWriteTokens stays in the leftover too, so clients built before
|
|
73
|
+
// cacheWriteInputTokens existed still rebuild it.
|
|
76
74
|
const leftoverPrompt = promptTokensDetails
|
|
77
75
|
? definedDetails(withoutKey(promptTokensDetails, 'cachedTokens'))
|
|
78
76
|
: undefined
|
|
@@ -94,6 +92,80 @@ export function toSpecTokenUsage(
|
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
94
|
|
|
95
|
+
function sumNumbers<T extends object>(
|
|
96
|
+
current: T | undefined,
|
|
97
|
+
next: T | undefined,
|
|
98
|
+
): T | undefined {
|
|
99
|
+
if (!current) return next
|
|
100
|
+
if (!next) return current
|
|
101
|
+
const result = { ...current }
|
|
102
|
+
for (const key of Object.keys(next) as Array<keyof T>) {
|
|
103
|
+
const value = next[key]
|
|
104
|
+
if (typeof value !== 'number') continue
|
|
105
|
+
const previous = current[key]
|
|
106
|
+
result[key] = ((typeof previous === 'number' ? previous : 0) +
|
|
107
|
+
value) as T[keyof T]
|
|
108
|
+
}
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function sumOptional(current?: number, next?: number): number | undefined {
|
|
113
|
+
if (current === undefined) return next
|
|
114
|
+
if (next === undefined) return current
|
|
115
|
+
return current + next
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Add two usage totals, as for a parent run and its children. Numbers add
|
|
120
|
+
* up. `billed` adds up only in the same unit. `providerUsageDetails` is
|
|
121
|
+
* opaque, so the latest one stays. `@tanstack/ai-persistence` sums per-run
|
|
122
|
+
* usage with the same rules.
|
|
123
|
+
*/
|
|
124
|
+
export function addTokenUsage(
|
|
125
|
+
current: TokenUsage,
|
|
126
|
+
next: TokenUsage,
|
|
127
|
+
): TokenUsage {
|
|
128
|
+
const promptTokensDetails = sumNumbers(
|
|
129
|
+
current.promptTokensDetails,
|
|
130
|
+
next.promptTokensDetails,
|
|
131
|
+
)
|
|
132
|
+
const completionTokensDetails = sumNumbers(
|
|
133
|
+
current.completionTokensDetails,
|
|
134
|
+
next.completionTokensDetails,
|
|
135
|
+
)
|
|
136
|
+
const costDetails = sumNumbers(current.costDetails, next.costDetails)
|
|
137
|
+
const cost = sumOptional(current.cost, next.cost)
|
|
138
|
+
const durationSeconds = sumOptional(
|
|
139
|
+
current.durationSeconds,
|
|
140
|
+
next.durationSeconds,
|
|
141
|
+
)
|
|
142
|
+
const unitsBilled = sumOptional(current.unitsBilled, next.unitsBilled)
|
|
143
|
+
const billed =
|
|
144
|
+
current.billed && next.billed && current.billed.unit === next.billed.unit
|
|
145
|
+
? {
|
|
146
|
+
quantity: current.billed.quantity + next.billed.quantity,
|
|
147
|
+
unit: current.billed.unit,
|
|
148
|
+
}
|
|
149
|
+
: (next.billed ?? current.billed)
|
|
150
|
+
const providerUsageDetails =
|
|
151
|
+
next.providerUsageDetails ?? current.providerUsageDetails
|
|
152
|
+
return {
|
|
153
|
+
...current,
|
|
154
|
+
...next,
|
|
155
|
+
promptTokens: current.promptTokens + next.promptTokens,
|
|
156
|
+
completionTokens: current.completionTokens + next.completionTokens,
|
|
157
|
+
totalTokens: current.totalTokens + next.totalTokens,
|
|
158
|
+
...(promptTokensDetails && { promptTokensDetails }),
|
|
159
|
+
...(completionTokensDetails && { completionTokensDetails }),
|
|
160
|
+
...(cost !== undefined && { cost }),
|
|
161
|
+
...(costDetails && { costDetails }),
|
|
162
|
+
...(durationSeconds !== undefined && { durationSeconds }),
|
|
163
|
+
...(unitsBilled !== undefined && { unitsBilled }),
|
|
164
|
+
...(billed && { billed }),
|
|
165
|
+
...(providerUsageDetails && { providerUsageDetails }),
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
97
169
|
export function rebuildTokenUsage(
|
|
98
170
|
usage: unknown,
|
|
99
171
|
leftover?: TokenUsageLeftover,
|
|
@@ -111,8 +183,20 @@ export function fromSpecTokenUsage(
|
|
|
111
183
|
usage: ReadonlyArray<SpecTokenUsage> | undefined,
|
|
112
184
|
leftover?: TokenUsageLeftover,
|
|
113
185
|
): TokenUsage | undefined {
|
|
114
|
-
const spec = usage?.
|
|
115
|
-
|
|
186
|
+
const spec = usage?.reduce<SpecTokenUsage>((total, entry) => {
|
|
187
|
+
for (const key of [
|
|
188
|
+
'inputTokens',
|
|
189
|
+
'outputTokens',
|
|
190
|
+
'totalTokens',
|
|
191
|
+
'cachedInputTokens',
|
|
192
|
+
'cacheWriteInputTokens',
|
|
193
|
+
'reasoningTokens',
|
|
194
|
+
] as const) {
|
|
195
|
+
if (entry[key] !== undefined) total[key] = (total[key] ?? 0) + entry[key]
|
|
196
|
+
}
|
|
197
|
+
return total
|
|
198
|
+
}, {})
|
|
199
|
+
if ((usage === undefined || usage.length === 0) && leftover == null) {
|
|
116
200
|
return undefined
|
|
117
201
|
}
|
|
118
202
|
|
|
@@ -126,6 +210,9 @@ export function fromSpecTokenUsage(
|
|
|
126
210
|
...(spec?.cachedInputTokens !== undefined
|
|
127
211
|
? { cachedTokens: spec.cachedInputTokens }
|
|
128
212
|
: {}),
|
|
213
|
+
...(spec?.cacheWriteInputTokens !== undefined
|
|
214
|
+
? { cacheWriteTokens: spec.cacheWriteInputTokens }
|
|
215
|
+
: {}),
|
|
129
216
|
...leftoverPromptDetails,
|
|
130
217
|
})
|
|
131
218
|
const completionTokensDetails = definedDetails({
|