@ag-ui/core 0.1.1-canary.beta.0 → 1.0.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/index.mjs CHANGED
@@ -1,6 +1,774 @@
1
- import { t as EventType } from "./events-BaoNrGbE.mjs";
1
+ import { n as EventType, t as PROTOCOL_VERSION } from "./version-CTNE2I0_.mjs";
2
2
 
3
- //#region src/types.ts
3
+ //#region src/generated/serialization.ts
4
+ const shapes = {
5
+ TextMessageStartEvent: {
6
+ optional: [
7
+ "timestamp",
8
+ "rawEvent",
9
+ "metadata",
10
+ "subagentRunId",
11
+ "role",
12
+ "name"
13
+ ],
14
+ fields: {}
15
+ },
16
+ TextMessageContentEvent: {
17
+ optional: [
18
+ "timestamp",
19
+ "rawEvent",
20
+ "metadata",
21
+ "subagentRunId"
22
+ ],
23
+ fields: {}
24
+ },
25
+ TextMessageEndEvent: {
26
+ optional: [
27
+ "timestamp",
28
+ "rawEvent",
29
+ "metadata",
30
+ "subagentRunId"
31
+ ],
32
+ fields: {}
33
+ },
34
+ TextMessageChunkEvent: {
35
+ optional: [
36
+ "timestamp",
37
+ "rawEvent",
38
+ "metadata",
39
+ "subagentRunId",
40
+ "messageId",
41
+ "role",
42
+ "delta",
43
+ "name"
44
+ ],
45
+ fields: {}
46
+ },
47
+ ToolCallStartEvent: {
48
+ optional: [
49
+ "timestamp",
50
+ "rawEvent",
51
+ "metadata",
52
+ "subagentRunId",
53
+ "parentMessageId"
54
+ ],
55
+ fields: {}
56
+ },
57
+ ToolCallArgsEvent: {
58
+ optional: [
59
+ "timestamp",
60
+ "rawEvent",
61
+ "metadata",
62
+ "subagentRunId"
63
+ ],
64
+ fields: {}
65
+ },
66
+ ToolCallEndEvent: {
67
+ optional: [
68
+ "timestamp",
69
+ "rawEvent",
70
+ "metadata",
71
+ "subagentRunId"
72
+ ],
73
+ fields: {}
74
+ },
75
+ ToolCallChunkEvent: {
76
+ optional: [
77
+ "timestamp",
78
+ "rawEvent",
79
+ "metadata",
80
+ "subagentRunId",
81
+ "toolCallId",
82
+ "toolCallName",
83
+ "parentMessageId",
84
+ "delta"
85
+ ],
86
+ fields: {}
87
+ },
88
+ TextPart: {
89
+ optional: ["id", "metadata"],
90
+ fields: {}
91
+ },
92
+ DataSource: {
93
+ optional: [],
94
+ fields: {}
95
+ },
96
+ UrlSource: {
97
+ optional: ["mimeType"],
98
+ fields: {}
99
+ },
100
+ FileSource: {
101
+ optional: ["provider", "mimeType"],
102
+ fields: {}
103
+ },
104
+ PartSource: {
105
+ discriminator: "type",
106
+ variants: {
107
+ data: "DataSource",
108
+ url: "UrlSource",
109
+ file: "FileSource"
110
+ }
111
+ },
112
+ ImagePart: {
113
+ optional: ["id", "metadata"],
114
+ fields: { source: "PartSource" }
115
+ },
116
+ AudioPart: {
117
+ optional: ["id", "metadata"],
118
+ fields: { source: "PartSource" }
119
+ },
120
+ VideoPart: {
121
+ optional: ["id", "metadata"],
122
+ fields: { source: "PartSource" }
123
+ },
124
+ DocumentPart: {
125
+ optional: ["id", "metadata"],
126
+ fields: { source: "PartSource" }
127
+ },
128
+ ContentPart: {
129
+ discriminator: "type",
130
+ variants: {
131
+ text: "TextPart",
132
+ image: "ImagePart",
133
+ audio: "AudioPart",
134
+ video: "VideoPart",
135
+ document: "DocumentPart"
136
+ }
137
+ },
138
+ ToolCallResultEvent: {
139
+ optional: [
140
+ "timestamp",
141
+ "rawEvent",
142
+ "metadata",
143
+ "subagentRunId",
144
+ "role"
145
+ ],
146
+ fields: { content: { array: "ContentPart" } }
147
+ },
148
+ StateSnapshotEvent: {
149
+ optional: [
150
+ "timestamp",
151
+ "rawEvent",
152
+ "metadata",
153
+ "subagentRunId"
154
+ ],
155
+ fields: {}
156
+ },
157
+ AddOperation: {
158
+ optional: [],
159
+ fields: {}
160
+ },
161
+ RemoveOperation: {
162
+ optional: [],
163
+ fields: {}
164
+ },
165
+ ReplaceOperation: {
166
+ optional: [],
167
+ fields: {}
168
+ },
169
+ MoveOperation: {
170
+ optional: [],
171
+ fields: {}
172
+ },
173
+ CopyOperation: {
174
+ optional: [],
175
+ fields: {}
176
+ },
177
+ TestOperation: {
178
+ optional: [],
179
+ fields: {}
180
+ },
181
+ JsonPatchOperation: {
182
+ discriminator: "op",
183
+ variants: {
184
+ add: "AddOperation",
185
+ remove: "RemoveOperation",
186
+ replace: "ReplaceOperation",
187
+ move: "MoveOperation",
188
+ copy: "CopyOperation",
189
+ test: "TestOperation"
190
+ }
191
+ },
192
+ StateDeltaEvent: {
193
+ optional: [
194
+ "timestamp",
195
+ "rawEvent",
196
+ "metadata",
197
+ "subagentRunId"
198
+ ],
199
+ fields: { delta: { array: "JsonPatchOperation" } }
200
+ },
201
+ DeveloperMessage: {
202
+ optional: [
203
+ "subagentRunId",
204
+ "name",
205
+ "encryptedValue",
206
+ "metadata"
207
+ ],
208
+ fields: {}
209
+ },
210
+ SystemMessage: {
211
+ optional: [
212
+ "subagentRunId",
213
+ "name",
214
+ "encryptedValue",
215
+ "metadata"
216
+ ],
217
+ fields: {}
218
+ },
219
+ FunctionCall: {
220
+ optional: [],
221
+ fields: {}
222
+ },
223
+ ToolCall: {
224
+ optional: ["encryptedValue", "metadata"],
225
+ fields: { function: "FunctionCall" }
226
+ },
227
+ AssistantMessage: {
228
+ optional: [
229
+ "subagentRunId",
230
+ "name",
231
+ "encryptedValue",
232
+ "metadata",
233
+ "content",
234
+ "toolCalls"
235
+ ],
236
+ fields: { toolCalls: { array: "ToolCall" } }
237
+ },
238
+ UserMessage: {
239
+ optional: [
240
+ "subagentRunId",
241
+ "name",
242
+ "encryptedValue",
243
+ "metadata"
244
+ ],
245
+ fields: { content: { array: "ContentPart" } }
246
+ },
247
+ ToolMessage: {
248
+ optional: [
249
+ "subagentRunId",
250
+ "error",
251
+ "encryptedValue",
252
+ "metadata"
253
+ ],
254
+ fields: { content: { array: "ContentPart" } }
255
+ },
256
+ ActivityMessage: {
257
+ optional: ["subagentRunId", "metadata"],
258
+ fields: {}
259
+ },
260
+ ReasoningMessage: {
261
+ optional: [
262
+ "subagentRunId",
263
+ "encryptedValue",
264
+ "metadata"
265
+ ],
266
+ fields: {}
267
+ },
268
+ Message: {
269
+ discriminator: "role",
270
+ variants: {
271
+ developer: "DeveloperMessage",
272
+ system: "SystemMessage",
273
+ assistant: "AssistantMessage",
274
+ user: "UserMessage",
275
+ tool: "ToolMessage",
276
+ activity: "ActivityMessage",
277
+ reasoning: "ReasoningMessage"
278
+ }
279
+ },
280
+ MessagesSnapshotEvent: {
281
+ optional: [
282
+ "timestamp",
283
+ "rawEvent",
284
+ "metadata"
285
+ ],
286
+ fields: { messages: { array: "Message" } }
287
+ },
288
+ ActivitySnapshotEvent: {
289
+ optional: [
290
+ "timestamp",
291
+ "rawEvent",
292
+ "metadata",
293
+ "subagentRunId",
294
+ "replace"
295
+ ],
296
+ fields: {}
297
+ },
298
+ ActivityDeltaEvent: {
299
+ optional: [
300
+ "timestamp",
301
+ "rawEvent",
302
+ "metadata",
303
+ "subagentRunId"
304
+ ],
305
+ fields: { patch: { array: "JsonPatchOperation" } }
306
+ },
307
+ RawEvent: {
308
+ optional: [
309
+ "timestamp",
310
+ "rawEvent",
311
+ "metadata",
312
+ "subagentRunId",
313
+ "source"
314
+ ],
315
+ fields: {}
316
+ },
317
+ CustomEvent: {
318
+ optional: [
319
+ "timestamp",
320
+ "rawEvent",
321
+ "metadata",
322
+ "subagentRunId"
323
+ ],
324
+ fields: {}
325
+ },
326
+ Tool: {
327
+ optional: ["parameters", "metadata"],
328
+ fields: {}
329
+ },
330
+ Context: {
331
+ optional: [],
332
+ fields: {}
333
+ },
334
+ ResumeEntry: {
335
+ optional: ["payload", "metadata"],
336
+ fields: {}
337
+ },
338
+ RunAgentInput: {
339
+ optional: [
340
+ "protocolVersion",
341
+ "parentRunId",
342
+ "state",
343
+ "tools",
344
+ "context",
345
+ "forwardedProps",
346
+ "resume"
347
+ ],
348
+ fields: {
349
+ messages: { array: "Message" },
350
+ tools: { array: "Tool" },
351
+ context: { array: "Context" },
352
+ resume: { array: "ResumeEntry" }
353
+ }
354
+ },
355
+ RunStartedEvent: {
356
+ optional: [
357
+ "timestamp",
358
+ "rawEvent",
359
+ "metadata",
360
+ "protocolVersion",
361
+ "parentRunId",
362
+ "input"
363
+ ],
364
+ fields: { input: "RunAgentInput" }
365
+ },
366
+ RunFinishedSuccessOutcome: {
367
+ optional: ["pendingToolCallIds"],
368
+ fields: {}
369
+ },
370
+ Interrupt: {
371
+ optional: [
372
+ "subagentRunId",
373
+ "message",
374
+ "toolCallId",
375
+ "responseSchema",
376
+ "expiresAt",
377
+ "metadata"
378
+ ],
379
+ fields: {}
380
+ },
381
+ RunFinishedInterruptOutcome: {
382
+ optional: [],
383
+ fields: { interrupts: { array: "Interrupt" } }
384
+ },
385
+ RunFinishedCancelledOutcome: {
386
+ optional: [],
387
+ fields: {}
388
+ },
389
+ RunFinishedOutcome: {
390
+ discriminator: "type",
391
+ variants: {
392
+ success: "RunFinishedSuccessOutcome",
393
+ interrupt: "RunFinishedInterruptOutcome",
394
+ cancelled: "RunFinishedCancelledOutcome"
395
+ }
396
+ },
397
+ TokenUsage: {
398
+ optional: [
399
+ "provider",
400
+ "model",
401
+ "inputTokens",
402
+ "outputTokens",
403
+ "totalTokens",
404
+ "reasoningTokens",
405
+ "cachedInputTokens",
406
+ "cacheWriteInputTokens"
407
+ ],
408
+ fields: {}
409
+ },
410
+ RunFinishedEvent: {
411
+ optional: [
412
+ "timestamp",
413
+ "rawEvent",
414
+ "metadata",
415
+ "result",
416
+ "outcome",
417
+ "usage"
418
+ ],
419
+ fields: {
420
+ outcome: "RunFinishedOutcome",
421
+ usage: { array: "TokenUsage" }
422
+ }
423
+ },
424
+ RunErrorEvent: {
425
+ optional: [
426
+ "timestamp",
427
+ "rawEvent",
428
+ "metadata",
429
+ "code",
430
+ "usage"
431
+ ],
432
+ fields: { usage: { array: "TokenUsage" } }
433
+ },
434
+ StepStartedEvent: {
435
+ optional: [
436
+ "timestamp",
437
+ "rawEvent",
438
+ "metadata",
439
+ "subagentRunId"
440
+ ],
441
+ fields: {}
442
+ },
443
+ StepFinishedEvent: {
444
+ optional: [
445
+ "timestamp",
446
+ "rawEvent",
447
+ "metadata",
448
+ "subagentRunId"
449
+ ],
450
+ fields: {}
451
+ },
452
+ ReasoningStartEvent: {
453
+ optional: [
454
+ "timestamp",
455
+ "rawEvent",
456
+ "metadata",
457
+ "subagentRunId"
458
+ ],
459
+ fields: {}
460
+ },
461
+ ReasoningMessageStartEvent: {
462
+ optional: [
463
+ "timestamp",
464
+ "rawEvent",
465
+ "metadata",
466
+ "subagentRunId"
467
+ ],
468
+ fields: {}
469
+ },
470
+ ReasoningMessageContentEvent: {
471
+ optional: [
472
+ "timestamp",
473
+ "rawEvent",
474
+ "metadata",
475
+ "subagentRunId"
476
+ ],
477
+ fields: {}
478
+ },
479
+ ReasoningMessageEndEvent: {
480
+ optional: [
481
+ "timestamp",
482
+ "rawEvent",
483
+ "metadata",
484
+ "subagentRunId"
485
+ ],
486
+ fields: {}
487
+ },
488
+ ReasoningMessageChunkEvent: {
489
+ optional: [
490
+ "timestamp",
491
+ "rawEvent",
492
+ "metadata",
493
+ "subagentRunId",
494
+ "messageId",
495
+ "delta"
496
+ ],
497
+ fields: {}
498
+ },
499
+ ReasoningEndEvent: {
500
+ optional: [
501
+ "timestamp",
502
+ "rawEvent",
503
+ "metadata",
504
+ "subagentRunId"
505
+ ],
506
+ fields: {}
507
+ },
508
+ ReasoningEncryptedValueEvent: {
509
+ optional: [
510
+ "timestamp",
511
+ "rawEvent",
512
+ "metadata",
513
+ "subagentRunId"
514
+ ],
515
+ fields: {}
516
+ },
517
+ SubagentStartedEvent: {
518
+ optional: [
519
+ "timestamp",
520
+ "rawEvent",
521
+ "metadata",
522
+ "description",
523
+ "parentSubagentRunId",
524
+ "parentToolCallId",
525
+ "parentMessageId"
526
+ ],
527
+ fields: {}
528
+ },
529
+ SubagentFinishedSuccessOutcome: {
530
+ optional: [],
531
+ fields: {}
532
+ },
533
+ SubagentFinishedSuspendedOutcome: {
534
+ optional: ["interruptIds"],
535
+ fields: {}
536
+ },
537
+ SubagentFinishedOutcome: {
538
+ discriminator: "type",
539
+ variants: {
540
+ success: "SubagentFinishedSuccessOutcome",
541
+ suspended: "SubagentFinishedSuspendedOutcome"
542
+ }
543
+ },
544
+ SubagentFinishedEvent: {
545
+ optional: [
546
+ "timestamp",
547
+ "rawEvent",
548
+ "metadata",
549
+ "result",
550
+ "outcome"
551
+ ],
552
+ fields: { outcome: "SubagentFinishedOutcome" }
553
+ },
554
+ SubagentErrorEvent: {
555
+ optional: [
556
+ "timestamp",
557
+ "rawEvent",
558
+ "metadata",
559
+ "code"
560
+ ],
561
+ fields: {}
562
+ },
563
+ Event: {
564
+ discriminator: "type",
565
+ variants: {
566
+ TEXT_MESSAGE_START: "TextMessageStartEvent",
567
+ TEXT_MESSAGE_CONTENT: "TextMessageContentEvent",
568
+ TEXT_MESSAGE_END: "TextMessageEndEvent",
569
+ TEXT_MESSAGE_CHUNK: "TextMessageChunkEvent",
570
+ TOOL_CALL_START: "ToolCallStartEvent",
571
+ TOOL_CALL_ARGS: "ToolCallArgsEvent",
572
+ TOOL_CALL_END: "ToolCallEndEvent",
573
+ TOOL_CALL_CHUNK: "ToolCallChunkEvent",
574
+ TOOL_CALL_RESULT: "ToolCallResultEvent",
575
+ STATE_SNAPSHOT: "StateSnapshotEvent",
576
+ STATE_DELTA: "StateDeltaEvent",
577
+ MESSAGES_SNAPSHOT: "MessagesSnapshotEvent",
578
+ ACTIVITY_SNAPSHOT: "ActivitySnapshotEvent",
579
+ ACTIVITY_DELTA: "ActivityDeltaEvent",
580
+ RAW: "RawEvent",
581
+ CUSTOM: "CustomEvent",
582
+ RUN_STARTED: "RunStartedEvent",
583
+ RUN_FINISHED: "RunFinishedEvent",
584
+ RUN_ERROR: "RunErrorEvent",
585
+ STEP_STARTED: "StepStartedEvent",
586
+ STEP_FINISHED: "StepFinishedEvent",
587
+ REASONING_START: "ReasoningStartEvent",
588
+ REASONING_MESSAGE_START: "ReasoningMessageStartEvent",
589
+ REASONING_MESSAGE_CONTENT: "ReasoningMessageContentEvent",
590
+ REASONING_MESSAGE_END: "ReasoningMessageEndEvent",
591
+ REASONING_MESSAGE_CHUNK: "ReasoningMessageChunkEvent",
592
+ REASONING_END: "ReasoningEndEvent",
593
+ REASONING_ENCRYPTED_VALUE: "ReasoningEncryptedValueEvent",
594
+ SUBAGENT_STARTED: "SubagentStartedEvent",
595
+ SUBAGENT_FINISHED: "SubagentFinishedEvent",
596
+ SUBAGENT_ERROR: "SubagentErrorEvent"
597
+ }
598
+ },
599
+ SubagentInfo: {
600
+ optional: ["description"],
601
+ fields: {}
602
+ },
603
+ IdentityCapabilities: {
604
+ optional: [
605
+ "name",
606
+ "type",
607
+ "description",
608
+ "version",
609
+ "provider",
610
+ "documentationUrl",
611
+ "metadata"
612
+ ],
613
+ fields: {}
614
+ },
615
+ TransportCapabilities: {
616
+ optional: [
617
+ "streaming",
618
+ "websocket",
619
+ "httpBinary",
620
+ "pushNotifications",
621
+ "resumable"
622
+ ],
623
+ fields: {}
624
+ },
625
+ ToolsCapabilities: {
626
+ optional: [
627
+ "supported",
628
+ "items",
629
+ "parallelCalls",
630
+ "clientProvided"
631
+ ],
632
+ fields: { items: { array: "Tool" } }
633
+ },
634
+ OutputCapabilities: {
635
+ optional: ["structuredOutput", "supportedMimeTypes"],
636
+ fields: {}
637
+ },
638
+ StateCapabilities: {
639
+ optional: [
640
+ "snapshots",
641
+ "deltas",
642
+ "memory",
643
+ "persistentState"
644
+ ],
645
+ fields: {}
646
+ },
647
+ MultiAgentCapabilities: {
648
+ optional: [
649
+ "supported",
650
+ "delegation",
651
+ "handoffs",
652
+ "subagents"
653
+ ],
654
+ fields: { subagents: { array: "SubagentInfo" } }
655
+ },
656
+ ReasoningCapabilities: {
657
+ optional: [
658
+ "supported",
659
+ "streaming",
660
+ "encrypted"
661
+ ],
662
+ fields: {}
663
+ },
664
+ MultimodalInputCapabilities: {
665
+ optional: [
666
+ "image",
667
+ "audio",
668
+ "video",
669
+ "pdf",
670
+ "file"
671
+ ],
672
+ fields: {}
673
+ },
674
+ MultimodalOutputCapabilities: {
675
+ optional: ["image", "audio"],
676
+ fields: {}
677
+ },
678
+ MultimodalCapabilities: {
679
+ optional: ["input", "output"],
680
+ fields: {
681
+ input: "MultimodalInputCapabilities",
682
+ output: "MultimodalOutputCapabilities"
683
+ }
684
+ },
685
+ ExecutionCapabilities: {
686
+ optional: [
687
+ "codeExecution",
688
+ "sandboxed",
689
+ "maxIterations",
690
+ "maxExecutionTime"
691
+ ],
692
+ fields: {}
693
+ },
694
+ HumanInTheLoopCapabilities: {
695
+ optional: [
696
+ "supported",
697
+ "approvals",
698
+ "interventions",
699
+ "feedback",
700
+ "interrupts",
701
+ "approveWithEdits"
702
+ ],
703
+ fields: {}
704
+ },
705
+ AgentCapabilities: {
706
+ optional: [
707
+ "identity",
708
+ "transport",
709
+ "tools",
710
+ "output",
711
+ "state",
712
+ "multiAgent",
713
+ "reasoning",
714
+ "multimodal",
715
+ "execution",
716
+ "humanInTheLoop",
717
+ "custom"
718
+ ],
719
+ fields: {
720
+ identity: "IdentityCapabilities",
721
+ transport: "TransportCapabilities",
722
+ tools: "ToolsCapabilities",
723
+ output: "OutputCapabilities",
724
+ state: "StateCapabilities",
725
+ multiAgent: "MultiAgentCapabilities",
726
+ reasoning: "ReasoningCapabilities",
727
+ multimodal: "MultimodalCapabilities",
728
+ execution: "ExecutionCapabilities",
729
+ humanInTheLoop: "HumanInTheLoopCapabilities"
730
+ }
731
+ }
732
+ };
733
+ function omit(value, shape) {
734
+ if (typeof shape === "string") return omit(value, shapes[shape]);
735
+ if ("array" in shape) {
736
+ if (!Array.isArray(value)) return value;
737
+ const result = value.map((item) => omit(item, shape.array));
738
+ return result.every((item, index) => item === value[index]) ? value : result;
739
+ }
740
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
741
+ const object = value;
742
+ if ("discriminator" in shape) {
743
+ const tag = object[shape.discriminator];
744
+ return typeof tag === "string" && Object.prototype.hasOwnProperty.call(shape.variants, tag) ? omit(value, shape.variants[tag]) : value;
745
+ }
746
+ let result = object;
747
+ for (const key of shape.optional) if (Object.prototype.hasOwnProperty.call(object, key) && object[key] === null) {
748
+ if (result === object) result = { ...object };
749
+ delete result[key];
750
+ }
751
+ for (const [key, child] of Object.entries(shape.fields)) {
752
+ if (!Object.prototype.hasOwnProperty.call(result, key)) continue;
753
+ const next = omit(result[key], child);
754
+ if (next !== result[key]) {
755
+ if (result === object) result = { ...object };
756
+ result[key] = next;
757
+ }
758
+ }
759
+ return result;
760
+ }
761
+ /**
762
+ * Omits whole optional null fields before transmission. Does not validate,
763
+ * mutate the input, or traverse arbitrary application JSON or unknown fields.
764
+ * Required null payloads and null values inside opaque data remain intact.
765
+ */
766
+ function omitOptionalNulls(value, root) {
767
+ return omit(value, root);
768
+ }
769
+
770
+ //#endregion
771
+ //#region src/compat.ts
4
772
  var AGUIError = class extends Error {
5
773
  constructor(message) {
6
774
  super(message);
@@ -13,5 +781,263 @@ var AGUIConnectNotImplementedError = class extends AGUIError {
13
781
  };
14
782
 
15
783
  //#endregion
16
- export { AGUIConnectNotImplementedError, AGUIError, EventType };
784
+ //#region src/metadata.ts
785
+ /**
786
+ * The key reserved for AG-UI's own use inside a metadata object. Every other
787
+ * key is user space.
788
+ *
789
+ * Reservation is by convention: nothing rejects a write to this key at runtime,
790
+ * because metadata is open by key and validating its shape would contradict
791
+ * that.
792
+ */
793
+ const AGUI_METADATA_KEY = "ag-ui";
794
+ /**
795
+ * Extra information attached to an event or a message.
796
+ *
797
+ * Open by key — any JSON value is allowed under a key, including `null`.
798
+ *
799
+ * Deliberately `z.any()` rather than a recursive JSON-value schema, which review
800
+ * has suggested more than once. Two reasons. Every dynamic payload in the
801
+ * protocol uses the permissive form — `state`, `rawEvent`, `CustomEvent.value`,
802
+ * `ActivityMessage.content`, and the pre-existing `Tool.metadata` and
803
+ * `Interrupt.metadata` — so tightening this one field would make it the sole
804
+ * outlier while fixing nothing elsewhere. And a recursive validation would walk
805
+ * every value on every event, on the streaming hot path, to catch a mistake
806
+ * (a function, a bigint) that already fails loudly at encode time.
807
+ *
808
+ * The schema itself now lives in the generated source (MetadataSchema in
809
+ * src/generated/schemas.ts); this comment survives as the recorded reasoning.
810
+ */
811
+ /**
812
+ * How metadata is declared on events and messages: the object is absent or an
813
+ * object, never `null`. The validator pinning that invariant is
814
+ * `OptionalMetadataSchema`, which lives in src/schemas.ts along with every
815
+ * other runtime validator this package ships.
816
+ */
817
+ /**
818
+ * Folds `incoming` metadata into `existing`, key by key, with the last write
819
+ * winning.
820
+ *
821
+ * A message is assembled from a sequence of events, and the interesting values
822
+ * — token usage and finish reason among them — are only known at the end. So
823
+ * metadata accumulates as the sequence arrives rather than being fixed at the
824
+ * start.
825
+ *
826
+ * A key's value is replaced outright. This never recurses, so an array or
827
+ * object under any key — including {@link AGUI_METADATA_KEY} — is replaced
828
+ * wholesale rather than blended with what was there before.
829
+ *
830
+ * Returns a new object rather than mutating either argument. An absent
831
+ * `incoming` returns `existing` untouched; an empty `incoming` changes nothing.
832
+ */
833
+ function mergeMetadata(existing, incoming) {
834
+ if (incoming === void 0) return existing;
835
+ if (existing === void 0) return { ...incoming };
836
+ return {
837
+ ...existing,
838
+ ...incoming
839
+ };
840
+ }
841
+
842
+ //#endregion
843
+ //#region src/token-usage.ts
844
+ /** The AG-UI names of the six token counts, in the order an entry lists them. */
845
+ const COUNT_KEYS = [
846
+ "inputTokens",
847
+ "outputTokens",
848
+ "totalTokens",
849
+ "reasoningTokens",
850
+ "cachedInputTokens",
851
+ "cacheWriteInputTokens"
852
+ ];
853
+ /**
854
+ * The count keys already warned about, so the diagnostic below fires once per
855
+ * process per key rather than once per event. A provider that hands over a
856
+ * string count hands one over on every call, and a per-call warning would bury
857
+ * the stream it is meant to annotate.
858
+ */
859
+ const warnedCountKeys = /* @__PURE__ */ new Set();
860
+ /** What the value WAS, said in a way that points at the provider's bug. */
861
+ const describeRejected = (v) => {
862
+ if (v === null) return "null";
863
+ if (typeof v === "string") return `${JSON.stringify(v)} (a string)`;
864
+ if (typeof v === "number") return `${String(v)} (a non-finite number)`;
865
+ if (typeof v === "object") return `an object`;
866
+ return `${String(v)} (a ${typeof v})`;
867
+ };
868
+ /**
869
+ * Accept a value only if it is a real, finite number.
870
+ *
871
+ * Shared by both vendor mappers so they guard identically. Providers do hand
872
+ * over strings, `null`s and `NaN`s in their usage metadata, and a bad value must
873
+ * not reach the wire: consumers validate every incoming event and throw on
874
+ * failure, so one malformed count would fail an otherwise-successful run at its
875
+ * final event — costing the user the answer, not just the token count.
876
+ *
877
+ * Dropping it is right; dropping it in silence is not. The usage this run
878
+ * reports is then simply wrong, with nothing anywhere saying which count went
879
+ * missing or why, so a present-but-unusable value is named once per key.
880
+ *
881
+ * `undefined` and `NaN` are exempt because they are not defects: they are how a
882
+ * provider spells "did not report this count". `undefined` covers both shapes —
883
+ * an absent key in LangChain's `usage_metadata`, an explicit `undefined` in
884
+ * AI-SDK's `LanguageModelUsage` — and AI-SDK uses `NaN` for the same thing,
885
+ * which is why its mapper's docstring says so. Warning on those would fire on
886
+ * ordinary traffic and train the reader to ignore the message.
887
+ *
888
+ * `key` is the AG-UI count name the value was headed for, not the vendor's
889
+ * spelling of it, so one message reads the same whichever mapper produced it.
890
+ */
891
+ const num = (v, key) => {
892
+ if (typeof v === "number" && Number.isFinite(v)) return v;
893
+ if (!(v === void 0 || typeof v === "number" && Number.isNaN(v)) && !warnedCountKeys.has(key)) {
894
+ warnedCountKeys.add(key);
895
+ console.warn(`[ag-ui] usage.${key} was ${describeRejected(v)}, not a number — omitted from this run's usage. Reported once per key.`);
896
+ }
897
+ };
898
+ /**
899
+ * Read a property from a value of unknown shape, yielding `undefined` for
900
+ * anything that is not an object. Lets the mappers take `unknown` rather than
901
+ * `any` — vendor payloads are untrusted, so every access should be narrowed
902
+ * rather than assumed.
903
+ */
904
+ const prop = (v, key) => typeof v === "object" && v !== null ? v[key] : void 0;
905
+ /**
906
+ * Build a {@link TokenUsage} from already-guarded counts, or `undefined` when no
907
+ * count survived. Returning `undefined` rather than a labels-only entry keeps
908
+ * "the provider reported no usage" distinct from "the provider reported usage",
909
+ * so callers omit the field instead of emitting an entry that claims nothing.
910
+ */
911
+ function buildEntry(counts, { provider, model }) {
912
+ if (!COUNT_KEYS.some((key) => counts[key] !== void 0)) return void 0;
913
+ const entry = {};
914
+ if (provider != null) entry.provider = provider;
915
+ if (model != null) entry.model = model;
916
+ for (const key of COUNT_KEYS) {
917
+ const value = counts[key];
918
+ if (value !== void 0) entry[key] = value;
919
+ }
920
+ return entry;
921
+ }
922
+ /**
923
+ * Map a LangChain-family `usage_metadata` object into an AG-UI {@link TokenUsage}.
924
+ *
925
+ * LangChain and LangGraph both attach usage as `{ input_tokens, output_tokens,
926
+ * total_tokens, input_token_details: { cache_read, cache_creation },
927
+ * output_token_details: { reasoning } }`. LangChain's accounting is the
928
+ * protocol's — `input_tokens` already includes the cache details and
929
+ * `output_tokens` the reasoning detail — so every count passes through as is.
930
+ * This maps only those numeric counts plus optional provider/model labels —
931
+ * never prompt/completion content. A count the provider
932
+ * did not return is simply absent from `usage_metadata` and reads as
933
+ * `undefined` here; that is not a defect and draws no warning. Returns
934
+ * `undefined` when no usable count is present, so callers can omit usage rather
935
+ * than report zeros.
936
+ */
937
+ function tokenUsageFromLangChainMetadata(usageMetadata, { provider, model }) {
938
+ if (!usageMetadata) return void 0;
939
+ const inputDetails = prop(usageMetadata, "input_token_details");
940
+ const outputDetails = prop(usageMetadata, "output_token_details");
941
+ return buildEntry({
942
+ inputTokens: num(prop(usageMetadata, "input_tokens"), "inputTokens"),
943
+ outputTokens: num(prop(usageMetadata, "output_tokens"), "outputTokens"),
944
+ totalTokens: num(prop(usageMetadata, "total_tokens"), "totalTokens"),
945
+ reasoningTokens: num(prop(outputDetails, "reasoning"), "reasoningTokens"),
946
+ cachedInputTokens: num(prop(inputDetails, "cache_read"), "cachedInputTokens"),
947
+ cacheWriteInputTokens: num(prop(inputDetails, "cache_creation"), "cacheWriteInputTokens")
948
+ }, {
949
+ provider,
950
+ model
951
+ });
952
+ }
953
+ /**
954
+ * Map an AI-SDK `LanguageModelUsage` object into an AG-UI {@link TokenUsage}.
955
+ *
956
+ * AI-SDK's v5 keys already match — `inputTokens`, `outputTokens`,
957
+ * `totalTokens`, `reasoningTokens`, `cachedInputTokens` — with the totals
958
+ * inclusive the way the protocol counts them. v6 adds `inputTokenDetails:
959
+ * { cacheReadTokens, cacheWriteTokens }` and `outputTokenDetails:
960
+ * { reasoningTokens }`; the cache-write count exists only there, and the two
961
+ * counts present in both forms are read from the top level first. AI-SDK
962
+ * reports `NaN`/`undefined` for counts a provider didn't return, so only finite
963
+ * numbers are copied. Returns `undefined` when no finite count is present (so
964
+ * callers omit empty usage).
965
+ */
966
+ function tokenUsageFromAiSdkUsage(usage, { provider, model }) {
967
+ if (!usage) return void 0;
968
+ const inputDetails = prop(usage, "inputTokenDetails");
969
+ const outputDetails = prop(usage, "outputTokenDetails");
970
+ return buildEntry({
971
+ inputTokens: num(prop(usage, "inputTokens"), "inputTokens"),
972
+ outputTokens: num(prop(usage, "outputTokens"), "outputTokens"),
973
+ totalTokens: num(prop(usage, "totalTokens"), "totalTokens"),
974
+ reasoningTokens: num(prop(usage, "reasoningTokens"), "reasoningTokens") ?? num(prop(outputDetails, "reasoningTokens"), "reasoningTokens"),
975
+ cachedInputTokens: num(prop(usage, "cachedInputTokens"), "cachedInputTokens") ?? num(prop(inputDetails, "cacheReadTokens"), "cachedInputTokens"),
976
+ cacheWriteInputTokens: num(prop(inputDetails, "cacheWriteTokens"), "cacheWriteInputTokens")
977
+ }, {
978
+ provider,
979
+ model
980
+ });
981
+ }
982
+ /**
983
+ * Sum per-call {@link TokenUsage} entries into one entry per `(provider, model)`
984
+ * pair. Order follows first appearance. A count field stays `undefined` when no
985
+ * member of the group reported it, so "not reported" stays distinct from zero.
986
+ *
987
+ * Protocol-agnostic: works on any producer's `TokenUsage[]`, so integrations
988
+ * share it rather than reimplementing aggregation.
989
+ */
990
+ function aggregateTokenUsage(entries) {
991
+ const grouped = /* @__PURE__ */ new Map();
992
+ for (const entry of entries) {
993
+ const key = `${entry.provider ?? ""} ${entry.model ?? ""}`;
994
+ let target = grouped.get(key);
995
+ if (!target) {
996
+ target = {
997
+ provider: entry.provider,
998
+ model: entry.model
999
+ };
1000
+ grouped.set(key, target);
1001
+ }
1002
+ for (const field of COUNT_KEYS) {
1003
+ const value = entry[field];
1004
+ if (value == null) continue;
1005
+ target[field] = (target[field] ?? 0) + value;
1006
+ }
1007
+ }
1008
+ return [...grouped.values()];
1009
+ }
1010
+
1011
+ //#endregion
1012
+ //#region src/content.ts
1013
+ /**
1014
+ * The text of string-or-parts content, for a consumer that can only hold a
1015
+ * string: the text parts concatenated in order, every other part dropped.
1016
+ *
1017
+ * This is the downgrade the specification permits for a peer that predates
1018
+ * content parts (/spec/1.0/basic/versioning): it removes and reshapes, and
1019
+ * it invents nothing — no placeholder stands in for a dropped image, because a
1020
+ * downgrade MUST NOT supply a value the producer never sent. Content that is
1021
+ * entirely media flattens to the empty string, which the same rule allows.
1022
+ *
1023
+ * Losing content is never meant to be silent. This helper only reshapes; a
1024
+ * caller that knows it is talking to an older peer warns as well, the way the
1025
+ * era shims in `@ag-ui/client` do.
1026
+ */
1027
+ function contentToText(content) {
1028
+ if (content === void 0) return "";
1029
+ if (typeof content === "string") return content;
1030
+ return content.filter((part) => part.type === "text").map((part) => part.text).join("");
1031
+ }
1032
+ /**
1033
+ * Whether string-or-parts content carries anything but text — the question a
1034
+ * caller asks before flattening, so it can warn about what the flattening
1035
+ * would drop.
1036
+ */
1037
+ function contentHasMedia(content) {
1038
+ return Array.isArray(content) && content.some((part) => part.type !== "text");
1039
+ }
1040
+
1041
+ //#endregion
1042
+ export { AGUIConnectNotImplementedError, AGUIError, AGUI_METADATA_KEY, EventType, PROTOCOL_VERSION, aggregateTokenUsage, contentHasMedia, contentToText, mergeMetadata, omitOptionalNulls, tokenUsageFromAiSdkUsage, tokenUsageFromLangChainMetadata };
17
1043
  //# sourceMappingURL=index.mjs.map