@komaa/standin-sdk 0.1.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.
Files changed (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/dist/ambient.d.ts +80 -0
  4. package/dist/ambient.d.ts.map +1 -0
  5. package/dist/ambient.js +281 -0
  6. package/dist/ambient.js.map +1 -0
  7. package/dist/attachments.d.ts +149 -0
  8. package/dist/attachments.d.ts.map +1 -0
  9. package/dist/attachments.js +451 -0
  10. package/dist/attachments.js.map +1 -0
  11. package/dist/audio.d.ts +80 -0
  12. package/dist/audio.d.ts.map +1 -0
  13. package/dist/audio.js +170 -0
  14. package/dist/audio.js.map +1 -0
  15. package/dist/avatar.d.ts +111 -0
  16. package/dist/avatar.d.ts.map +1 -0
  17. package/dist/avatar.js +201 -0
  18. package/dist/avatar.js.map +1 -0
  19. package/dist/callServer.d.ts +151 -0
  20. package/dist/callServer.d.ts.map +1 -0
  21. package/dist/callServer.js +1097 -0
  22. package/dist/callServer.js.map +1 -0
  23. package/dist/callTools.d.ts +154 -0
  24. package/dist/callTools.d.ts.map +1 -0
  25. package/dist/callTools.js +255 -0
  26. package/dist/callTools.js.map +1 -0
  27. package/dist/chat.d.ts +226 -0
  28. package/dist/chat.d.ts.map +1 -0
  29. package/dist/chat.js +574 -0
  30. package/dist/chat.js.map +1 -0
  31. package/dist/config.d.ts +32 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +86 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/consult.d.ts +147 -0
  36. package/dist/consult.d.ts.map +1 -0
  37. package/dist/consult.js +388 -0
  38. package/dist/consult.js.map +1 -0
  39. package/dist/delivery.d.ts +81 -0
  40. package/dist/delivery.d.ts.map +1 -0
  41. package/dist/delivery.js +187 -0
  42. package/dist/delivery.js.map +1 -0
  43. package/dist/echoGuard.d.ts +56 -0
  44. package/dist/echoGuard.d.ts.map +1 -0
  45. package/dist/echoGuard.js +57 -0
  46. package/dist/echoGuard.js.map +1 -0
  47. package/dist/errors.d.ts +5 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +10 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/fetch.d.ts +40 -0
  52. package/dist/fetch.d.ts.map +1 -0
  53. package/dist/fetch.js +240 -0
  54. package/dist/fetch.js.map +1 -0
  55. package/dist/gate.d.ts +80 -0
  56. package/dist/gate.d.ts.map +1 -0
  57. package/dist/gate.js +249 -0
  58. package/dist/gate.js.map +1 -0
  59. package/dist/handler.d.ts +283 -0
  60. package/dist/handler.d.ts.map +1 -0
  61. package/dist/handler.js +4 -0
  62. package/dist/handler.js.map +1 -0
  63. package/dist/hmac.d.ts +32 -0
  64. package/dist/hmac.d.ts.map +1 -0
  65. package/dist/hmac.js +108 -0
  66. package/dist/hmac.js.map +1 -0
  67. package/dist/index.d.ts +59 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +60 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/lane.d.ts +92 -0
  72. package/dist/lane.d.ts.map +1 -0
  73. package/dist/lane.js +269 -0
  74. package/dist/lane.js.map +1 -0
  75. package/dist/lipsync.d.ts +136 -0
  76. package/dist/lipsync.d.ts.map +1 -0
  77. package/dist/lipsync.js +310 -0
  78. package/dist/lipsync.js.map +1 -0
  79. package/dist/log.d.ts +18 -0
  80. package/dist/log.d.ts.map +1 -0
  81. package/dist/log.js +20 -0
  82. package/dist/log.js.map +1 -0
  83. package/dist/media.d.ts +43 -0
  84. package/dist/media.d.ts.map +1 -0
  85. package/dist/media.js +190 -0
  86. package/dist/media.js.map +1 -0
  87. package/dist/minutes.d.ts +398 -0
  88. package/dist/minutes.d.ts.map +1 -0
  89. package/dist/minutes.js +805 -0
  90. package/dist/minutes.js.map +1 -0
  91. package/dist/outbound.d.ts +388 -0
  92. package/dist/outbound.d.ts.map +1 -0
  93. package/dist/outbound.js +933 -0
  94. package/dist/outbound.js.map +1 -0
  95. package/dist/plugins/cartesia/agent.d.ts +58 -0
  96. package/dist/plugins/cartesia/agent.d.ts.map +1 -0
  97. package/dist/plugins/cartesia/agent.js +254 -0
  98. package/dist/plugins/cartesia/agent.js.map +1 -0
  99. package/dist/plugins/cartesia/cli.d.ts +3 -0
  100. package/dist/plugins/cartesia/cli.d.ts.map +1 -0
  101. package/dist/plugins/cartesia/cli.js +10 -0
  102. package/dist/plugins/cartesia/cli.js.map +1 -0
  103. package/dist/plugins/cartesia/config.d.ts +30 -0
  104. package/dist/plugins/cartesia/config.d.ts.map +1 -0
  105. package/dist/plugins/cartesia/config.js +29 -0
  106. package/dist/plugins/cartesia/config.js.map +1 -0
  107. package/dist/plugins/cartesia/handler.d.ts +40 -0
  108. package/dist/plugins/cartesia/handler.d.ts.map +1 -0
  109. package/dist/plugins/cartesia/handler.js +142 -0
  110. package/dist/plugins/cartesia/handler.js.map +1 -0
  111. package/dist/plugins/cartesia/index.d.ts +6 -0
  112. package/dist/plugins/cartesia/index.d.ts.map +1 -0
  113. package/dist/plugins/cartesia/index.js +54 -0
  114. package/dist/plugins/cartesia/index.js.map +1 -0
  115. package/dist/plugins/deepgram/agent.d.ts +60 -0
  116. package/dist/plugins/deepgram/agent.d.ts.map +1 -0
  117. package/dist/plugins/deepgram/agent.js +302 -0
  118. package/dist/plugins/deepgram/agent.js.map +1 -0
  119. package/dist/plugins/deepgram/cli.d.ts +3 -0
  120. package/dist/plugins/deepgram/cli.d.ts.map +1 -0
  121. package/dist/plugins/deepgram/cli.js +10 -0
  122. package/dist/plugins/deepgram/cli.js.map +1 -0
  123. package/dist/plugins/deepgram/config.d.ts +39 -0
  124. package/dist/plugins/deepgram/config.d.ts.map +1 -0
  125. package/dist/plugins/deepgram/config.js +66 -0
  126. package/dist/plugins/deepgram/config.js.map +1 -0
  127. package/dist/plugins/deepgram/handler.d.ts +87 -0
  128. package/dist/plugins/deepgram/handler.d.ts.map +1 -0
  129. package/dist/plugins/deepgram/handler.js +268 -0
  130. package/dist/plugins/deepgram/handler.js.map +1 -0
  131. package/dist/plugins/deepgram/index.d.ts +11 -0
  132. package/dist/plugins/deepgram/index.d.ts.map +1 -0
  133. package/dist/plugins/deepgram/index.js +76 -0
  134. package/dist/plugins/deepgram/index.js.map +1 -0
  135. package/dist/plugins/echo/cli.d.ts +3 -0
  136. package/dist/plugins/echo/cli.d.ts.map +1 -0
  137. package/dist/plugins/echo/cli.js +10 -0
  138. package/dist/plugins/echo/cli.js.map +1 -0
  139. package/dist/plugins/echo/index.d.ts +37 -0
  140. package/dist/plugins/echo/index.d.ts.map +1 -0
  141. package/dist/plugins/echo/index.js +61 -0
  142. package/dist/plugins/echo/index.js.map +1 -0
  143. package/dist/plugins/elevenlabs/agent.d.ts +72 -0
  144. package/dist/plugins/elevenlabs/agent.d.ts.map +1 -0
  145. package/dist/plugins/elevenlabs/agent.js +305 -0
  146. package/dist/plugins/elevenlabs/agent.js.map +1 -0
  147. package/dist/plugins/elevenlabs/cli.d.ts +3 -0
  148. package/dist/plugins/elevenlabs/cli.d.ts.map +1 -0
  149. package/dist/plugins/elevenlabs/cli.js +10 -0
  150. package/dist/plugins/elevenlabs/cli.js.map +1 -0
  151. package/dist/plugins/elevenlabs/config.d.ts +27 -0
  152. package/dist/plugins/elevenlabs/config.d.ts.map +1 -0
  153. package/dist/plugins/elevenlabs/config.js +42 -0
  154. package/dist/plugins/elevenlabs/config.js.map +1 -0
  155. package/dist/plugins/elevenlabs/handler.d.ts +67 -0
  156. package/dist/plugins/elevenlabs/handler.d.ts.map +1 -0
  157. package/dist/plugins/elevenlabs/handler.js +419 -0
  158. package/dist/plugins/elevenlabs/handler.js.map +1 -0
  159. package/dist/plugins/elevenlabs/index.d.ts +11 -0
  160. package/dist/plugins/elevenlabs/index.d.ts.map +1 -0
  161. package/dist/plugins/elevenlabs/index.js +72 -0
  162. package/dist/plugins/elevenlabs/index.js.map +1 -0
  163. package/dist/plugins/livekit/cli.d.ts +3 -0
  164. package/dist/plugins/livekit/cli.d.ts.map +1 -0
  165. package/dist/plugins/livekit/cli.js +10 -0
  166. package/dist/plugins/livekit/cli.js.map +1 -0
  167. package/dist/plugins/livekit/config.d.ts +47 -0
  168. package/dist/plugins/livekit/config.d.ts.map +1 -0
  169. package/dist/plugins/livekit/config.js +46 -0
  170. package/dist/plugins/livekit/config.js.map +1 -0
  171. package/dist/plugins/livekit/handler.d.ts +59 -0
  172. package/dist/plugins/livekit/handler.d.ts.map +1 -0
  173. package/dist/plugins/livekit/handler.js +211 -0
  174. package/dist/plugins/livekit/handler.js.map +1 -0
  175. package/dist/plugins/livekit/index.d.ts +6 -0
  176. package/dist/plugins/livekit/index.d.ts.map +1 -0
  177. package/dist/plugins/livekit/index.js +68 -0
  178. package/dist/plugins/livekit/index.js.map +1 -0
  179. package/dist/plugins/livekit/room.d.ts +117 -0
  180. package/dist/plugins/livekit/room.d.ts.map +1 -0
  181. package/dist/plugins/livekit/room.js +449 -0
  182. package/dist/plugins/livekit/room.js.map +1 -0
  183. package/dist/plugins/openai/agent.d.ts +74 -0
  184. package/dist/plugins/openai/agent.d.ts.map +1 -0
  185. package/dist/plugins/openai/agent.js +264 -0
  186. package/dist/plugins/openai/agent.js.map +1 -0
  187. package/dist/plugins/openai/cli.d.ts +3 -0
  188. package/dist/plugins/openai/cli.d.ts.map +1 -0
  189. package/dist/plugins/openai/cli.js +10 -0
  190. package/dist/plugins/openai/cli.js.map +1 -0
  191. package/dist/plugins/openai/config.d.ts +29 -0
  192. package/dist/plugins/openai/config.d.ts.map +1 -0
  193. package/dist/plugins/openai/config.js +37 -0
  194. package/dist/plugins/openai/config.js.map +1 -0
  195. package/dist/plugins/openai/handler.d.ts +65 -0
  196. package/dist/plugins/openai/handler.d.ts.map +1 -0
  197. package/dist/plugins/openai/handler.js +297 -0
  198. package/dist/plugins/openai/handler.js.map +1 -0
  199. package/dist/plugins/openai/index.d.ts +6 -0
  200. package/dist/plugins/openai/index.d.ts.map +1 -0
  201. package/dist/plugins/openai/index.js +72 -0
  202. package/dist/plugins/openai/index.js.map +1 -0
  203. package/dist/plugins/openclaw/allowlist.d.ts +9 -0
  204. package/dist/plugins/openclaw/allowlist.d.ts.map +1 -0
  205. package/dist/plugins/openclaw/allowlist.js +11 -0
  206. package/dist/plugins/openclaw/allowlist.js.map +1 -0
  207. package/dist/plugins/openclaw/config.d.ts +50 -0
  208. package/dist/plugins/openclaw/config.d.ts.map +1 -0
  209. package/dist/plugins/openclaw/config.js +53 -0
  210. package/dist/plugins/openclaw/config.js.map +1 -0
  211. package/dist/plugins/openclaw/handler.d.ts +90 -0
  212. package/dist/plugins/openclaw/handler.d.ts.map +1 -0
  213. package/dist/plugins/openclaw/handler.js +146 -0
  214. package/dist/plugins/openclaw/handler.js.map +1 -0
  215. package/dist/plugins/openclaw/index.d.ts +55 -0
  216. package/dist/plugins/openclaw/index.d.ts.map +1 -0
  217. package/dist/plugins/openclaw/index.js +89 -0
  218. package/dist/plugins/openclaw/index.js.map +1 -0
  219. package/dist/plugins/openclaw/openclaw.plugin.json +74 -0
  220. package/dist/plugins/openclaw/package.json +14 -0
  221. package/dist/plugins/openclaw/realtime.d.ts +82 -0
  222. package/dist/plugins/openclaw/realtime.d.ts.map +1 -0
  223. package/dist/plugins/openclaw/realtime.js +238 -0
  224. package/dist/plugins/openclaw/realtime.js.map +1 -0
  225. package/dist/plugins/openclaw/runtime.d.ts +19 -0
  226. package/dist/plugins/openclaw/runtime.d.ts.map +1 -0
  227. package/dist/plugins/openclaw/runtime.js +160 -0
  228. package/dist/plugins/openclaw/runtime.js.map +1 -0
  229. package/dist/policy.d.ts +38 -0
  230. package/dist/policy.d.ts.map +1 -0
  231. package/dist/policy.js +95 -0
  232. package/dist/policy.js.map +1 -0
  233. package/dist/protocol.d.ts +44 -0
  234. package/dist/protocol.d.ts.map +1 -0
  235. package/dist/protocol.js +77 -0
  236. package/dist/protocol.js.map +1 -0
  237. package/dist/protocolRuntime.d.ts +19 -0
  238. package/dist/protocolRuntime.d.ts.map +1 -0
  239. package/dist/protocolRuntime.js +78 -0
  240. package/dist/protocolRuntime.js.map +1 -0
  241. package/dist/smoke.d.ts +65 -0
  242. package/dist/smoke.d.ts.map +1 -0
  243. package/dist/smoke.js +293 -0
  244. package/dist/smoke.js.map +1 -0
  245. package/dist/startup.d.ts +74 -0
  246. package/dist/startup.d.ts.map +1 -0
  247. package/dist/startup.js +112 -0
  248. package/dist/startup.js.map +1 -0
  249. package/dist/tile.d.ts +101 -0
  250. package/dist/tile.d.ts.map +1 -0
  251. package/dist/tile.js +195 -0
  252. package/dist/tile.js.map +1 -0
  253. package/dist/version.d.ts +2 -0
  254. package/dist/version.d.ts.map +1 -0
  255. package/dist/version.js +4 -0
  256. package/dist/version.js.map +1 -0
  257. package/dist/vision.d.ts +160 -0
  258. package/dist/vision.d.ts.map +1 -0
  259. package/dist/vision.js +301 -0
  260. package/dist/vision.js.map +1 -0
  261. package/dist/visionTools.d.ts +237 -0
  262. package/dist/visionTools.d.ts.map +1 -0
  263. package/dist/visionTools.js +578 -0
  264. package/dist/visionTools.js.map +1 -0
  265. package/dist/voice.d.ts +143 -0
  266. package/dist/voice.d.ts.map +1 -0
  267. package/dist/voice.js +403 -0
  268. package/dist/voice.js.map +1 -0
  269. package/package.json +129 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Loudness at which a frame counts as speech rather than room noise. The same
3
+ * scale {@link pcm16Rms} returns, 0.0 to 1.0.
4
+ */
5
+ export declare const DEFAULT_SPEECH_RMS = 0.02;
6
+ /**
7
+ * How much quiet ends an utterance. Short enough that the agent does not feel
8
+ * slow, long enough to survive the pause in the middle of a sentence.
9
+ */
10
+ export declare const DEFAULT_SILENCE_MS = 800;
11
+ /**
12
+ * Audio kept from BEFORE the gate opened. The syllable that trips the gate is
13
+ * part of the word, and without this every utterance starts clipped.
14
+ */
15
+ export declare const DEFAULT_PREROLL_MS = 240;
16
+ /**
17
+ * Below this an utterance is a cough, a door, a chair. Transcribing it costs a
18
+ * request and returns nothing worth answering.
19
+ */
20
+ export declare const DEFAULT_MIN_UTTERANCE_MS = 120;
21
+ /**
22
+ * A hard ceiling, so a stuck-open microphone or a television in the room does
23
+ * not grow one utterance for the length of the call.
24
+ */
25
+ export declare const DEFAULT_MAX_UTTERANCE_MS = 30000;
26
+ /** Options for {@link UtteranceSegmenter}. */
27
+ export interface SegmenterOptions {
28
+ speechRms?: number;
29
+ silenceMs?: number;
30
+ prerollMs?: number;
31
+ minUtteranceMs?: number;
32
+ maxUtteranceMs?: number;
33
+ }
34
+ /**
35
+ * One utterance per spoken phrase, out of a continuous stream.
36
+ *
37
+ * A Microsoft Teams call delivers audio continuously: silence is still frames,
38
+ * fifty a second. A transcription service wants a phrase. This is the gate
39
+ * between them.
40
+ *
41
+ * ```ts
42
+ * const utterance = segmenter.feed(frame);
43
+ * if (utterance !== undefined) await transcribe(utterance);
44
+ * ```
45
+ *
46
+ * Four bounds, and each exists because of a specific failure.
47
+ *
48
+ * **Pre-roll**, because the syllable that trips the gate is part of the word.
49
+ * Without it every utterance begins mid-consonant and the transcript loses the
50
+ * first word of most sentences.
51
+ *
52
+ * **Trailing silence**, because a pause inside a sentence is not the end of one.
53
+ * Too short and the agent interrupts a thinking caller; too long and it feels
54
+ * slow.
55
+ *
56
+ * **A floor**, because a cough is not a turn. Sending one costs a request and
57
+ * returns nothing worth answering.
58
+ *
59
+ * **A ceiling**, because a stuck-open microphone or a television in the room
60
+ * never goes quiet, and without a cap one utterance grows for the whole call.
61
+ */
62
+ export declare class UtteranceSegmenter {
63
+ #private;
64
+ readonly speechRms: number;
65
+ readonly silenceMs: number;
66
+ readonly minUtteranceMs: number;
67
+ readonly maxUtteranceMs: number;
68
+ constructor(options?: SegmenterOptions);
69
+ /** Whether the caller is mid-utterance right now. */
70
+ get speaking(): boolean;
71
+ /**
72
+ * Take one frame. Returns a finished utterance, or undefined.
73
+ *
74
+ * Never throws and never blocks: it runs on the receive path of a live call,
75
+ * once per frame.
76
+ */
77
+ feed(pcm: Buffer): Buffer | undefined;
78
+ /** Take whatever is held, mid-utterance. For teardown, or a barge-in. */
79
+ flush(): Buffer | undefined;
80
+ /** Forget everything. The caller interrupted, or the turn is abandoned. */
81
+ reset(): void;
82
+ }
83
+ /**
84
+ * Read a WAV and return PCM16 mono at the call's rate.
85
+ *
86
+ * A speech engine hands you a WAV and it is rarely the one you wanted: 32-bit
87
+ * float, 44.1 kHz, stereo, or wrapped in `WAVE_FORMAT_EXTENSIBLE`, which ffmpeg
88
+ * emits even for plain PCM. Every one of those plays as noise if you put it on a
89
+ * call unconverted, and the failure is not obvious from the header.
90
+ *
91
+ * Chunks are walked rather than assumed at a fixed offset, because a real
92
+ * encoder puts `LIST` and `fact` chunks before the data and a fixed offset reads
93
+ * them as samples.
94
+ *
95
+ * Throws on anything that is not a WAV this can read.
96
+ */
97
+ export declare function decodeWav(data: Buffer): Buffer;
98
+ /** Wrap PCM16 mono in a WAV, for a service that will not take raw PCM. */
99
+ export declare function encodeWav(pcm: Buffer, sampleRateHz?: number): Buffer;
100
+ /** What happened to one buffer handed to {@link PacedPlayback}. */
101
+ export interface Playback {
102
+ /** How much actually reached the caller. */
103
+ readonly sentMs: number;
104
+ /** How much there was. */
105
+ readonly totalMs: number;
106
+ /** Whether it was cut short. */
107
+ readonly interrupted: boolean;
108
+ }
109
+ /** Hand one wire frame to the call. Normally `session.sendAudio`. */
110
+ export type FrameSink = (pcm: Buffer) => Promise<void>;
111
+ /**
112
+ * Feed a finished buffer out at the rate a call consumes it.
113
+ *
114
+ * A text-to-speech engine returns a whole utterance at once. A call takes 20
115
+ * milliseconds every 20 milliseconds. Sending the buffer in one go hands the
116
+ * service seconds of audio it must queue, and the queue is what makes a barge-in
117
+ * arrive too late to matter: the caller interrupts, the model stops, and the bot
118
+ * keeps talking for the length of what was already sent.
119
+ *
120
+ * So it goes out paced, and the pacing is on an ABSOLUTE clock. Sleeping 20 ms
121
+ * per frame accumulates every scheduling delay, and a minute of speech ends
122
+ * seconds behind where it should be; this one waits until the next frame is DUE,
123
+ * so a late frame is followed by a short wait rather than a full one.
124
+ *
125
+ * ```ts
126
+ * const playback = new PacedPlayback((pcm) => session.sendAudio(pcm));
127
+ * const result = await playback.say(pcm);
128
+ * if (result.interrupted) { ... }
129
+ * ```
130
+ *
131
+ * {@link cancel} stops whatever is playing. The result says how much was heard,
132
+ * which is the difference between "I told them" and "I started to".
133
+ */
134
+ export declare class PacedPlayback {
135
+ #private;
136
+ constructor(send: FrameSink, frameMs?: number);
137
+ get playing(): boolean;
138
+ /** Stop what is playing. Safe from anywhere, including a receive loop. */
139
+ cancel(): void;
140
+ /** Play one buffer and return what the caller actually heard. */
141
+ say(pcm: Buffer): Promise<Playback>;
142
+ }
143
+ //# sourceMappingURL=voice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,kBAAkB;;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAepB,OAAO,GAAE,gBAAqB;IAW1C,qDAAqD;IACrD,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAmCrC,yEAAyE;IACzE,KAAK,IAAI,MAAM,GAAG,SAAS;IAI3B,2EAA2E;IAC3E,KAAK,IAAI,IAAI;CA+Bd;AAeD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0D9C;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,YAAY,GAAE,MAAuB,GACpC,MAAM,CAgBR;AA+BD,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,aAAa;;gBAUZ,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,MAAiB;IAMvD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,0EAA0E;IAC1E,MAAM,IAAI,IAAI;IAId,iEAAiE;IAC3D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CA8C1C"}
package/dist/voice.js ADDED
@@ -0,0 +1,403 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * Turn-taking for an agent that is not a realtime model.
5
+ *
6
+ * A realtime speech-to-speech provider is handed the caller's audio and hands
7
+ * audio back, and the turn-taking is theirs. Everything else is not like that. A
8
+ * transcription service wants one utterance at a time, a language model wants
9
+ * text, and a text-to-speech engine hands back a whole buffer that somebody has
10
+ * to feed out at the rate a call consumes it.
11
+ *
12
+ * That shape is the same whichever three services you pick, and four separate
13
+ * bridges each wrote it before this module existed. Three pieces:
14
+ *
15
+ * {@link UtteranceSegmenter} turns fifty frames a second into one utterance per
16
+ * spoken phrase. {@link decodeWav} and {@link encodeWav} deal with the fact that
17
+ * a speech engine hands you a WAV and it is rarely the WAV you wanted.
18
+ * {@link PacedPlayback} feeds a finished buffer out at the rate the call
19
+ * consumes it, interruptibly.
20
+ *
21
+ * None of this is needed by a realtime plugin, and none of it costs one
22
+ * anything: it is a module you do not import.
23
+ *
24
+ * Identical in shape to the Python SDK's `standin.voice`.
25
+ */
26
+ import { FRAME_BYTES, FRAME_MS, pcm16Rms, resamplePcm16 } from "./audio.js";
27
+ import { logger } from "./log.js";
28
+ import { SAMPLE_RATE_HZ } from "./protocol.js";
29
+ /**
30
+ * Loudness at which a frame counts as speech rather than room noise. The same
31
+ * scale {@link pcm16Rms} returns, 0.0 to 1.0.
32
+ */
33
+ export const DEFAULT_SPEECH_RMS = 0.02;
34
+ /**
35
+ * How much quiet ends an utterance. Short enough that the agent does not feel
36
+ * slow, long enough to survive the pause in the middle of a sentence.
37
+ */
38
+ export const DEFAULT_SILENCE_MS = 800;
39
+ /**
40
+ * Audio kept from BEFORE the gate opened. The syllable that trips the gate is
41
+ * part of the word, and without this every utterance starts clipped.
42
+ */
43
+ export const DEFAULT_PREROLL_MS = 240;
44
+ /**
45
+ * Below this an utterance is a cough, a door, a chair. Transcribing it costs a
46
+ * request and returns nothing worth answering.
47
+ */
48
+ export const DEFAULT_MIN_UTTERANCE_MS = 120;
49
+ /**
50
+ * A hard ceiling, so a stuck-open microphone or a television in the room does
51
+ * not grow one utterance for the length of the call.
52
+ */
53
+ export const DEFAULT_MAX_UTTERANCE_MS = 30_000;
54
+ /**
55
+ * One utterance per spoken phrase, out of a continuous stream.
56
+ *
57
+ * A Microsoft Teams call delivers audio continuously: silence is still frames,
58
+ * fifty a second. A transcription service wants a phrase. This is the gate
59
+ * between them.
60
+ *
61
+ * ```ts
62
+ * const utterance = segmenter.feed(frame);
63
+ * if (utterance !== undefined) await transcribe(utterance);
64
+ * ```
65
+ *
66
+ * Four bounds, and each exists because of a specific failure.
67
+ *
68
+ * **Pre-roll**, because the syllable that trips the gate is part of the word.
69
+ * Without it every utterance begins mid-consonant and the transcript loses the
70
+ * first word of most sentences.
71
+ *
72
+ * **Trailing silence**, because a pause inside a sentence is not the end of one.
73
+ * Too short and the agent interrupts a thinking caller; too long and it feels
74
+ * slow.
75
+ *
76
+ * **A floor**, because a cough is not a turn. Sending one costs a request and
77
+ * returns nothing worth answering.
78
+ *
79
+ * **A ceiling**, because a stuck-open microphone or a television in the room
80
+ * never goes quiet, and without a cap one utterance grows for the whole call.
81
+ */
82
+ export class UtteranceSegmenter {
83
+ speechRms;
84
+ silenceMs;
85
+ minUtteranceMs;
86
+ maxUtteranceMs;
87
+ #prerollFrames;
88
+ // A ring, not a growing list: it holds pre-speech audio on every frame of a
89
+ // silent call, which is most of them.
90
+ #preroll = [];
91
+ #speech = [];
92
+ #quietMs = 0;
93
+ #speaking = false;
94
+ /**
95
+ * Frames since the gate opened, and the last of them that was loud. The gap
96
+ * between the two is trailing silence, which is not speech.
97
+ */
98
+ #sinceOpen = 0;
99
+ #lastLoud = 0;
100
+ constructor(options = {}) {
101
+ this.speechRms = options.speechRms ?? DEFAULT_SPEECH_RMS;
102
+ this.silenceMs = options.silenceMs ?? DEFAULT_SILENCE_MS;
103
+ this.minUtteranceMs = options.minUtteranceMs ?? DEFAULT_MIN_UTTERANCE_MS;
104
+ this.maxUtteranceMs = options.maxUtteranceMs ?? DEFAULT_MAX_UTTERANCE_MS;
105
+ this.#prerollFrames = Math.max(1, Math.floor((options.prerollMs ?? DEFAULT_PREROLL_MS) / FRAME_MS));
106
+ }
107
+ /** Whether the caller is mid-utterance right now. */
108
+ get speaking() {
109
+ return this.#speaking;
110
+ }
111
+ /**
112
+ * Take one frame. Returns a finished utterance, or undefined.
113
+ *
114
+ * Never throws and never blocks: it runs on the receive path of a live call,
115
+ * once per frame.
116
+ */
117
+ feed(pcm) {
118
+ if (pcm.length === 0)
119
+ return undefined;
120
+ const loud = pcm16Rms(pcm) >= this.speechRms;
121
+ if (!this.#speaking) {
122
+ if (!loud) {
123
+ this.#preroll.push(pcm);
124
+ if (this.#preroll.length > this.#prerollFrames)
125
+ this.#preroll.shift();
126
+ return undefined;
127
+ }
128
+ // Opening: the ring is what the caller actually started saying.
129
+ this.#speech = [...this.#preroll, pcm];
130
+ this.#sinceOpen = 1;
131
+ this.#lastLoud = 1;
132
+ this.#preroll = [];
133
+ this.#speaking = true;
134
+ this.#quietMs = 0;
135
+ return undefined;
136
+ }
137
+ this.#speech.push(pcm);
138
+ this.#sinceOpen += 1;
139
+ if (loud)
140
+ this.#lastLoud = this.#sinceOpen;
141
+ this.#quietMs = loud ? 0 : this.#quietMs + FRAME_MS;
142
+ if (this.#quietMs >= this.silenceMs)
143
+ return this.#finish(false);
144
+ if (this.#durationMs() >= this.maxUtteranceMs) {
145
+ logger.info(`standin: cutting an utterance at its ${this.maxUtteranceMs} ms ceiling`);
146
+ return this.#finish(true);
147
+ }
148
+ return undefined;
149
+ }
150
+ /** Take whatever is held, mid-utterance. For teardown, or a barge-in. */
151
+ flush() {
152
+ return this.#speaking ? this.#finish(false) : undefined;
153
+ }
154
+ /** Forget everything. The caller interrupted, or the turn is abandoned. */
155
+ reset() {
156
+ this.#speech = [];
157
+ this.#preroll = [];
158
+ this.#quietMs = 0;
159
+ this.#speaking = false;
160
+ this.#sinceOpen = 0;
161
+ this.#lastLoud = 0;
162
+ }
163
+ /**
164
+ * Everything held, pre-roll and trailing silence included.
165
+ *
166
+ * The right measure for the ceiling: a stuck-open microphone is filling
167
+ * memory whether or not anybody is talking into it.
168
+ */
169
+ #durationMs() {
170
+ return this.#speech.length * FRAME_MS;
171
+ }
172
+ /** The loud part alone, which is what a floor has to judge. */
173
+ #voicedMs() {
174
+ return this.#lastLoud * FRAME_MS;
175
+ }
176
+ #finish(force) {
177
+ const audio = Buffer.concat(this.#speech);
178
+ const voiced = this.#voicedMs();
179
+ this.reset();
180
+ if (!force && voiced < this.minUtteranceMs)
181
+ return undefined;
182
+ return audio.length > 0 ? audio : undefined;
183
+ }
184
+ }
185
+ // -------------------------------------------------------------------- the WAV
186
+ /** Plain integer PCM. */
187
+ const FORMAT_PCM = 1;
188
+ /** IEEE float, which several engines emit at 32 bits. */
189
+ const FORMAT_FLOAT = 3;
190
+ /**
191
+ * The wrapper ffmpeg and several speech engines emit even for plain PCM. The
192
+ * real format is a GUID in the extension, whose first two bytes are the tag
193
+ * above, so reading those two bytes is enough.
194
+ */
195
+ const FORMAT_EXTENSIBLE = 0xfffe;
196
+ /**
197
+ * Read a WAV and return PCM16 mono at the call's rate.
198
+ *
199
+ * A speech engine hands you a WAV and it is rarely the one you wanted: 32-bit
200
+ * float, 44.1 kHz, stereo, or wrapped in `WAVE_FORMAT_EXTENSIBLE`, which ffmpeg
201
+ * emits even for plain PCM. Every one of those plays as noise if you put it on a
202
+ * call unconverted, and the failure is not obvious from the header.
203
+ *
204
+ * Chunks are walked rather than assumed at a fixed offset, because a real
205
+ * encoder puts `LIST` and `fact` chunks before the data and a fixed offset reads
206
+ * them as samples.
207
+ *
208
+ * Throws on anything that is not a WAV this can read.
209
+ */
210
+ export function decodeWav(data) {
211
+ if (data.length < 12 ||
212
+ data.toString("ascii", 0, 4) !== "RIFF" ||
213
+ data.toString("ascii", 8, 12) !== "WAVE") {
214
+ throw new Error("not a RIFF/WAVE file");
215
+ }
216
+ let audioFormat = 0;
217
+ let channels = 0;
218
+ let rate = 0;
219
+ let bits = 0;
220
+ let payload;
221
+ let at = 12;
222
+ while (at + 8 <= data.length) {
223
+ const chunkId = data.toString("ascii", at, at + 4);
224
+ const size = data.readUInt32LE(at + 4);
225
+ const body = data.subarray(at + 8, at + 8 + size);
226
+ if (chunkId === "fmt " && body.length >= 16) {
227
+ audioFormat = body.readUInt16LE(0);
228
+ channels = body.readUInt16LE(2);
229
+ rate = body.readUInt32LE(4);
230
+ bits = body.readUInt16LE(14);
231
+ if (audioFormat === FORMAT_EXTENSIBLE && body.length >= 26) {
232
+ // The real format is the first two bytes of the sub-format GUID.
233
+ audioFormat = body.readUInt16LE(24);
234
+ }
235
+ }
236
+ else if (chunkId === "data") {
237
+ payload = body;
238
+ }
239
+ // Chunks are word-aligned, and an odd size carries a pad byte.
240
+ at += 8 + size + (size & 1);
241
+ }
242
+ if (channels === 0 || rate === 0)
243
+ throw new Error("the WAV has no readable fmt chunk");
244
+ if (payload === undefined)
245
+ throw new Error("the WAV has no data chunk");
246
+ let samples;
247
+ if (audioFormat === FORMAT_FLOAT && bits === 32) {
248
+ samples = float32ToPcm16(payload);
249
+ }
250
+ else if (audioFormat === FORMAT_PCM && bits === 16) {
251
+ samples = payload;
252
+ }
253
+ else if (audioFormat === FORMAT_PCM && bits === 8) {
254
+ // 8-bit WAV is UNSIGNED, centred on 128. Read as signed it is a square wave
255
+ // of noise.
256
+ samples = Buffer.alloc(payload.length * 2);
257
+ for (let i = 0; i < payload.length; i += 1)
258
+ samples.writeInt16LE((payload[i] - 128) * 256, i * 2);
259
+ }
260
+ else {
261
+ throw new Error(`unsupported WAV format ${audioFormat} at ${bits} bits`);
262
+ }
263
+ if (channels > 1)
264
+ samples = downmix(samples, channels);
265
+ if (rate !== SAMPLE_RATE_HZ)
266
+ samples = resamplePcm16(samples, rate, SAMPLE_RATE_HZ);
267
+ return samples;
268
+ }
269
+ /** Wrap PCM16 mono in a WAV, for a service that will not take raw PCM. */
270
+ export function encodeWav(pcm, sampleRateHz = SAMPLE_RATE_HZ) {
271
+ const header = Buffer.alloc(44);
272
+ header.write("RIFF", 0, "ascii");
273
+ header.writeUInt32LE(36 + pcm.length, 4);
274
+ header.write("WAVE", 8, "ascii");
275
+ header.write("fmt ", 12, "ascii");
276
+ header.writeUInt32LE(16, 16);
277
+ header.writeUInt16LE(FORMAT_PCM, 20);
278
+ header.writeUInt16LE(1, 22);
279
+ header.writeUInt32LE(sampleRateHz, 24);
280
+ header.writeUInt32LE(sampleRateHz * 2, 28);
281
+ header.writeUInt16LE(2, 32);
282
+ header.writeUInt16LE(16, 34);
283
+ header.write("data", 36, "ascii");
284
+ header.writeUInt32LE(pcm.length, 40);
285
+ return Buffer.concat([header, pcm]);
286
+ }
287
+ function float32ToPcm16(payload) {
288
+ const count = Math.floor(payload.length / 4);
289
+ const out = Buffer.alloc(count * 2);
290
+ for (let i = 0; i < count; i += 1) {
291
+ const value = payload.readFloatLE(i * 4);
292
+ // Clamped, because a float WAV is allowed outside -1..1 and wrapping there
293
+ // is the loudest possible click.
294
+ const clamped = value < -1 ? -1 : value > 1 ? 1 : value;
295
+ out.writeInt16LE(Math.trunc(clamped * 32767), i * 2);
296
+ }
297
+ return out;
298
+ }
299
+ /** Average the channels. Taking only the left loses whoever is on the right. */
300
+ function downmix(pcm, channels) {
301
+ const frame = channels * 2;
302
+ const count = Math.floor(pcm.length / frame);
303
+ const out = Buffer.alloc(count * 2);
304
+ for (let i = 0; i < count; i += 1) {
305
+ let total = 0;
306
+ for (let c = 0; c < channels; c += 1)
307
+ total += pcm.readInt16LE(i * frame + c * 2);
308
+ out.writeInt16LE(Math.trunc(total / channels), i * 2);
309
+ }
310
+ return out;
311
+ }
312
+ /**
313
+ * Feed a finished buffer out at the rate a call consumes it.
314
+ *
315
+ * A text-to-speech engine returns a whole utterance at once. A call takes 20
316
+ * milliseconds every 20 milliseconds. Sending the buffer in one go hands the
317
+ * service seconds of audio it must queue, and the queue is what makes a barge-in
318
+ * arrive too late to matter: the caller interrupts, the model stops, and the bot
319
+ * keeps talking for the length of what was already sent.
320
+ *
321
+ * So it goes out paced, and the pacing is on an ABSOLUTE clock. Sleeping 20 ms
322
+ * per frame accumulates every scheduling delay, and a minute of speech ends
323
+ * seconds behind where it should be; this one waits until the next frame is DUE,
324
+ * so a late frame is followed by a short wait rather than a full one.
325
+ *
326
+ * ```ts
327
+ * const playback = new PacedPlayback((pcm) => session.sendAudio(pcm));
328
+ * const result = await playback.say(pcm);
329
+ * if (result.interrupted) { ... }
330
+ * ```
331
+ *
332
+ * {@link cancel} stops whatever is playing. The result says how much was heard,
333
+ * which is the difference between "I told them" and "I started to".
334
+ */
335
+ export class PacedPlayback {
336
+ #send;
337
+ #frameMs;
338
+ #frameBytes;
339
+ #cancelled = false;
340
+ #playing = false;
341
+ // Serialised, so two turns cannot interleave into one stream of audio the
342
+ // caller hears as both at once.
343
+ #queue = Promise.resolve();
344
+ constructor(send, frameMs = FRAME_MS) {
345
+ this.#send = send;
346
+ this.#frameMs = Math.max(1, frameMs);
347
+ this.#frameBytes = (FRAME_BYTES * this.#frameMs) / FRAME_MS;
348
+ }
349
+ get playing() {
350
+ return this.#playing;
351
+ }
352
+ /** Stop what is playing. Safe from anywhere, including a receive loop. */
353
+ cancel() {
354
+ this.#cancelled = true;
355
+ }
356
+ /** Play one buffer and return what the caller actually heard. */
357
+ async say(pcm) {
358
+ const totalMs = Math.floor((Math.floor(pcm.length / 2) * 1000) / SAMPLE_RATE_HZ);
359
+ if (pcm.length === 0)
360
+ return { sentMs: 0, totalMs: 0, interrupted: false };
361
+ const run = this.#queue.then(() => this.#play(pcm, totalMs));
362
+ // Swallowed on the QUEUE only: the caller still sees the rejection through
363
+ // their own await, but one failed turn must not poison every later one.
364
+ this.#queue = run.catch(() => undefined);
365
+ return run;
366
+ }
367
+ async #play(pcm, totalMs) {
368
+ this.#cancelled = false;
369
+ this.#playing = true;
370
+ let sent = 0;
371
+ // The clock is absolute. Waiting a fixed step per frame accumulates every
372
+ // delay, and a long utterance finishes seconds late.
373
+ let due = Date.now();
374
+ try {
375
+ for (let at = 0; at < pcm.length; at += this.#frameBytes) {
376
+ if (this.#cancelled)
377
+ break;
378
+ const frame = pcm.subarray(at, at + this.#frameBytes);
379
+ await this.#send(frame);
380
+ sent += frame.length;
381
+ due += this.#frameMs;
382
+ const delay = due - Date.now();
383
+ if (delay > 0) {
384
+ await new Promise((resolve) => {
385
+ const timer = setTimeout(resolve, delay);
386
+ timer.unref?.();
387
+ });
388
+ }
389
+ }
390
+ }
391
+ finally {
392
+ this.#playing = false;
393
+ }
394
+ const interrupted = this.#cancelled;
395
+ this.#cancelled = false;
396
+ return {
397
+ sentMs: Math.floor((Math.floor(sent / 2) * 1000) / SAMPLE_RATE_HZ),
398
+ totalMs,
399
+ interrupted,
400
+ };
401
+ }
402
+ }
403
+ //# sourceMappingURL=voice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAW/C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,kBAAkB;IACpB,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,cAAc,CAAS;IACvB,cAAc,CAAS;IACvB,cAAc,CAAS;IAChC,4EAA4E;IAC5E,sCAAsC;IACtC,QAAQ,GAAa,EAAE,CAAC;IACxB,OAAO,GAAa,EAAE,CAAC;IACvB,QAAQ,GAAG,CAAC,CAAC;IACb,SAAS,GAAG,KAAK,CAAC;IAClB;;;OAGG;IACH,UAAU,GAAG,CAAC,CAAC;IACf,SAAS,GAAG,CAAC,CAAC;IAEd,YAAY,UAA4B,EAAE;QACxC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACzD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC;QACzE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC;QACzE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAC5B,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC,GAAG,QAAQ,CAAC,CACjE,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,GAAW;QACd,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC;QAE7C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc;oBAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACtE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,gEAAgE;YAChE,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YAClB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACrB,IAAI,IAAI;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEpD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC9C,MAAM,CAAC,IAAI,CACT,wCAAwC,IAAI,CAAC,cAAc,aAAa,CACzE,CAAC;YACF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,yEAAyE;IACzE,KAAK;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,CAAC;IAED,2EAA2E;IAC3E,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;IACxC,CAAC;IAED,+DAA+D;IAC/D,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IACnC,CAAC;IAED,OAAO,CAAC,KAAc;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc;YAAE,OAAO,SAAS,CAAC;QAC7D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9C,CAAC;CACF;AAED,+EAA+E;AAE/E,yBAAyB;AACzB,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,yDAAyD;AACzD,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEjC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IACE,IAAI,CAAC,MAAM,GAAG,EAAE;QAChB,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM;QACvC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM,EACxC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,OAA2B,CAAC;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QAClD,IAAI,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YAC5C,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACnC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,WAAW,KAAK,iBAAiB,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC3D,iEAAiE;gBACjE,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,+DAA+D;QAC/D,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,QAAQ,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAExE,IAAI,OAAe,CAAC;IACpB,IAAI,WAAW,KAAK,YAAY,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChD,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,WAAW,KAAK,UAAU,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACrD,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC;SAAM,IAAI,WAAW,KAAK,UAAU,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACpD,4EAA4E;QAC5E,YAAY;QACZ,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;YACxC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,OAAO,IAAI,OAAO,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,IAAI,KAAK,cAAc;QACzB,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,SAAS,CACvB,GAAW,EACX,eAAuB,cAAc;IAErC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,aAAa,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7B,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5B,MAAM,CAAC,aAAa,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,aAAa,CAAC,YAAY,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5B,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,2EAA2E;QAC3E,iCAAiC;QACjC,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACxD,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gFAAgF;AAChF,SAAS,OAAO,CAAC,GAAW,EAAE,QAAgB;IAC5C,MAAM,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC;YAClC,KAAK,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAiBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,aAAa;IACf,KAAK,CAAY;IACjB,QAAQ,CAAS;IACjB,WAAW,CAAS;IAC7B,UAAU,GAAG,KAAK,CAAC;IACnB,QAAQ,GAAG,KAAK,CAAC;IACjB,0EAA0E;IAC1E,gCAAgC;IAChC,MAAM,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAE7C,YAAY,IAAe,EAAE,UAAkB,QAAQ;QACrD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAC9D,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,0EAA0E;IAC1E,MAAM;QACJ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,cAAc,CACrD,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAE3E,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QAC7D,2EAA2E;QAC3E,wEAAwE;QACxE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,OAAe;QACtC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,0EAA0E;QAC1E,qDAAqD;QACrD,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACzD,IAAI,IAAI,CAAC,UAAU;oBAAE,MAAM;gBAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;gBACtD,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACxB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;gBACrB,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC;gBACrB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC/B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACd,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;wBAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;wBACzC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;oBAClB,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,cAAc,CAAC;YAClE,OAAO;YACP,WAAW;SACZ,CAAC;IACJ,CAAC;CACF"}