@memberjunction/ai-realtime-client 6.2.0-edge.2 → 6.2.0-edge.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +156 -29
  2. package/dist/audio/audioMeter.d.ts +71 -0
  3. package/dist/audio/audioMeter.d.ts.map +1 -1
  4. package/dist/audio/audioMeter.js +83 -0
  5. package/dist/audio/audioMeter.js.map +1 -1
  6. package/dist/audio/mediaElementAudioRouter.d.ts +41 -0
  7. package/dist/audio/mediaElementAudioRouter.d.ts.map +1 -0
  8. package/dist/audio/mediaElementAudioRouter.js +82 -0
  9. package/dist/audio/mediaElementAudioRouter.js.map +1 -0
  10. package/dist/audio/micCapture.d.ts +12 -3
  11. package/dist/audio/micCapture.d.ts.map +1 -1
  12. package/dist/audio/micCapture.js +15 -1
  13. package/dist/audio/micCapture.js.map +1 -1
  14. package/dist/audio/pcmPlayback.d.ts +72 -4
  15. package/dist/audio/pcmPlayback.d.ts.map +1 -1
  16. package/dist/audio/pcmPlayback.js +101 -1
  17. package/dist/audio/pcmPlayback.js.map +1 -1
  18. package/dist/drivers/assemblyAIRealtimeClient.d.ts +2 -0
  19. package/dist/drivers/assemblyAIRealtimeClient.d.ts.map +1 -1
  20. package/dist/drivers/assemblyAIRealtimeClient.js +14 -0
  21. package/dist/drivers/assemblyAIRealtimeClient.js.map +1 -1
  22. package/dist/drivers/elevenLabsRealtimeClient.d.ts +2 -0
  23. package/dist/drivers/elevenLabsRealtimeClient.d.ts.map +1 -1
  24. package/dist/drivers/elevenLabsRealtimeClient.js +14 -0
  25. package/dist/drivers/elevenLabsRealtimeClient.js.map +1 -1
  26. package/dist/drivers/geminiAvatarOutput.d.ts +132 -0
  27. package/dist/drivers/geminiAvatarOutput.d.ts.map +1 -0
  28. package/dist/drivers/geminiAvatarOutput.js +310 -0
  29. package/dist/drivers/geminiAvatarOutput.js.map +1 -0
  30. package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts +38 -0
  31. package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts.map +1 -0
  32. package/dist/drivers/geminiEnterpriseRealtimeClient.js +107 -0
  33. package/dist/drivers/geminiEnterpriseRealtimeClient.js.map +1 -0
  34. package/dist/drivers/geminiRealtimeClient.d.ts +314 -48
  35. package/dist/drivers/geminiRealtimeClient.d.ts.map +1 -1
  36. package/dist/drivers/geminiRealtimeClient.js +759 -176
  37. package/dist/drivers/geminiRealtimeClient.js.map +1 -1
  38. package/dist/drivers/openAILiveClient.d.ts +5 -8
  39. package/dist/drivers/openAILiveClient.d.ts.map +1 -1
  40. package/dist/drivers/openAILiveClient.js +19 -32
  41. package/dist/drivers/openAILiveClient.js.map +1 -1
  42. package/dist/drivers/openAIRealtimeClient.d.ts +23 -26
  43. package/dist/drivers/openAIRealtimeClient.d.ts.map +1 -1
  44. package/dist/drivers/openAIRealtimeClient.js +42 -57
  45. package/dist/drivers/openAIRealtimeClient.js.map +1 -1
  46. package/dist/generic/baseRealtimeClient.d.ts +188 -30
  47. package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
  48. package/dist/generic/baseRealtimeClient.js +250 -14
  49. package/dist/generic/baseRealtimeClient.js.map +1 -1
  50. package/dist/generic/openAIProtocolClient.d.ts +57 -1
  51. package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
  52. package/dist/generic/openAIProtocolClient.js +89 -4
  53. package/dist/generic/openAIProtocolClient.js.map +1 -1
  54. package/dist/index.d.ts +2 -3
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +3 -3
  57. package/dist/index.js.map +1 -1
  58. package/dist/media/attachVideoSource.d.ts +23 -0
  59. package/dist/media/attachVideoSource.d.ts.map +1 -0
  60. package/dist/media/attachVideoSource.js +49 -0
  61. package/dist/media/attachVideoSource.js.map +1 -0
  62. package/dist/media/channelVideoSource.d.ts +110 -14
  63. package/dist/media/channelVideoSource.d.ts.map +1 -1
  64. package/dist/media/channelVideoSource.js +183 -18
  65. package/dist/media/channelVideoSource.js.map +1 -1
  66. package/dist/media/decoders/frameScheduler.d.ts +119 -0
  67. package/dist/media/decoders/frameScheduler.d.ts.map +1 -0
  68. package/dist/media/decoders/frameScheduler.js +238 -0
  69. package/dist/media/decoders/frameScheduler.js.map +1 -0
  70. package/dist/media/decoders/imageFrameDecoder.d.ts +58 -0
  71. package/dist/media/decoders/imageFrameDecoder.d.ts.map +1 -0
  72. package/dist/media/decoders/imageFrameDecoder.js +110 -0
  73. package/dist/media/decoders/imageFrameDecoder.js.map +1 -0
  74. package/dist/media/decoders/mseFmp4Decoder.d.ts +130 -0
  75. package/dist/media/decoders/mseFmp4Decoder.d.ts.map +1 -0
  76. package/dist/media/decoders/mseFmp4Decoder.js +402 -0
  77. package/dist/media/decoders/mseFmp4Decoder.js.map +1 -0
  78. package/dist/media/decoders/streamCanvas.d.ts +46 -0
  79. package/dist/media/decoders/streamCanvas.d.ts.map +1 -0
  80. package/dist/media/decoders/streamCanvas.js +163 -0
  81. package/dist/media/decoders/streamCanvas.js.map +1 -0
  82. package/dist/media/decoders/videoMimeTypes.d.ts +29 -0
  83. package/dist/media/decoders/videoMimeTypes.d.ts.map +1 -0
  84. package/dist/media/decoders/videoMimeTypes.js +50 -0
  85. package/dist/media/decoders/videoMimeTypes.js.map +1 -0
  86. package/dist/media/decoders/webCodecsChunkDecoder.d.ts +99 -0
  87. package/dist/media/decoders/webCodecsChunkDecoder.d.ts.map +1 -0
  88. package/dist/media/decoders/webCodecsChunkDecoder.js +265 -0
  89. package/dist/media/decoders/webCodecsChunkDecoder.js.map +1 -0
  90. package/dist/media/displayCapture.d.ts +128 -0
  91. package/dist/media/displayCapture.d.ts.map +1 -0
  92. package/dist/media/displayCapture.js +245 -0
  93. package/dist/media/displayCapture.js.map +1 -0
  94. package/dist/media/frameCapture.d.ts +25 -8
  95. package/dist/media/frameCapture.d.ts.map +1 -1
  96. package/dist/media/frameCapture.js +42 -72
  97. package/dist/media/frameCapture.js.map +1 -1
  98. package/dist/media/frameSampler.d.ts +94 -0
  99. package/dist/media/frameSampler.d.ts.map +1 -0
  100. package/dist/media/frameSampler.js +134 -0
  101. package/dist/media/frameSampler.js.map +1 -0
  102. package/dist/media/index.d.ts +32 -0
  103. package/dist/media/index.d.ts.map +1 -0
  104. package/dist/media/index.js +32 -0
  105. package/dist/media/index.js.map +1 -0
  106. package/dist/media/localMediaController.d.ts +116 -0
  107. package/dist/media/localMediaController.d.ts.map +1 -0
  108. package/dist/media/localMediaController.js +281 -0
  109. package/dist/media/localMediaController.js.map +1 -0
  110. package/dist/media/mediaLayout.d.ts +93 -0
  111. package/dist/media/mediaLayout.d.ts.map +1 -0
  112. package/dist/media/mediaLayout.js +187 -0
  113. package/dist/media/mediaLayout.js.map +1 -0
  114. package/dist/media/mediaPreview.d.ts +94 -0
  115. package/dist/media/mediaPreview.d.ts.map +1 -0
  116. package/dist/media/mediaPreview.js +154 -0
  117. package/dist/media/mediaPreview.js.map +1 -0
  118. package/dist/media/mediaStage.d.ts +99 -0
  119. package/dist/media/mediaStage.d.ts.map +1 -0
  120. package/dist/media/mediaStage.js +171 -0
  121. package/dist/media/mediaStage.js.map +1 -0
  122. package/dist/media/model.d.ts +154 -0
  123. package/dist/media/model.d.ts.map +1 -0
  124. package/dist/media/model.js +9 -0
  125. package/dist/media/model.js.map +1 -0
  126. package/dist/media/playbackClock.d.ts +20 -0
  127. package/dist/media/playbackClock.d.ts.map +1 -0
  128. package/dist/media/playbackClock.js +13 -0
  129. package/dist/media/playbackClock.js.map +1 -0
  130. package/dist/media/videoFrameDecoder.d.ts +86 -0
  131. package/dist/media/videoFrameDecoder.d.ts.map +1 -0
  132. package/dist/media/videoFrameDecoder.js +2 -0
  133. package/dist/media/videoFrameDecoder.js.map +1 -0
  134. package/dist/media/videoFrameDecoderRegistry.d.ts +40 -0
  135. package/dist/media/videoFrameDecoderRegistry.d.ts.map +1 -0
  136. package/dist/media/videoFrameDecoderRegistry.js +69 -0
  137. package/dist/media/videoFrameDecoderRegistry.js.map +1 -0
  138. package/dist/media/videoPacing.d.ts +32 -0
  139. package/dist/media/videoPacing.d.ts.map +1 -0
  140. package/dist/media/videoPacing.js +37 -0
  141. package/dist/media/videoPacing.js.map +1 -0
  142. package/dist/media/videoPlayout.d.ts +168 -0
  143. package/dist/media/videoPlayout.d.ts.map +1 -0
  144. package/dist/media/videoPlayout.js +217 -0
  145. package/dist/media/videoPlayout.js.map +1 -0
  146. package/dist/media/videoSourceArbiter.d.ts +250 -0
  147. package/dist/media/videoSourceArbiter.d.ts.map +1 -0
  148. package/dist/media/videoSourceArbiter.js +423 -0
  149. package/dist/media/videoSourceArbiter.js.map +1 -0
  150. package/dist/testing/conformanceAssertions.d.ts +25 -0
  151. package/dist/testing/conformanceAssertions.d.ts.map +1 -0
  152. package/dist/testing/conformanceAssertions.js +64 -0
  153. package/dist/testing/conformanceAssertions.js.map +1 -0
  154. package/dist/testing/conformanceFixtures.d.ts +76 -0
  155. package/dist/testing/conformanceFixtures.d.ts.map +1 -0
  156. package/dist/testing/conformanceFixtures.js +169 -0
  157. package/dist/testing/conformanceFixtures.js.map +1 -0
  158. package/dist/testing/conformanceGates.d.ts +32 -0
  159. package/dist/testing/conformanceGates.d.ts.map +1 -0
  160. package/dist/testing/conformanceGates.js +35 -0
  161. package/dist/testing/conformanceGates.js.map +1 -0
  162. package/dist/testing/conformanceMicrophone.d.ts +10 -0
  163. package/dist/testing/conformanceMicrophone.d.ts.map +1 -0
  164. package/dist/testing/conformanceMicrophone.js +71 -0
  165. package/dist/testing/conformanceMicrophone.js.map +1 -0
  166. package/dist/testing/conformanceTimeline.d.ts +128 -0
  167. package/dist/testing/conformanceTimeline.d.ts.map +1 -0
  168. package/dist/testing/conformanceTimeline.js +32 -0
  169. package/dist/testing/conformanceTimeline.js.map +1 -0
  170. package/dist/testing/conformanceVideoStream.d.ts +29 -0
  171. package/dist/testing/conformanceVideoStream.d.ts.map +1 -0
  172. package/dist/testing/conformanceVideoStream.js +39 -0
  173. package/dist/testing/conformanceVideoStream.js.map +1 -0
  174. package/dist/testing/index.d.ts +29 -0
  175. package/dist/testing/index.d.ts.map +1 -0
  176. package/dist/testing/index.js +28 -0
  177. package/dist/testing/index.js.map +1 -0
  178. package/dist/testing/realtimeVideoConformance.d.ts +23 -0
  179. package/dist/testing/realtimeVideoConformance.d.ts.map +1 -0
  180. package/dist/testing/realtimeVideoConformance.js +139 -0
  181. package/dist/testing/realtimeVideoConformance.js.map +1 -0
  182. package/dist/testing/realtimeVideoConformanceChecks.d.ts +4 -0
  183. package/dist/testing/realtimeVideoConformanceChecks.d.ts.map +1 -0
  184. package/dist/testing/realtimeVideoConformanceChecks.js +164 -0
  185. package/dist/testing/realtimeVideoConformanceChecks.js.map +1 -0
  186. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts +4 -0
  187. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts.map +1 -0
  188. package/dist/testing/realtimeVideoConformanceFrameChecks.js +63 -0
  189. package/dist/testing/realtimeVideoConformanceFrameChecks.js.map +1 -0
  190. package/dist/testing/realtimeVideoConformanceSession.d.ts +108 -0
  191. package/dist/testing/realtimeVideoConformanceSession.d.ts.map +1 -0
  192. package/dist/testing/realtimeVideoConformanceSession.js +270 -0
  193. package/dist/testing/realtimeVideoConformanceSession.js.map +1 -0
  194. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts +4 -0
  195. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts.map +1 -0
  196. package/dist/testing/realtimeVideoConformanceTurnChecks.js +248 -0
  197. package/dist/testing/realtimeVideoConformanceTurnChecks.js.map +1 -0
  198. package/dist/testing/realtimeVideoConformanceTypes.d.ts +155 -0
  199. package/dist/testing/realtimeVideoConformanceTypes.d.ts.map +1 -0
  200. package/dist/testing/realtimeVideoConformanceTypes.js +2 -0
  201. package/dist/testing/realtimeVideoConformanceTypes.js.map +1 -0
  202. package/dist/testing/recordingPlayout.d.ts +84 -0
  203. package/dist/testing/recordingPlayout.d.ts.map +1 -0
  204. package/dist/testing/recordingPlayout.js +120 -0
  205. package/dist/testing/recordingPlayout.js.map +1 -0
  206. package/package.json +29 -4
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @fileoverview The ordered record of one conformance session: what the driver did with the kit's recorders (the
3
+ * avatar's video players and the PCM playback), what the client emitted, and what it logged. Checks read it by kind and
4
+ * from a mark, so "since the barge-in" and "in this turn" are one slice.
5
+ *
6
+ * @module @memberjunction/ai-realtime-client/testing
7
+ */
8
+ import type { RealtimeTrack, RealtimeVideoFrame } from '@memberjunction/ai';
9
+ import type { RealtimeClientError, RealtimeClientState, RealtimeClientUsage } from '../generic/baseRealtimeClient.js';
10
+ import type { MediaVideoSource } from '../media/model.js';
11
+ import type { VideoPlayoutOptions } from '../media/videoPlayout.js';
12
+ /**
13
+ * One thing that happened in a conformance session, in the order it happened. `Player` numbers the video players the
14
+ * driver created in the session, from 0.
15
+ */
16
+ export type RealtimeVideoConformanceEvent =
17
+ /** The driver created a video player. */
18
+ {
19
+ Kind: 'player-created';
20
+ Player: number;
21
+ Options: VideoPlayoutOptions;
22
+ }
23
+ /** The driver handed a frame of video to a player. */
24
+ | {
25
+ Kind: 'player-append';
26
+ Player: number;
27
+ Frame: RealtimeVideoFrame;
28
+ }
29
+ /** The driver told a player the turn's video is all in. */
30
+ | {
31
+ Kind: 'player-end-of-turn';
32
+ Player: number;
33
+ }
34
+ /** The driver dropped what a player had not played (barge-in). */
35
+ | {
36
+ Kind: 'player-flush';
37
+ Player: number;
38
+ }
39
+ /** The driver released a player. */
40
+ | {
41
+ Kind: 'player-dispose';
42
+ Player: number;
43
+ }
44
+ /** The driver changed whether a player plays the video's audio. */
45
+ | {
46
+ Kind: 'player-carries-voice';
47
+ Player: number;
48
+ CarriesVoice: boolean;
49
+ }
50
+ /** The driver queued PCM on the voice playback, with its media time when the driver gave one. */
51
+ | {
52
+ Kind: 'voice-enqueue';
53
+ Data: ArrayBuffer;
54
+ MediaTimeMs?: number;
55
+ }
56
+ /** The driver dropped the PCM the voice playback had not played. */
57
+ | {
58
+ Kind: 'voice-flush';
59
+ }
60
+ /** The driver closed the voice playback. */
61
+ | {
62
+ Kind: 'voice-close';
63
+ }
64
+ /** The client reported a state. */
65
+ | {
66
+ Kind: 'state';
67
+ State: RealtimeClientState;
68
+ }
69
+ /** The client handed over the agent's video (`OnRemoteVideo`). */
70
+ | {
71
+ Kind: 'remote-video';
72
+ Video: MediaVideoSource;
73
+ }
74
+ /** The client reported a barge-in (`OnInterruption`). */
75
+ | {
76
+ Kind: 'interruption';
77
+ }
78
+ /** The client reported usage (`OnUsage`). */
79
+ | {
80
+ Kind: 'usage';
81
+ Usage: RealtimeClientUsage;
82
+ }
83
+ /** The client reported a track's state (`OnTrackStateChange`). */
84
+ | {
85
+ Kind: 'track';
86
+ Track: RealtimeTrack;
87
+ }
88
+ /** The client reported an error (`OnError`). */
89
+ | {
90
+ Kind: 'error';
91
+ Error: RealtimeClientError;
92
+ }
93
+ /** Something logged a warning while the session ran. */
94
+ | {
95
+ Kind: 'warn';
96
+ Message: string;
97
+ }
98
+ /** Something logged an info line while the session ran. */
99
+ | {
100
+ Kind: 'info';
101
+ Message: string;
102
+ };
103
+ /** The kinds of {@link RealtimeVideoConformanceEvent}. */
104
+ export type RealtimeVideoConformanceEventKind = RealtimeVideoConformanceEvent['Kind'];
105
+ /** The event of one kind. */
106
+ export type RealtimeVideoConformanceEventOf<K extends RealtimeVideoConformanceEventKind> = Extract<RealtimeVideoConformanceEvent, {
107
+ Kind: K;
108
+ }>;
109
+ /** An ordered, append-only record of a conformance session, shared by its recorders and its observers. */
110
+ export declare class RealtimeVideoConformanceTimeline {
111
+ private readonly entries;
112
+ /** Every event, in order. */
113
+ get Entries(): readonly RealtimeVideoConformanceEvent[];
114
+ /** Appends one event. */
115
+ Record(event: RealtimeVideoConformanceEvent): void;
116
+ /** The position the next event will take. Pass it to {@link Of} or {@link Since} to read only what came after. */
117
+ Mark(): number;
118
+ /** The events from a mark on. */
119
+ Since(mark: number): readonly RealtimeVideoConformanceEvent[];
120
+ /**
121
+ * The events of one kind, in order, from a mark on.
122
+ *
123
+ * @param kind The kind to keep.
124
+ * @param since A {@link Mark}; default the start of the session.
125
+ */
126
+ Of<K extends RealtimeVideoConformanceEventKind>(kind: K, since?: number): RealtimeVideoConformanceEventOf<K>[];
127
+ }
128
+ //# sourceMappingURL=conformanceTimeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformanceTimeline.d.ts","sourceRoot":"","sources":["../../src/testing/conformanceTimeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /** An ordered, append-only record of a conformance session, shared by its recorders and its observers. */
2
+ export class RealtimeVideoConformanceTimeline {
3
+ constructor() {
4
+ this.entries = [];
5
+ }
6
+ /** Every event, in order. */
7
+ get Entries() {
8
+ return this.entries;
9
+ }
10
+ /** Appends one event. */
11
+ Record(event) {
12
+ this.entries.push(event);
13
+ }
14
+ /** The position the next event will take. Pass it to {@link Of} or {@link Since} to read only what came after. */
15
+ Mark() {
16
+ return this.entries.length;
17
+ }
18
+ /** The events from a mark on. */
19
+ Since(mark) {
20
+ return this.entries.slice(mark);
21
+ }
22
+ /**
23
+ * The events of one kind, in order, from a mark on.
24
+ *
25
+ * @param kind The kind to keep.
26
+ * @param since A {@link Mark}; default the start of the session.
27
+ */
28
+ Of(kind, since = 0) {
29
+ return this.entries.slice(since).filter((event) => event.Kind === kind);
30
+ }
31
+ }
32
+ //# sourceMappingURL=conformanceTimeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformanceTimeline.js","sourceRoot":"","sources":["../../src/testing/conformanceTimeline.ts"],"names":[],"mappings":"AA0DA,0GAA0G;AAC1G,MAAM,OAAO,gCAAgC;IAA7C;QACqB,YAAO,GAAoC,EAAE,CAAC;IA+BnE,CAAC;IA7BG,6BAA6B;IAC7B,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,yBAAyB;IAClB,MAAM,CAAC,KAAoC;QAC9C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,kHAAkH;IAC3G,IAAI;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,iCAAiC;IAC1B,KAAK,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACI,EAAE,CAA8C,IAAO,EAAE,QAAgB,CAAC;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAA+C,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACzH,CAAC;CACJ"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview The video a conformance session's model sends, in the provider's form: an fMP4 init segment then
3
+ * one-frame fragments, or encoded chunks from a key frame, or images. Each call continues the same 24 fps stream, so every
4
+ * frame's bytes are distinct and its time follows the last.
5
+ *
6
+ * @module @memberjunction/ai-realtime-client/testing
7
+ */
8
+ import type { RealtimeVideoFrame, RealtimeVideoFrameKind } from '@memberjunction/ai';
9
+ /** One session's video stream, of one frame kind. */
10
+ export declare class ConformanceVideoStream {
11
+ readonly Kind: RealtimeVideoFrameKind;
12
+ readonly CarriesVoice: boolean;
13
+ /** The number of the next video frame (an fMP4 fragment, a chunk or an image), from 0. */
14
+ private next;
15
+ /**
16
+ * @param Kind The form the provider's model sends its video in.
17
+ * @param CarriesVoice Whether an fMP4 stream's init segment has the voice's audio track.
18
+ */
19
+ constructor(Kind: RealtimeVideoFrameKind, CarriesVoice: boolean);
20
+ /** Where the next frame sits on the stream's media timeline, in ms: the time a voice chunk sent now goes with. */
21
+ get NextTimeMs(): number;
22
+ /** The frame a stream starts with: an fMP4 init segment, or the first chunk (a key frame) or image. */
23
+ Start(): RealtimeVideoFrame;
24
+ /** The stream's next `count` video frames: one-frame fMP4 fragments, chunks or images. */
25
+ Frames(count: number): RealtimeVideoFrame[];
26
+ }
27
+ /** The seconds of video some frames carry: 1/24 s each, an fMP4 init segment none. */
28
+ export declare function SecondsOfVideo(frames: readonly RealtimeVideoFrame[]): number;
29
+ //# sourceMappingURL=conformanceVideoStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformanceVideoStream.d.ts","sourceRoot":"","sources":["../../src/testing/conformanceVideoStream.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAWrF,qDAAqD;AACrD,qBAAa,sBAAsB;aAQH,IAAI,EAAE,sBAAsB;aAAkB,YAAY,EAAE,OAAO;IAP/F,0FAA0F;IAC1F,OAAO,CAAC,IAAI,CAAK;IAEjB;;;OAGG;gBACyB,IAAI,EAAE,sBAAsB,EAAkB,YAAY,EAAE,OAAO;IAE/F,kHAAkH;IAClH,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,uGAAuG;IAChG,KAAK,IAAI,kBAAkB;IAOlC,0FAA0F;IACnF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE;CAUrD;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAE5E"}
@@ -0,0 +1,39 @@
1
+ import { CONFORMANCE_FMP4_FRAME_SECONDS, ConformanceChunkFrames, ConformanceFmp4InitSegment, ConformanceFmp4VideoFragment, ConformanceImageFrame, Fmp4Frame, FrameTimeMs, } from './conformanceFixtures.js';
2
+ /** One session's video stream, of one frame kind. */
3
+ export class ConformanceVideoStream {
4
+ /**
5
+ * @param Kind The form the provider's model sends its video in.
6
+ * @param CarriesVoice Whether an fMP4 stream's init segment has the voice's audio track.
7
+ */
8
+ constructor(Kind, CarriesVoice) {
9
+ this.Kind = Kind;
10
+ this.CarriesVoice = CarriesVoice;
11
+ /** The number of the next video frame (an fMP4 fragment, a chunk or an image), from 0. */
12
+ this.next = 0;
13
+ }
14
+ /** Where the next frame sits on the stream's media timeline, in ms: the time a voice chunk sent now goes with. */
15
+ get NextTimeMs() {
16
+ return FrameTimeMs(this.next);
17
+ }
18
+ /** The frame a stream starts with: an fMP4 init segment, or the first chunk (a key frame) or image. */
19
+ Start() {
20
+ if (this.Kind === 'fmp4') {
21
+ return Fmp4Frame(ConformanceFmp4InitSegment(this.CarriesVoice));
22
+ }
23
+ return this.Frames(1)[0];
24
+ }
25
+ /** The stream's next `count` video frames: one-frame fMP4 fragments, chunks or images. */
26
+ Frames(count) {
27
+ const first = this.next;
28
+ this.next += count;
29
+ if (this.Kind === 'chunk') {
30
+ return ConformanceChunkFrames(count, { FirstIndex: first });
31
+ }
32
+ return Array.from({ length: count }, (_, i) => this.Kind === 'image' ? ConformanceImageFrame(first + i) : Fmp4Frame(ConformanceFmp4VideoFragment(1, first + i + 1)));
33
+ }
34
+ }
35
+ /** The seconds of video some frames carry: 1/24 s each, an fMP4 init segment none. */
36
+ export function SecondsOfVideo(frames) {
37
+ return frames.filter((frame) => !(frame.Kind === 'fmp4' && frame.Piece === 'init')).length * CONFORMANCE_FMP4_FRAME_SECONDS;
38
+ }
39
+ //# sourceMappingURL=conformanceVideoStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformanceVideoStream.js","sourceRoot":"","sources":["../../src/testing/conformanceVideoStream.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,8BAA8B,EAC9B,sBAAsB,EACtB,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,SAAS,EACT,WAAW,GACd,MAAM,uBAAuB,CAAC;AAE/B,qDAAqD;AACrD,MAAM,OAAO,sBAAsB;IAI/B;;;OAGG;IACH,YAA4B,IAA4B,EAAkB,YAAqB;QAAnE,SAAI,GAAJ,IAAI,CAAwB;QAAkB,iBAAY,GAAZ,YAAY,CAAS;QAP/F,0FAA0F;QAClF,SAAI,GAAG,CAAC,CAAC;IAMiF,CAAC;IAEnG,kHAAkH;IAClH,IAAW,UAAU;QACjB,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,uGAAuG;IAChG,KAAK;QACR,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC,0BAA0B,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,0FAA0F;IACnF,MAAM,CAAC,KAAa;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACxB,OAAO,sBAAsB,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAsB,EAAE,CAC9D,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CACvH,CAAC;IACN,CAAC;CACJ;AAED,sFAAsF;AACtF,MAAM,UAAU,cAAc,CAAC,MAAqC;IAChE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,8BAA8B,CAAC;AAChI,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview The `@memberjunction/ai-realtime-client/testing` entry point: the video provider conformance kit. A
3
+ * provider's test runs it against the provider's client driver to prove the driver meets the realtime video contract:
4
+ * what it hands the host, where the model's video and voice go, what barge-in, turn ends, resumes and Disconnect do to
5
+ * them, and the generated video seconds it reports.
6
+ *
7
+ * The checks (VC01-VC15, VF01-VF02) take the agent's video as Core's `RealtimeVideoFrame`s, in whichever form the
8
+ * provider's model sends it: fragmented MP4, encoded chunks or images.
9
+ *
10
+ * The kit needs no test framework: {@link RunRealtimeVideoConformance} resolves to results, and
11
+ * {@link ListRealtimeVideoConformanceChecks} gives a runner one test per check. A provider writes a harness
12
+ * ({@link IRealtimeVideoConformanceHarness}): what its server mints, its client driver with a fake transport and its
13
+ * creation seams wired to the kit's recorders, and the model's side of the wire.
14
+ *
15
+ * Everything reachable from here may import only other `/testing` modules, `/media`, `src/audio/`,
16
+ * `generic/baseRealtimeClient`, `@memberjunction/ai`, `@memberjunction/global` and `rxjs`: no driver, no
17
+ * `@google/genai`, no test framework. `testing-entry-boundary.test.ts` fails the build otherwise. The main entry does
18
+ * not export the kit, so apps never bundle it.
19
+ *
20
+ * @module @memberjunction/ai-realtime-client/testing
21
+ */
22
+ export { RealtimeVideoConformanceError } from './conformanceAssertions.js';
23
+ export { CONFORMANCE_FMP4_FRAME_SECONDS, ConformanceChunkFrames, ConformanceFmp4AudioFragment, ConformanceFmp4InitSegment, ConformanceFmp4VideoFragment, ConformanceImageFrame, ConformancePcm, type ConformanceChunkOptions, } from './conformanceFixtures.js';
24
+ export { CreateConformanceMicrophone } from './conformanceMicrophone.js';
25
+ export { RealtimeVideoConformanceTimeline, type RealtimeVideoConformanceEvent, type RealtimeVideoConformanceEventKind, type RealtimeVideoConformanceEventOf, } from './conformanceTimeline.js';
26
+ export { RecordingPcmPlayback, RecordingVideoPlayout } from './recordingPlayout.js';
27
+ export { ListRealtimeVideoConformanceChecks, REALTIME_VIDEO_CONFORMANCE_CHECKS, RunRealtimeVideoConformance } from './realtimeVideoConformance.js';
28
+ export type { IRealtimeVideoConformanceHarness, RealtimeVideoConformanceCheck, RealtimeVideoConformanceCheckRun, RealtimeVideoConformanceDriverFactory, RealtimeVideoConformanceGrant, RealtimeVideoConformanceMedia, RealtimeVideoConformanceResult, RealtimeVideoConformanceTraits, } from './realtimeVideoConformanceTypes.js';
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EACH,8BAA8B,EAC9B,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,cAAc,EACd,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACH,gCAAgC,EAChC,KAAK,6BAA6B,EAClC,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,GACvC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,kCAAkC,EAAE,iCAAiC,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAChJ,YAAY,EACR,gCAAgC,EAChC,6BAA6B,EAC7B,gCAAgC,EAChC,qCAAqC,EACrC,6BAA6B,EAC7B,6BAA6B,EAC7B,8BAA8B,EAC9B,8BAA8B,GACjC,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview The `@memberjunction/ai-realtime-client/testing` entry point: the video provider conformance kit. A
3
+ * provider's test runs it against the provider's client driver to prove the driver meets the realtime video contract:
4
+ * what it hands the host, where the model's video and voice go, what barge-in, turn ends, resumes and Disconnect do to
5
+ * them, and the generated video seconds it reports.
6
+ *
7
+ * The checks (VC01-VC15, VF01-VF02) take the agent's video as Core's `RealtimeVideoFrame`s, in whichever form the
8
+ * provider's model sends it: fragmented MP4, encoded chunks or images.
9
+ *
10
+ * The kit needs no test framework: {@link RunRealtimeVideoConformance} resolves to results, and
11
+ * {@link ListRealtimeVideoConformanceChecks} gives a runner one test per check. A provider writes a harness
12
+ * ({@link IRealtimeVideoConformanceHarness}): what its server mints, its client driver with a fake transport and its
13
+ * creation seams wired to the kit's recorders, and the model's side of the wire.
14
+ *
15
+ * Everything reachable from here may import only other `/testing` modules, `/media`, `src/audio/`,
16
+ * `generic/baseRealtimeClient`, `@memberjunction/ai`, `@memberjunction/global` and `rxjs`: no driver, no
17
+ * `@google/genai`, no test framework. `testing-entry-boundary.test.ts` fails the build otherwise. The main entry does
18
+ * not export the kit, so apps never bundle it.
19
+ *
20
+ * @module @memberjunction/ai-realtime-client/testing
21
+ */
22
+ export { RealtimeVideoConformanceError } from './conformanceAssertions.js';
23
+ export { CONFORMANCE_FMP4_FRAME_SECONDS, ConformanceChunkFrames, ConformanceFmp4AudioFragment, ConformanceFmp4InitSegment, ConformanceFmp4VideoFragment, ConformanceImageFrame, ConformancePcm, } from './conformanceFixtures.js';
24
+ export { CreateConformanceMicrophone } from './conformanceMicrophone.js';
25
+ export { RealtimeVideoConformanceTimeline, } from './conformanceTimeline.js';
26
+ export { RecordingPcmPlayback, RecordingVideoPlayout } from './recordingPlayout.js';
27
+ export { ListRealtimeVideoConformanceChecks, REALTIME_VIDEO_CONFORMANCE_CHECKS, RunRealtimeVideoConformance } from './realtimeVideoConformance.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EACH,8BAA8B,EAC9B,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,cAAc,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACH,gCAAgC,GAInC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,kCAAkC,EAAE,iCAAiC,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { RealtimeVideoConformanceCheck, RealtimeVideoConformanceCheckRun, RealtimeVideoConformanceDriverFactory, RealtimeVideoConformanceResult } from './realtimeVideoConformanceTypes.js';
2
+ /** Every check of the kit, VC01-VC15 then VF01-VF02, in the order they run. */
3
+ export declare const REALTIME_VIDEO_CONFORMANCE_CHECKS: readonly RealtimeVideoConformanceCheck[];
4
+ /**
5
+ * Runs every check against a provider, one at a time, each on a new harness from `driverFactory`, and resolves to one
6
+ * result per check, in order. Never rejects: a check that can't run is Skipped with the reason, and any error makes its
7
+ * check Failed with the rule it broke. Each harness is disposed after its check.
8
+ *
9
+ * @param driverFactory Makes the provider's harness; called once per check.
10
+ */
11
+ export declare function RunRealtimeVideoConformance(driverFactory: RealtimeVideoConformanceDriverFactory): Promise<RealtimeVideoConformanceResult[]>;
12
+ /**
13
+ * The checks bound to a provider, for a test runner to register one test each. A check whose `SkipReason` is set has a
14
+ * `Run` that does nothing; register it as a conditional skip (vitest: `it.skipIf(check.SkipReason !== null)`), since the
15
+ * harness's traits and methods decide it, not as a disabled test. `Run` makes a new harness, runs the check, disposes
16
+ * the harness, and rejects with a {@link RealtimeVideoConformanceError} when the provider breaks a rule.
17
+ *
18
+ * `driverFactory` is called once here, to read the harness's traits and methods, and that harness is disposed.
19
+ *
20
+ * @param driverFactory Makes the provider's harness.
21
+ */
22
+ export declare function ListRealtimeVideoConformanceChecks(driverFactory: RealtimeVideoConformanceDriverFactory): RealtimeVideoConformanceCheckRun[];
23
+ //# sourceMappingURL=realtimeVideoConformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtimeVideoConformance.d.ts","sourceRoot":"","sources":["../../src/testing/realtimeVideoConformance.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAER,6BAA6B,EAC7B,gCAAgC,EAChC,qCAAqC,EACrC,8BAA8B,EACjC,MAAM,iCAAiC,CAAC;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,iCAAiC,EAAE,SAAS,6BAA6B,EAIrF,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAAC,aAAa,EAAE,qCAAqC,GAAG,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAMjJ;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAAC,aAAa,EAAE,qCAAqC,GAAG,gCAAgC,EAAE,CAe3I"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * @fileoverview The video conformance kit's runners. {@link RunRealtimeVideoConformance} runs every check against a
3
+ * provider and reports each outcome; {@link ListRealtimeVideoConformanceChecks} hands a test runner the same checks
4
+ * bound to the provider, one test each. Neither needs a test framework.
5
+ *
6
+ * ```ts
7
+ * for (const check of ListRealtimeVideoConformanceChecks(() => new MyProviderHarness())) {
8
+ * it.skipIf(check.SkipReason !== null)(`${check.Id} ${check.Title}`, () => check.Run());
9
+ * }
10
+ * ```
11
+ *
12
+ * @module @memberjunction/ai-realtime-client/testing
13
+ */
14
+ import { RealtimeVideoConformanceError } from './conformanceAssertions.js';
15
+ import { REALTIME_VIDEO_SESSION_CHECKS } from './realtimeVideoConformanceChecks.js';
16
+ import { REALTIME_VIDEO_FRAME_CHECKS } from './realtimeVideoConformanceFrameChecks.js';
17
+ import { REALTIME_VIDEO_TURN_CHECKS } from './realtimeVideoConformanceTurnChecks.js';
18
+ /** Every check of the kit, VC01-VC15 then VF01-VF02, in the order they run. */
19
+ export const REALTIME_VIDEO_CONFORMANCE_CHECKS = [
20
+ ...REALTIME_VIDEO_SESSION_CHECKS,
21
+ ...REALTIME_VIDEO_TURN_CHECKS,
22
+ ...REALTIME_VIDEO_FRAME_CHECKS,
23
+ ];
24
+ /**
25
+ * Runs every check against a provider, one at a time, each on a new harness from `driverFactory`, and resolves to one
26
+ * result per check, in order. Never rejects: a check that can't run is Skipped with the reason, and any error makes its
27
+ * check Failed with the rule it broke. Each harness is disposed after its check.
28
+ *
29
+ * @param driverFactory Makes the provider's harness; called once per check.
30
+ */
31
+ export async function RunRealtimeVideoConformance(driverFactory) {
32
+ const results = [];
33
+ for (const check of REALTIME_VIDEO_CONFORMANCE_CHECKS) {
34
+ results.push(await runForResult(check, driverFactory));
35
+ }
36
+ return results;
37
+ }
38
+ /**
39
+ * The checks bound to a provider, for a test runner to register one test each. A check whose `SkipReason` is set has a
40
+ * `Run` that does nothing; register it as a conditional skip (vitest: `it.skipIf(check.SkipReason !== null)`), since the
41
+ * harness's traits and methods decide it, not as a disabled test. `Run` makes a new harness, runs the check, disposes
42
+ * the harness, and rejects with a {@link RealtimeVideoConformanceError} when the provider breaks a rule.
43
+ *
44
+ * `driverFactory` is called once here, to read the harness's traits and methods, and that harness is disposed.
45
+ *
46
+ * @param driverFactory Makes the provider's harness.
47
+ */
48
+ export function ListRealtimeVideoConformanceChecks(driverFactory) {
49
+ const probe = driverFactory();
50
+ try {
51
+ return REALTIME_VIDEO_CONFORMANCE_CHECKS.map((check) => {
52
+ const skipReason = skipReasonFor(check, probe);
53
+ return {
54
+ Id: check.Id,
55
+ Title: check.Title,
56
+ SkipReason: skipReason,
57
+ Run: () => (skipReason === null ? runCheck(check, driverFactory) : Promise.resolve()),
58
+ };
59
+ });
60
+ }
61
+ finally {
62
+ void disposeHarness(probe);
63
+ }
64
+ }
65
+ /**
66
+ * Why a check doesn't run against a harness: the environment's skip for it, else its gate's reason; `null` when it runs.
67
+ * A harness whose traits can't be read skips with the error.
68
+ */
69
+ function skipReasonFor(check, harness) {
70
+ try {
71
+ const environment = harness.Traits.EnvironmentSkips?.[check.Id];
72
+ return environment !== undefined ? `environment: ${environment}` : check.Gate(harness);
73
+ }
74
+ catch (error) {
75
+ return `the gate failed: ${describeError(error)}`;
76
+ }
77
+ }
78
+ /** Runs one check on a new harness and disposes the harness, whatever happens. */
79
+ async function runCheck(check, driverFactory) {
80
+ const harness = driverFactory();
81
+ try {
82
+ await runOn(check, harness);
83
+ }
84
+ finally {
85
+ await disposeHarness(harness);
86
+ }
87
+ }
88
+ /** Runs one check on a harness. Rejects with a {@link RealtimeVideoConformanceError} whose message starts with the check's id. */
89
+ async function runOn(check, harness) {
90
+ try {
91
+ await check.Run(harness);
92
+ }
93
+ catch (error) {
94
+ throw new RealtimeVideoConformanceError(`${check.Id} (${harness.Name}): ${describeError(error)}`);
95
+ }
96
+ }
97
+ /** One check's outcome for {@link RunRealtimeVideoConformance}: gated and run on one new harness, then disposed. */
98
+ async function runForResult(check, driverFactory) {
99
+ const base = { Id: check.Id, Title: check.Title };
100
+ let harness;
101
+ try {
102
+ harness = driverFactory();
103
+ }
104
+ catch (error) {
105
+ return { ...base, Status: 'Failed', Detail: `the driver factory failed: ${describeError(error)}`, DurationMs: 0 };
106
+ }
107
+ const startedAt = Date.now();
108
+ try {
109
+ const skipReason = skipReasonFor(check, harness);
110
+ if (skipReason !== null) {
111
+ return { ...base, Status: 'Skipped', Detail: skipReason, DurationMs: 0 };
112
+ }
113
+ await runOn(check, harness);
114
+ return { ...base, Status: 'Passed', Detail: null, DurationMs: Date.now() - startedAt };
115
+ }
116
+ catch (error) {
117
+ return { ...base, Status: 'Failed', Detail: describeError(error), DurationMs: Date.now() - startedAt };
118
+ }
119
+ finally {
120
+ await disposeHarness(harness);
121
+ }
122
+ }
123
+ /** Disposes a harness; an error in its Dispose is logged, never thrown over the check's outcome. */
124
+ async function disposeHarness(harness) {
125
+ try {
126
+ await harness.Dispose?.();
127
+ }
128
+ catch (error) {
129
+ console.warn(`[RealtimeVideoConformance] ${harness.Name}'s Dispose failed: ${describeError(error)}`);
130
+ }
131
+ }
132
+ /** A thrown value as text: a conformance failure's message as it is, anything else with its name. */
133
+ function describeError(error) {
134
+ if (error instanceof RealtimeVideoConformanceError) {
135
+ return error.message;
136
+ }
137
+ return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
138
+ }
139
+ //# sourceMappingURL=realtimeVideoConformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtimeVideoConformance.js","sourceRoot":"","sources":["../../src/testing/realtimeVideoConformance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { RealtimeVideoConformanceCheck } from './realtimeVideoConformanceTypes.js';
2
+ /** VC01-VC07, in order. */
3
+ export declare const REALTIME_VIDEO_SESSION_CHECKS: readonly RealtimeVideoConformanceCheck[];
4
+ //# sourceMappingURL=realtimeVideoConformanceChecks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtimeVideoConformanceChecks.d.ts","sourceRoot":"","sources":["../../src/testing/realtimeVideoConformanceChecks.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AA0HrF,2BAA2B;AAC3B,eAAO,MAAM,6BAA6B,EAAE,SAAS,6BAA6B,EAA+C,CAAC"}