@tanstack/ai 0.58.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 +337 -13
- 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 +47 -1
- 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 +54 -5
- 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 +6 -3
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/types.d.ts +110 -88
- 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/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 +2 -2
- 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 +529 -11
- 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 +47 -0
- package/src/activities/chat/stream/processor.ts +428 -8
- package/src/activities/chat/tools/tool-calls.ts +77 -11
- 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/types.ts +154 -94
- 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/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). */
|
|
@@ -1113,6 +1131,12 @@ export interface TextOptions<
|
|
|
1113
1131
|
* Surfaced for observability/middleware; not consumed by the LLM call.
|
|
1114
1132
|
*/
|
|
1115
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
|
|
1116
1140
|
|
|
1117
1141
|
/** Application state mirrored in a STATE_SNAPSHOT before an interrupt terminal. */
|
|
1118
1142
|
state?: unknown
|
|
@@ -1285,15 +1309,12 @@ export interface TextMessageEndEvent extends AGUITextMessageEndEvent {}
|
|
|
1285
1309
|
/**
|
|
1286
1310
|
* Emitted when a tool call starts.
|
|
1287
1311
|
*
|
|
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.
|
|
1312
|
+
* @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId?`,
|
|
1313
|
+
* `subagentRunId?`
|
|
1293
1314
|
*/
|
|
1294
|
-
export interface ToolCallStartEvent extends
|
|
1315
|
+
export interface ToolCallStartEvent extends Omit<
|
|
1295
1316
|
AGUIToolCallStartEvent,
|
|
1296
|
-
'
|
|
1317
|
+
'type'
|
|
1297
1318
|
> {
|
|
1298
1319
|
type: 'TOOL_CALL_START'
|
|
1299
1320
|
/** Alias of `toolCallName`. Kept so existing stream readers still compile. */
|
|
@@ -1312,14 +1333,9 @@ export interface ToolCallArgsEvent extends AGUIToolCallArgsEvent {}
|
|
|
1312
1333
|
/**
|
|
1313
1334
|
* Emitted when a tool call completes.
|
|
1314
1335
|
*
|
|
1315
|
-
* @ag-ui/core provides: `toolCallId`
|
|
1316
|
-
*
|
|
1317
|
-
* Same `Pick` (not `extends`) rationale as {@link ToolCallStartEvent}.
|
|
1336
|
+
* @ag-ui/core provides: `toolCallId`, `subagentRunId?`
|
|
1318
1337
|
*/
|
|
1319
|
-
export interface ToolCallEndEvent extends
|
|
1320
|
-
AGUIToolCallEndEvent,
|
|
1321
|
-
'toolCallId' | 'timestamp' | 'rawEvent'
|
|
1322
|
-
> {
|
|
1338
|
+
export interface ToolCallEndEvent extends Omit<AGUIToolCallEndEvent, 'type'> {
|
|
1323
1339
|
type: 'TOOL_CALL_END'
|
|
1324
1340
|
/** Parsed tool arguments when the adapter already parsed them. */
|
|
1325
1341
|
input?: unknown
|
|
@@ -1377,15 +1393,9 @@ export interface StateDeltaEvent extends AGUIStateDeltaEvent {}
|
|
|
1377
1393
|
/**
|
|
1378
1394
|
* Custom event for extensibility.
|
|
1379
1395
|
*
|
|
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.
|
|
1396
|
+
* @ag-ui/core provides: `name`, `value`, `subagentRunId?`
|
|
1384
1397
|
*/
|
|
1385
|
-
export interface CustomEvent extends
|
|
1386
|
-
AGUICustomEvent,
|
|
1387
|
-
'name' | 'value' | 'timestamp' | 'rawEvent'
|
|
1388
|
-
> {
|
|
1398
|
+
export interface CustomEvent extends Omit<AGUICustomEvent, 'type'> {
|
|
1389
1399
|
type: 'CUSTOM'
|
|
1390
1400
|
metadata?: Record<string, any>
|
|
1391
1401
|
}
|
|
@@ -1671,6 +1681,24 @@ export interface ReasoningEndEvent extends AGUIReasoningEndEvent {}
|
|
|
1671
1681
|
*/
|
|
1672
1682
|
export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValueEvent {}
|
|
1673
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
|
+
|
|
1674
1702
|
// ============================================================================
|
|
1675
1703
|
// AG-UI Event Union
|
|
1676
1704
|
// ============================================================================
|
|
@@ -1679,6 +1707,12 @@ export interface ReasoningEncryptedValueEvent extends AGUIReasoningEncryptedValu
|
|
|
1679
1707
|
* Union of all AG-UI events.
|
|
1680
1708
|
*/
|
|
1681
1709
|
export type AGUIEvent =
|
|
1710
|
+
| ActivitySnapshotEvent
|
|
1711
|
+
| ActivityDeltaEvent
|
|
1712
|
+
| RawEvent
|
|
1713
|
+
| TextMessageChunkEvent
|
|
1714
|
+
| ToolCallChunkEvent
|
|
1715
|
+
| ReasoningMessageChunkEvent
|
|
1682
1716
|
| RunStartedEvent
|
|
1683
1717
|
| RunFinishedEvent
|
|
1684
1718
|
| RunErrorEvent
|
|
@@ -1701,6 +1735,32 @@ export type AGUIEvent =
|
|
|
1701
1735
|
| ReasoningMessageEndEvent
|
|
1702
1736
|
| ReasoningEndEvent
|
|
1703
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 {}
|
|
1704
1764
|
|
|
1705
1765
|
/**
|
|
1706
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({
|