@proj-airi/trace-kit 0.0.0-stage → 0.15.2

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.
@@ -0,0 +1,880 @@
1
+ import { G as definitionRecordsOf, J as trackPath } from "../conventions-DLiC8rkL.mjs";
2
+ import { ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS } from "../semconv.mjs";
3
+ import { a as TraceReader, t as createTimelineProjection } from "../timeline-B4Vc6qQf.mjs";
4
+ import "../projections/index.mjs";
5
+ import { VoiceAttributes, VoiceNames, VoiceSeries, VoiceTracks } from "../profiles/voice.mjs";
6
+ import { AgentNames, AgentTracks } from "../profiles/agent.mjs";
7
+ //#region src/testing/fixtures/long-leading-silence.json
8
+ var long_leading_silence_default = {
9
+ intervalMs: 32,
10
+ times: [
11
+ 20,
12
+ 52,
13
+ 84,
14
+ 116,
15
+ 148,
16
+ 180,
17
+ 212,
18
+ 244,
19
+ 276,
20
+ 308,
21
+ 340,
22
+ 372,
23
+ 404,
24
+ 436,
25
+ 468,
26
+ 500,
27
+ 532,
28
+ 564,
29
+ 596,
30
+ 628,
31
+ 660,
32
+ 692,
33
+ 724,
34
+ 756,
35
+ 788,
36
+ 820,
37
+ 852,
38
+ 884,
39
+ 916,
40
+ 948,
41
+ 980,
42
+ 1012,
43
+ 1044,
44
+ 1076,
45
+ 1108,
46
+ 1140,
47
+ 1172,
48
+ 1204,
49
+ 1236,
50
+ 1268,
51
+ 1300,
52
+ 1332,
53
+ 1364,
54
+ 1396,
55
+ 1428,
56
+ 1460,
57
+ 1492,
58
+ 1524,
59
+ 1556,
60
+ 1588,
61
+ 1620,
62
+ 1652,
63
+ 1684,
64
+ 1716,
65
+ 1748,
66
+ 1780,
67
+ 1812,
68
+ 1844,
69
+ 1876,
70
+ 1908,
71
+ 1940,
72
+ 1972,
73
+ 2004,
74
+ 2036,
75
+ 2068,
76
+ 2100,
77
+ 2132,
78
+ 2164,
79
+ 2196,
80
+ 2228,
81
+ 2260,
82
+ 2292,
83
+ 2324,
84
+ 2356,
85
+ 2388,
86
+ 2420,
87
+ 2452,
88
+ 2484,
89
+ 2516,
90
+ 2548,
91
+ 2580,
92
+ 2612,
93
+ 2644,
94
+ 2676,
95
+ 2708,
96
+ 2740,
97
+ 2772,
98
+ 2804,
99
+ 2836,
100
+ 2868,
101
+ 2900,
102
+ 2932,
103
+ 2964,
104
+ 2996,
105
+ 3028,
106
+ 3060,
107
+ 3092,
108
+ 3124,
109
+ 3156,
110
+ 3188,
111
+ 3220,
112
+ 3252,
113
+ 3284,
114
+ 3316,
115
+ 3348,
116
+ 3380,
117
+ 3412,
118
+ 3444,
119
+ 3476,
120
+ 3508,
121
+ 3540,
122
+ 3572,
123
+ 3604,
124
+ 3636,
125
+ 3668,
126
+ 3700,
127
+ 3732,
128
+ 3764,
129
+ 3796,
130
+ 3828,
131
+ 3860,
132
+ 3892,
133
+ 3924,
134
+ 3956,
135
+ 3988,
136
+ 4020,
137
+ 4052,
138
+ 4084,
139
+ 4116,
140
+ 4148,
141
+ 4180,
142
+ 4212,
143
+ 4244,
144
+ 4276,
145
+ 4308,
146
+ 4340,
147
+ 4372,
148
+ 4404,
149
+ 4436,
150
+ 4468,
151
+ 4500,
152
+ 4532,
153
+ 4564,
154
+ 4596,
155
+ 4628,
156
+ 4660,
157
+ 4692,
158
+ 4724,
159
+ 4756,
160
+ 4788,
161
+ 4820,
162
+ 4852,
163
+ 4884,
164
+ 4916,
165
+ 4948,
166
+ 4980,
167
+ 5012,
168
+ 5044,
169
+ 5076,
170
+ 5108,
171
+ 5140,
172
+ 5172,
173
+ 5204,
174
+ 5236,
175
+ 5268
176
+ ],
177
+ probability: [
178
+ 0,
179
+ 0,
180
+ 0,
181
+ 0,
182
+ 0,
183
+ 0,
184
+ 0,
185
+ 0,
186
+ 0,
187
+ 0,
188
+ 0,
189
+ 0,
190
+ 0,
191
+ 0,
192
+ 0,
193
+ 0,
194
+ 0,
195
+ 0,
196
+ 0,
197
+ 0,
198
+ 0,
199
+ .001,
200
+ .065,
201
+ .303,
202
+ .488,
203
+ .26,
204
+ .251,
205
+ .894,
206
+ .907,
207
+ .851,
208
+ .514,
209
+ .625,
210
+ .547,
211
+ .726,
212
+ .824,
213
+ .754,
214
+ .633,
215
+ .599,
216
+ .525,
217
+ .496,
218
+ .92,
219
+ .785,
220
+ .912,
221
+ .912,
222
+ .849,
223
+ .932,
224
+ .922,
225
+ .883,
226
+ .722,
227
+ .477,
228
+ .455,
229
+ .666,
230
+ .908,
231
+ .963,
232
+ .951,
233
+ .965,
234
+ .95,
235
+ .954,
236
+ .939,
237
+ .934,
238
+ .911,
239
+ .732,
240
+ .751,
241
+ .463,
242
+ .957,
243
+ .988,
244
+ .991,
245
+ .98,
246
+ .98,
247
+ .985,
248
+ .857,
249
+ .91,
250
+ .97,
251
+ .956,
252
+ .96,
253
+ .944,
254
+ .865,
255
+ .737,
256
+ .67,
257
+ .48,
258
+ .373,
259
+ .339,
260
+ .227,
261
+ .17,
262
+ .067,
263
+ .031,
264
+ .026,
265
+ .024,
266
+ .02,
267
+ .017,
268
+ .015,
269
+ .012,
270
+ .01,
271
+ .008,
272
+ .006,
273
+ .005,
274
+ .004,
275
+ .003,
276
+ .003,
277
+ .002,
278
+ .002,
279
+ .002,
280
+ .002,
281
+ .001,
282
+ .001,
283
+ .001,
284
+ .001,
285
+ .001,
286
+ .001,
287
+ .001,
288
+ .001,
289
+ .001,
290
+ 0,
291
+ 0,
292
+ .001,
293
+ .138,
294
+ .389,
295
+ .556,
296
+ .755,
297
+ .705,
298
+ .394,
299
+ .197,
300
+ .682,
301
+ .464,
302
+ .78,
303
+ .76,
304
+ .582,
305
+ .31,
306
+ .13,
307
+ .517,
308
+ .935,
309
+ .982,
310
+ .988,
311
+ .985,
312
+ .987,
313
+ .976,
314
+ .982,
315
+ .899,
316
+ .805,
317
+ .749,
318
+ .728,
319
+ .523,
320
+ .372,
321
+ .157,
322
+ .058,
323
+ .039,
324
+ .027,
325
+ .019,
326
+ .014,
327
+ .01,
328
+ .008,
329
+ .007,
330
+ .005,
331
+ .004,
332
+ .003,
333
+ .003,
334
+ .002,
335
+ .002,
336
+ .002,
337
+ .002,
338
+ .002,
339
+ .002,
340
+ .001,
341
+ .001,
342
+ .001
343
+ ],
344
+ level: [
345
+ 0,
346
+ 0,
347
+ 0,
348
+ 0,
349
+ 0,
350
+ 0,
351
+ 0,
352
+ 0,
353
+ 0,
354
+ 0,
355
+ 0,
356
+ 0,
357
+ 0,
358
+ 0,
359
+ 0,
360
+ 0,
361
+ 0,
362
+ 0,
363
+ 0,
364
+ 0,
365
+ .06,
366
+ .434,
367
+ .779,
368
+ .784,
369
+ .779,
370
+ .764,
371
+ .76,
372
+ .683,
373
+ .347,
374
+ .275,
375
+ .724,
376
+ .777,
377
+ .772,
378
+ .759,
379
+ .752,
380
+ .74,
381
+ .738,
382
+ .758,
383
+ .774,
384
+ .777,
385
+ .768,
386
+ .751,
387
+ .747,
388
+ .725,
389
+ .717,
390
+ .706,
391
+ .7,
392
+ .693,
393
+ .494,
394
+ .415,
395
+ .361,
396
+ .698,
397
+ .703,
398
+ .702,
399
+ .73,
400
+ .725,
401
+ .719,
402
+ .724,
403
+ .724,
404
+ .617,
405
+ .417,
406
+ .338,
407
+ .306,
408
+ .336,
409
+ .715,
410
+ .706,
411
+ .566,
412
+ .473,
413
+ .437,
414
+ .239,
415
+ .353,
416
+ .61,
417
+ .569,
418
+ .549,
419
+ .525,
420
+ .475,
421
+ .179,
422
+ .149,
423
+ .231,
424
+ .267,
425
+ .25,
426
+ .224,
427
+ .171,
428
+ .026,
429
+ 0,
430
+ 0,
431
+ 0,
432
+ 0,
433
+ 0,
434
+ 0,
435
+ 0,
436
+ 0,
437
+ 0,
438
+ 0,
439
+ 0,
440
+ 0,
441
+ 0,
442
+ 0,
443
+ 0,
444
+ 0,
445
+ 0,
446
+ 0,
447
+ 0,
448
+ 0,
449
+ 0,
450
+ 0,
451
+ 0,
452
+ 0,
453
+ 0,
454
+ 0,
455
+ 0,
456
+ 0,
457
+ 0,
458
+ .379,
459
+ .581,
460
+ .787,
461
+ .817,
462
+ .76,
463
+ .47,
464
+ .472,
465
+ .386,
466
+ .716,
467
+ .81,
468
+ .802,
469
+ .759,
470
+ .465,
471
+ .078,
472
+ 0,
473
+ .475,
474
+ .743,
475
+ .772,
476
+ .746,
477
+ .735,
478
+ .709,
479
+ .695,
480
+ .669,
481
+ .655,
482
+ .64,
483
+ .631,
484
+ .62,
485
+ .511,
486
+ .305,
487
+ .103,
488
+ 0,
489
+ 0,
490
+ 0,
491
+ 0,
492
+ 0,
493
+ 0,
494
+ 0,
495
+ 0,
496
+ 0,
497
+ 0,
498
+ 0,
499
+ 0,
500
+ 0,
501
+ 0,
502
+ 0,
503
+ 0,
504
+ 0,
505
+ 0,
506
+ 0,
507
+ 0,
508
+ 0,
509
+ 0
510
+ ]
511
+ };
512
+ //#endregion
513
+ //#region src/testing/voice-turn.ts
514
+ /**
515
+ * A real recording: the level and the VAD probability of each 32 ms detector window of 5.3 s of speech.
516
+ *
517
+ * The values come from the AIRI Silero VAD model and `levelOf` of stage-ui, run on
518
+ * `cases/long-leading-silence/input.test.wav` of `@proj-airi/testing-audio`. The probability is near 0 in silence,
519
+ * jumps to near 1 within one or two windows, and dips between words. The speech starts at 884 ms.
520
+ */
521
+ const LONG_LEADING_SILENCE = long_leading_silence_default;
522
+ /** The trace clock times of the voice turn of {@link voiceTurnRecords}, in milliseconds. */
523
+ const VOICE_TURN = {
524
+ inputStart: 200,
525
+ speechStart: 1084,
526
+ inputEnd: 5500,
527
+ playbackStart: 7e3,
528
+ playbackEnd: 1e4,
529
+ /** A second model request starts here and stays open. */
530
+ openRequestStart: 10200,
531
+ end: 12e3
532
+ };
533
+ /**
534
+ * Records of one voice turn, for tests and stories of trace views. The trace has every kind of item that the IO
535
+ * tracer draws:
536
+ *
537
+ * - A voice input with the level and the VAD probability of {@link LONG_LEADING_SILENCE}, and two speech segments.
538
+ * - A failed speech recognition and its retry.
539
+ * - A chat turn, a model request with tokens and a first chunk, and a labelled tool call.
540
+ * - A speech output, a TTS request, and a playback with a level series.
541
+ * - Participant states, floor instants, and a model request that is still open at the end.
542
+ */
543
+ function voiceTurnRecords() {
544
+ const user = { actor: "user" };
545
+ const agent = { actor: "agent" };
546
+ const input = {
547
+ ...user,
548
+ input: "i1",
549
+ conversation: "c1"
550
+ };
551
+ const turn = {
552
+ turn: "i1",
553
+ conversation: "c1"
554
+ };
555
+ const at = VOICE_TURN;
556
+ const userTrack = (path) => trackPath(path, user);
557
+ const agentTrack = (path) => trackPath(path, agent);
558
+ const llm = trackPath(AgentTracks.LLM, { agent: "agent" });
559
+ const played = long_leading_silence_default.times.flatMap((time, index) => time >= 884 && time - 884 < at.playbackEnd - at.playbackStart ? [index] : []);
560
+ return [
561
+ {
562
+ type: "state",
563
+ ts: 0,
564
+ track: userTrack(VoiceTracks.State),
565
+ value: "idle",
566
+ ids: user
567
+ },
568
+ {
569
+ type: "state",
570
+ ts: at.inputStart,
571
+ track: userTrack(VoiceTracks.State),
572
+ value: "listening",
573
+ from: "idle",
574
+ ids: user
575
+ },
576
+ {
577
+ type: "state",
578
+ ts: at.speechStart,
579
+ track: userTrack(VoiceTracks.State),
580
+ value: "speaking",
581
+ from: "listening",
582
+ ids: user
583
+ },
584
+ {
585
+ type: "state",
586
+ ts: at.inputEnd,
587
+ track: userTrack(VoiceTracks.State),
588
+ value: "waiting",
589
+ from: "speaking",
590
+ ids: user
591
+ },
592
+ {
593
+ type: "span.begin",
594
+ ts: at.inputStart,
595
+ track: userTrack(VoiceTracks.Input),
596
+ spanId: "input",
597
+ name: VoiceNames.VoiceInput,
598
+ ids: input,
599
+ attrs: { [VoiceAttributes.InputTrigger]: "speech" }
600
+ },
601
+ {
602
+ type: "sample.chunk",
603
+ ts: at.inputStart,
604
+ track: userTrack(VoiceTracks.Input),
605
+ ids: user,
606
+ offsetsMs: long_leading_silence_default.times,
607
+ values: {
608
+ [VoiceSeries.Level]: long_leading_silence_default.level,
609
+ [VoiceSeries.Probability]: long_leading_silence_default.probability
610
+ }
611
+ },
612
+ {
613
+ type: "span.begin",
614
+ ts: at.speechStart,
615
+ track: userTrack(VoiceTracks.Speech),
616
+ spanId: "speech-1",
617
+ name: VoiceNames.SpeechSegment,
618
+ ids: input
619
+ },
620
+ {
621
+ type: "instant",
622
+ ts: at.speechStart,
623
+ track: trackPath(VoiceTracks.Floor, { conversation: "c1" }),
624
+ name: VoiceNames.FloorTaken,
625
+ attrs: { actor: "user" }
626
+ },
627
+ {
628
+ type: "span.end",
629
+ ts: 2748,
630
+ track: userTrack(VoiceTracks.Speech),
631
+ spanId: "speech-1",
632
+ status: "ok"
633
+ },
634
+ {
635
+ type: "span.begin",
636
+ ts: 3964,
637
+ track: userTrack(VoiceTracks.Speech),
638
+ spanId: "speech-2",
639
+ name: VoiceNames.SpeechSegment,
640
+ ids: input
641
+ },
642
+ {
643
+ type: "span.end",
644
+ ts: 4764,
645
+ track: userTrack(VoiceTracks.Speech),
646
+ spanId: "speech-2",
647
+ status: "ok"
648
+ },
649
+ {
650
+ type: "span.begin",
651
+ ts: 4764,
652
+ track: userTrack(VoiceTracks.ASR),
653
+ spanId: "asr-1",
654
+ name: VoiceNames.SpeechRecognition,
655
+ ids: input
656
+ },
657
+ {
658
+ type: "span.end",
659
+ ts: 5150,
660
+ track: userTrack(VoiceTracks.ASR),
661
+ spanId: "asr-1",
662
+ status: "error",
663
+ reason: "provider failed"
664
+ },
665
+ {
666
+ type: "span.begin",
667
+ ts: 5150,
668
+ track: userTrack(VoiceTracks.ASR),
669
+ spanId: "asr-2",
670
+ name: VoiceNames.SpeechRecognition,
671
+ ids: input,
672
+ links: [{
673
+ rel: "retry-of",
674
+ to: { spanId: "asr-1" }
675
+ }]
676
+ },
677
+ {
678
+ type: "span.end",
679
+ ts: at.inputEnd,
680
+ track: userTrack(VoiceTracks.ASR),
681
+ spanId: "asr-2",
682
+ status: "ok"
683
+ },
684
+ {
685
+ type: "span.end",
686
+ ts: at.inputEnd,
687
+ track: userTrack(VoiceTracks.Input),
688
+ spanId: "input",
689
+ status: "ok"
690
+ },
691
+ {
692
+ type: "span.begin",
693
+ ts: at.inputEnd,
694
+ track: trackPath(AgentTracks.Turn, { agent: "agent" }),
695
+ spanId: "turn",
696
+ name: AgentNames.ChatTurn,
697
+ ids: turn,
698
+ links: [{
699
+ rel: "caused-by",
700
+ to: { spanId: "input" }
701
+ }]
702
+ },
703
+ {
704
+ type: "span.begin",
705
+ ts: 5550,
706
+ track: llm,
707
+ spanId: "llm-1",
708
+ parentSpanId: "turn",
709
+ name: AgentNames.ModelRequest,
710
+ ids: turn,
711
+ attrs: { [ATTR_GEN_AI_REQUEST_MODEL]: "demo-model" }
712
+ },
713
+ {
714
+ type: "instant",
715
+ ts: 6100,
716
+ track: llm,
717
+ spanId: "llm-1",
718
+ name: AgentNames.LLMFirstChunk
719
+ },
720
+ {
721
+ type: "span.begin",
722
+ ts: 6200,
723
+ track: trackPath(AgentTracks.Tools, { agent: "agent" }),
724
+ spanId: "tool-1",
725
+ parentSpanId: "llm-1",
726
+ name: "web_search",
727
+ ids: turn
728
+ },
729
+ {
730
+ type: "span.end",
731
+ ts: 6600,
732
+ track: trackPath(AgentTracks.Tools, { agent: "agent" }),
733
+ spanId: "tool-1",
734
+ status: "ok"
735
+ },
736
+ {
737
+ type: "span.end",
738
+ ts: 6800,
739
+ track: llm,
740
+ spanId: "llm-1",
741
+ status: "ok",
742
+ attrs: {
743
+ [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: 1200,
744
+ [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: 86
745
+ }
746
+ },
747
+ {
748
+ type: "span.begin",
749
+ ts: at.inputEnd,
750
+ track: agentTrack(VoiceTracks.Output),
751
+ spanId: "output",
752
+ name: VoiceNames.SpeechOutput,
753
+ ids: {
754
+ ...agent,
755
+ ...turn
756
+ }
757
+ },
758
+ {
759
+ type: "span.begin",
760
+ ts: 6800,
761
+ track: agentTrack(VoiceTracks.TTS),
762
+ spanId: "tts-1",
763
+ name: VoiceNames.TTSRequest,
764
+ ids: {
765
+ ...agent,
766
+ ...turn,
767
+ segment: "s1"
768
+ }
769
+ },
770
+ {
771
+ type: "span.end",
772
+ ts: at.playbackStart,
773
+ track: agentTrack(VoiceTracks.TTS),
774
+ spanId: "tts-1",
775
+ status: "ok"
776
+ },
777
+ {
778
+ type: "span.end",
779
+ ts: at.playbackStart,
780
+ track: trackPath(AgentTracks.Turn, { agent: "agent" }),
781
+ spanId: "turn",
782
+ status: "ok"
783
+ },
784
+ {
785
+ type: "span.begin",
786
+ ts: at.playbackStart,
787
+ track: agentTrack(VoiceTracks.Playback),
788
+ spanId: "playback-1",
789
+ name: VoiceNames.Playback,
790
+ ids: {
791
+ ...agent,
792
+ ...turn,
793
+ segment: "s1"
794
+ }
795
+ },
796
+ {
797
+ type: "instant",
798
+ ts: at.playbackStart,
799
+ track: trackPath(VoiceTracks.Floor, { conversation: "c1" }),
800
+ name: VoiceNames.FloorTaken,
801
+ attrs: { actor: "agent" }
802
+ },
803
+ {
804
+ type: "sample.chunk",
805
+ ts: at.playbackStart,
806
+ track: agentTrack(VoiceTracks.Playback),
807
+ ids: agent,
808
+ offsetsMs: played.map((index) => long_leading_silence_default.times[index] - 884),
809
+ values: { [VoiceSeries.Level]: played.map((index) => long_leading_silence_default.level[index]) }
810
+ },
811
+ {
812
+ type: "span.end",
813
+ ts: at.playbackEnd,
814
+ track: agentTrack(VoiceTracks.Playback),
815
+ spanId: "playback-1",
816
+ status: "ok"
817
+ },
818
+ {
819
+ type: "span.end",
820
+ ts: at.playbackEnd,
821
+ track: agentTrack(VoiceTracks.Output),
822
+ spanId: "output",
823
+ status: "ok"
824
+ },
825
+ {
826
+ type: "span.begin",
827
+ ts: at.openRequestStart,
828
+ track: llm,
829
+ spanId: "llm-2",
830
+ name: AgentNames.ModelRequest,
831
+ ids: {
832
+ turn: "i2",
833
+ conversation: "c1"
834
+ }
835
+ }
836
+ ];
837
+ }
838
+ //#endregion
839
+ //#region src/testing/index.ts
840
+ /**
841
+ * Returns a function that completes record inputs as the records of one source epoch, with `seq` from 0.
842
+ *
843
+ * @example
844
+ * const stamp = createRecordStamper({ source: 'tab:a' })
845
+ * stamp({ type: 'span.begin', ts: 0, track: 'agents/agent/llm', spanId: 's', name: 'chat' })
846
+ * // => { clock: 'mono:collector', type: 'span.begin', ..., source: 'tab:a', epoch: 'e1', seq: 0 }
847
+ */
848
+ function createRecordStamper(options = {}) {
849
+ const { source = "window:main", epoch = "e1", clock = "mono:collector" } = options;
850
+ let seq = 0;
851
+ return (input) => ({
852
+ clock,
853
+ ...input,
854
+ source,
855
+ epoch,
856
+ seq: seq++
857
+ });
858
+ }
859
+ /**
860
+ * Reads record inputs into the timeline state that a viewer sees, with the definitions of `profiles` first.
861
+ *
862
+ * @example
863
+ * const { state } = readTimeline([{ type: 'span.begin', ts: 0, track: 'agents/agent/llm', spanId: 's', name: 'chat' }], { profiles: [agentProfile] })
864
+ * state.spans.size
865
+ * // => 1
866
+ */
867
+ function readTimeline(inputs, options = {}) {
868
+ const stamp = createRecordStamper(options);
869
+ const records = [...(options.profiles ?? []).flatMap((profile) => definitionRecordsOf(profile, 0)), ...inputs].map(stamp);
870
+ const timeline = createTimelineProjection();
871
+ const reader = new TraceReader([timeline], options.clock ?? "mono:collector");
872
+ reader.handleRecords(records);
873
+ return {
874
+ state: reader.view(timeline),
875
+ indexes: reader.indexes,
876
+ records
877
+ };
878
+ }
879
+ //#endregion
880
+ export { LONG_LEADING_SILENCE, VOICE_TURN, createRecordStamper, readTimeline, voiceTurnRecords };