@cemscale-voip/voip-sdk 1.48.0 → 1.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +362 -857
- package/dist/client.d.ts +39 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +45 -0
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/playground.d.ts +71 -0
- package/dist/playground.d.ts.map +1 -0
- package/dist/playground.js +320 -0
- package/dist/playground.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Agent Playground — browser-based live testing of AI voice agents.
|
|
3
|
+
*
|
|
4
|
+
* Opens a WebSocket connection to the VoIP API, captures microphone audio,
|
|
5
|
+
* sends it to the AI agent, and plays back the agent's voice response.
|
|
6
|
+
* No phone, no SIP, no extensions needed.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const session = voip.connectAiPlayground('my-agent');
|
|
11
|
+
* session.on('ready', () => console.log('Speak into your mic!'));
|
|
12
|
+
* session.on('end', () => console.log('Session ended'));
|
|
13
|
+
* // ... when done:
|
|
14
|
+
* session.disconnect();
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
// ── Constants ────────────────────────────────────────────────
|
|
18
|
+
const INPUT_SAMPLE_RATE = 16000; // What Gemini expects
|
|
19
|
+
const OUTPUT_SAMPLE_RATE = 24000; // What Gemini outputs
|
|
20
|
+
const BUFFER_SIZE = 4096; // ScriptProcessor buffer
|
|
21
|
+
// ── AudioWorklet processor (inline, stringified) ─────────────
|
|
22
|
+
const WORKLET_CODE = `
|
|
23
|
+
class PcmCaptureProcessor extends AudioWorkletProcessor {
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
this._buffer = new Float32Array(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
process(inputs) {
|
|
30
|
+
const input = inputs[0];
|
|
31
|
+
if (!input || !input[0]) return true;
|
|
32
|
+
|
|
33
|
+
const channelData = input[0]; // mono
|
|
34
|
+
|
|
35
|
+
// Accumulate samples
|
|
36
|
+
const newBuf = new Float32Array(this._buffer.length + channelData.length);
|
|
37
|
+
newBuf.set(this._buffer);
|
|
38
|
+
newBuf.set(channelData, this._buffer.length);
|
|
39
|
+
this._buffer = newBuf;
|
|
40
|
+
|
|
41
|
+
// Send chunks of ~20ms at input sample rate
|
|
42
|
+
const chunkSize = Math.floor(sampleRate * 0.02); // ~20ms
|
|
43
|
+
while (this._buffer.length >= chunkSize) {
|
|
44
|
+
const chunk = this._buffer.slice(0, chunkSize);
|
|
45
|
+
this._buffer = this._buffer.slice(chunkSize);
|
|
46
|
+
this.port.postMessage({ pcm: chunk });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
registerProcessor('pcm-capture-processor', PcmCaptureProcessor);
|
|
54
|
+
`;
|
|
55
|
+
// ── Main class ───────────────────────────────────────────────
|
|
56
|
+
export class AiPlaygroundSession {
|
|
57
|
+
wsUrl;
|
|
58
|
+
ws = null;
|
|
59
|
+
audioContext = null;
|
|
60
|
+
mediaStream = null;
|
|
61
|
+
sourceNode = null;
|
|
62
|
+
workletNode = null;
|
|
63
|
+
scriptNode = null;
|
|
64
|
+
_isConnected = false;
|
|
65
|
+
_isMuted = false;
|
|
66
|
+
listeners = {};
|
|
67
|
+
// Playback
|
|
68
|
+
playbackCtx = null;
|
|
69
|
+
nextPlayTime = 0;
|
|
70
|
+
constructor(wsUrl) {
|
|
71
|
+
this.wsUrl = wsUrl;
|
|
72
|
+
}
|
|
73
|
+
/** Whether the session is connected and streaming. */
|
|
74
|
+
get isConnected() {
|
|
75
|
+
return this._isConnected;
|
|
76
|
+
}
|
|
77
|
+
/** Whether the microphone is muted. */
|
|
78
|
+
get isMuted() {
|
|
79
|
+
return this._isMuted;
|
|
80
|
+
}
|
|
81
|
+
/** Register an event listener. */
|
|
82
|
+
on(event, cb) {
|
|
83
|
+
if (!this.listeners[event])
|
|
84
|
+
this.listeners[event] = [];
|
|
85
|
+
this.listeners[event].push(cb);
|
|
86
|
+
}
|
|
87
|
+
/** Remove an event listener. */
|
|
88
|
+
off(event, cb) {
|
|
89
|
+
const arr = this.listeners[event];
|
|
90
|
+
if (arr) {
|
|
91
|
+
this.listeners[event] = arr.filter(fn => fn !== cb);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
emit(event, ...args) {
|
|
95
|
+
const arr = this.listeners[event];
|
|
96
|
+
if (arr) {
|
|
97
|
+
for (const fn of arr) {
|
|
98
|
+
try {
|
|
99
|
+
fn(...args);
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
console.error(`[Playground] Event handler error:`, e);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Start the playground session: connect WebSocket + capture microphone. */
|
|
108
|
+
async start() {
|
|
109
|
+
// 1. Open WebSocket
|
|
110
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
111
|
+
this.ws.binaryType = 'arraybuffer';
|
|
112
|
+
this.ws.onopen = () => {
|
|
113
|
+
console.log('[Playground] WebSocket connected');
|
|
114
|
+
};
|
|
115
|
+
this.ws.onmessage = (event) => {
|
|
116
|
+
if (event.data instanceof ArrayBuffer) {
|
|
117
|
+
// Binary = PCM audio from AI agent
|
|
118
|
+
this.playAudio(event.data);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// Text = JSON event
|
|
122
|
+
try {
|
|
123
|
+
const msg = JSON.parse(event.data);
|
|
124
|
+
this.handleServerMessage(msg);
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
console.error('[Playground] Bad JSON:', e);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
this.ws.onerror = (event) => {
|
|
132
|
+
console.error('[Playground] WebSocket error:', event);
|
|
133
|
+
this.emit('error', new Error('WebSocket connection error'));
|
|
134
|
+
};
|
|
135
|
+
this.ws.onclose = (event) => {
|
|
136
|
+
console.log('[Playground] WebSocket closed:', event.code, event.reason);
|
|
137
|
+
this._isConnected = false;
|
|
138
|
+
if (event.code !== 1000) {
|
|
139
|
+
this.emit('error', new Error(`WebSocket closed: ${event.code} ${event.reason}`));
|
|
140
|
+
}
|
|
141
|
+
this.cleanup();
|
|
142
|
+
};
|
|
143
|
+
// 2. Capture microphone
|
|
144
|
+
try {
|
|
145
|
+
this.mediaStream = await navigator.mediaDevices.getUserMedia({
|
|
146
|
+
audio: {
|
|
147
|
+
channelCount: 1,
|
|
148
|
+
sampleRate: INPUT_SAMPLE_RATE,
|
|
149
|
+
echoCancellation: true,
|
|
150
|
+
noiseSuppression: true,
|
|
151
|
+
autoGainControl: true,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
this.emit('error', new Error('Microphone access denied: ' + err.message));
|
|
157
|
+
this.ws?.close();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// 3. Set up audio processing
|
|
161
|
+
this.audioContext = new AudioContext({ sampleRate: INPUT_SAMPLE_RATE });
|
|
162
|
+
this.sourceNode = this.audioContext.createMediaStreamSource(this.mediaStream);
|
|
163
|
+
// Try AudioWorklet first, fall back to ScriptProcessor
|
|
164
|
+
try {
|
|
165
|
+
const blob = new Blob([WORKLET_CODE], { type: 'application/javascript' });
|
|
166
|
+
const url = URL.createObjectURL(blob);
|
|
167
|
+
await this.audioContext.audioWorklet.addModule(url);
|
|
168
|
+
URL.revokeObjectURL(url);
|
|
169
|
+
this.workletNode = new AudioWorkletNode(this.audioContext, 'pcm-capture-processor');
|
|
170
|
+
this.workletNode.port.onmessage = (e) => {
|
|
171
|
+
if (this._isMuted || !this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
172
|
+
return;
|
|
173
|
+
const float32 = e.data.pcm;
|
|
174
|
+
const pcm16 = this.float32ToPcm16(float32);
|
|
175
|
+
this.ws.send(pcm16.buffer);
|
|
176
|
+
};
|
|
177
|
+
this.sourceNode.connect(this.workletNode);
|
|
178
|
+
this.workletNode.connect(this.audioContext.destination); // needed for worklet to process
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Fallback: ScriptProcessorNode (deprecated but widely supported)
|
|
182
|
+
console.warn('[Playground] AudioWorklet not supported, using ScriptProcessor fallback');
|
|
183
|
+
this.scriptNode = this.audioContext.createScriptProcessor(BUFFER_SIZE, 1, 1);
|
|
184
|
+
this.scriptNode.onaudioprocess = (e) => {
|
|
185
|
+
if (this._isMuted || !this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
186
|
+
return;
|
|
187
|
+
const float32 = e.inputBuffer.getChannelData(0);
|
|
188
|
+
// Resample to 16kHz if needed
|
|
189
|
+
const resampled = this.audioContext.sampleRate !== INPUT_SAMPLE_RATE
|
|
190
|
+
? this.resample(float32, this.audioContext.sampleRate, INPUT_SAMPLE_RATE)
|
|
191
|
+
: float32;
|
|
192
|
+
const pcm16 = this.float32ToPcm16(resampled);
|
|
193
|
+
this.ws.send(pcm16.buffer);
|
|
194
|
+
};
|
|
195
|
+
this.sourceNode.connect(this.scriptNode);
|
|
196
|
+
this.scriptNode.connect(this.audioContext.destination);
|
|
197
|
+
}
|
|
198
|
+
// 4. Set up playback context (for AI audio at 24kHz)
|
|
199
|
+
this.playbackCtx = new AudioContext({ sampleRate: OUTPUT_SAMPLE_RATE });
|
|
200
|
+
this.nextPlayTime = 0;
|
|
201
|
+
this._isConnected = true;
|
|
202
|
+
}
|
|
203
|
+
/** Disconnect and clean up all resources. */
|
|
204
|
+
disconnect() {
|
|
205
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
206
|
+
try {
|
|
207
|
+
this.ws.send(JSON.stringify({ type: 'end' }));
|
|
208
|
+
}
|
|
209
|
+
catch { }
|
|
210
|
+
this.ws.close(1000, 'user disconnected');
|
|
211
|
+
}
|
|
212
|
+
this.cleanup();
|
|
213
|
+
}
|
|
214
|
+
/** Mute microphone (stops sending audio, AI still plays). */
|
|
215
|
+
mute() {
|
|
216
|
+
this._isMuted = true;
|
|
217
|
+
}
|
|
218
|
+
/** Unmute microphone. */
|
|
219
|
+
unmute() {
|
|
220
|
+
this._isMuted = false;
|
|
221
|
+
}
|
|
222
|
+
// ── Private methods ──────────────────────────────────────
|
|
223
|
+
handleServerMessage(msg) {
|
|
224
|
+
switch (msg.type) {
|
|
225
|
+
case 'ready':
|
|
226
|
+
this._isConnected = true;
|
|
227
|
+
this.emit('ready');
|
|
228
|
+
break;
|
|
229
|
+
case 'tool_call':
|
|
230
|
+
this.emit('toolCall', { function: msg.function, args: msg.args });
|
|
231
|
+
break;
|
|
232
|
+
case 'tool_result':
|
|
233
|
+
this.emit('toolResult', { function: msg.function, status: msg.status, message: msg.message });
|
|
234
|
+
break;
|
|
235
|
+
case 'end':
|
|
236
|
+
this.emit('end', { reason: msg.reason || 'unknown' });
|
|
237
|
+
this.cleanup();
|
|
238
|
+
break;
|
|
239
|
+
case 'error':
|
|
240
|
+
this.emit('error', new Error(msg.message || 'Unknown error'));
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
playAudio(pcmBuffer) {
|
|
245
|
+
if (!this.playbackCtx)
|
|
246
|
+
return;
|
|
247
|
+
// Convert raw PCM 16-bit LE to Float32
|
|
248
|
+
const pcm16 = new Int16Array(pcmBuffer);
|
|
249
|
+
const float32 = new Float32Array(pcm16.length);
|
|
250
|
+
for (let i = 0; i < pcm16.length; i++) {
|
|
251
|
+
float32[i] = pcm16[i] / 32768;
|
|
252
|
+
}
|
|
253
|
+
// Create audio buffer and schedule playback
|
|
254
|
+
const audioBuffer = this.playbackCtx.createBuffer(1, float32.length, OUTPUT_SAMPLE_RATE);
|
|
255
|
+
audioBuffer.getChannelData(0).set(float32);
|
|
256
|
+
const source = this.playbackCtx.createBufferSource();
|
|
257
|
+
source.buffer = audioBuffer;
|
|
258
|
+
source.connect(this.playbackCtx.destination);
|
|
259
|
+
// Schedule seamlessly after previous chunk
|
|
260
|
+
const now = this.playbackCtx.currentTime;
|
|
261
|
+
if (this.nextPlayTime < now) {
|
|
262
|
+
this.nextPlayTime = now + 0.05; // 50ms initial buffer
|
|
263
|
+
}
|
|
264
|
+
source.start(this.nextPlayTime);
|
|
265
|
+
this.nextPlayTime += audioBuffer.duration;
|
|
266
|
+
}
|
|
267
|
+
float32ToPcm16(float32) {
|
|
268
|
+
const pcm16 = new Int16Array(float32.length);
|
|
269
|
+
for (let i = 0; i < float32.length; i++) {
|
|
270
|
+
const s = Math.max(-1, Math.min(1, float32[i]));
|
|
271
|
+
pcm16[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
|
272
|
+
}
|
|
273
|
+
return pcm16;
|
|
274
|
+
}
|
|
275
|
+
resample(input, fromRate, toRate) {
|
|
276
|
+
if (fromRate === toRate)
|
|
277
|
+
return input;
|
|
278
|
+
const ratio = fromRate / toRate;
|
|
279
|
+
const outputLen = Math.floor(input.length / ratio);
|
|
280
|
+
const output = new Float32Array(outputLen);
|
|
281
|
+
for (let i = 0; i < outputLen; i++) {
|
|
282
|
+
const srcIdx = i * ratio;
|
|
283
|
+
const idx = Math.floor(srcIdx);
|
|
284
|
+
const frac = srcIdx - idx;
|
|
285
|
+
const a = input[idx] || 0;
|
|
286
|
+
const b = input[idx + 1] || 0;
|
|
287
|
+
output[i] = a + frac * (b - a);
|
|
288
|
+
}
|
|
289
|
+
return output;
|
|
290
|
+
}
|
|
291
|
+
cleanup() {
|
|
292
|
+
this._isConnected = false;
|
|
293
|
+
if (this.workletNode) {
|
|
294
|
+
this.workletNode.disconnect();
|
|
295
|
+
this.workletNode = null;
|
|
296
|
+
}
|
|
297
|
+
if (this.scriptNode) {
|
|
298
|
+
this.scriptNode.disconnect();
|
|
299
|
+
this.scriptNode = null;
|
|
300
|
+
}
|
|
301
|
+
if (this.sourceNode) {
|
|
302
|
+
this.sourceNode.disconnect();
|
|
303
|
+
this.sourceNode = null;
|
|
304
|
+
}
|
|
305
|
+
if (this.mediaStream) {
|
|
306
|
+
this.mediaStream.getTracks().forEach(t => t.stop());
|
|
307
|
+
this.mediaStream = null;
|
|
308
|
+
}
|
|
309
|
+
if (this.audioContext) {
|
|
310
|
+
this.audioContext.close().catch(() => { });
|
|
311
|
+
this.audioContext = null;
|
|
312
|
+
}
|
|
313
|
+
if (this.playbackCtx) {
|
|
314
|
+
this.playbackCtx.close().catch(() => { });
|
|
315
|
+
this.playbackCtx = null;
|
|
316
|
+
}
|
|
317
|
+
this.ws = null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=playground.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playground.js","sourceRoot":"","sources":["../src/playground.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,gEAAgE;AAEhE,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAG,sBAAsB;AACzD,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAE,sBAAsB;AACzD,MAAM,WAAW,GAAG,IAAI,CAAC,CAAU,yBAAyB;AAE5D,gEAAgE;AAEhE,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCpB,CAAC;AAEF,gEAAgE;AAEhE,MAAM,OAAO,mBAAmB;IAgBpB;IAfF,EAAE,GAAqB,IAAI,CAAC;IAC5B,YAAY,GAAwB,IAAI,CAAC;IACzC,WAAW,GAAuB,IAAI,CAAC;IACvC,UAAU,GAAsC,IAAI,CAAC;IACrD,WAAW,GAA4B,IAAI,CAAC;IAC5C,UAAU,GAA+B,IAAI,CAAC;IAC9C,YAAY,GAAG,KAAK,CAAC;IACrB,QAAQ,GAAG,KAAK,CAAC;IACjB,SAAS,GAAsE,EAAE,CAAC;IAE1F,WAAW;IACH,WAAW,GAAwB,IAAI,CAAC;IACxC,YAAY,GAAG,CAAC,CAAC;IAEzB,YACU,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IACpB,CAAC;IAEJ,sDAAsD;IACtD,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,uCAAuC;IACvC,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,kCAAkC;IAClC,EAAE,CAA4B,KAAQ,EAAE,EAAuB;QAC7D,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACvD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAS,CAAC,CAAC;IACzC,CAAC;IAED,gCAAgC;IAChC,GAAG,CAA4B,KAAQ,EAAE,EAAuB;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAQ,CAAC;QAC7D,CAAC;IACH,CAAC;IAEO,IAAI,CAA4B,KAAQ,EAAE,GAAG,IAAqC;QACxF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrB,IAAI,CAAC;oBAAE,EAAU,CAAC,GAAG,IAAI,CAAC,CAAC;gBAAC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,CAAC,CAAC;gBAAC,CAAC;YACpG,CAAC;QACH,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,KAAK;QACT,oBAAoB;QACpB,IAAI,CAAC,EAAE,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE,CAAC,UAAU,GAAG,aAAa,CAAC;QAEnC,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE;YAC5B,IAAI,KAAK,CAAC,IAAI,YAAY,WAAW,EAAE,CAAC;gBACtC,mCAAmC;gBACnC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,oBAAoB;gBACpB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAc,CAAC,CAAC;oBAC7C,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBAChC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACxE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QAEF,wBAAwB;QACxB,IAAI,CAAC;YACH,IAAI,CAAC,WAAW,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC3D,KAAK,EAAE;oBACL,YAAY,EAAE,CAAC;oBACf,UAAU,EAAE,iBAAiB;oBAC7B,gBAAgB,EAAE,IAAI;oBACtB,gBAAgB,EAAE,IAAI;oBACtB,eAAe,EAAE,IAAI;iBACtB;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,4BAA4B,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE9E,uDAAuD;QACvD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC,CAAC;YAC1E,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACpD,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAEzB,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;YACpF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE;gBACtC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;oBAAE,OAAO;gBAC/E,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAmB,CAAC;gBAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBAC3C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,gCAAgC;QAC3F,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,OAAO,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;YACxF,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7E,IAAI,CAAC,UAAU,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,EAAE;gBACrC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;oBAAE,OAAO;gBAC/E,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;gBAEhD,8BAA8B;gBAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,YAAa,CAAC,UAAU,KAAK,iBAAiB;oBACnE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,YAAa,CAAC,UAAU,EAAE,iBAAiB,CAAC;oBAC1E,CAAC,CAAC,OAAO,CAAC;gBAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;gBAC7C,IAAI,CAAC,EAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACzD,CAAC;QAED,qDAAqD;QACrD,IAAI,CAAC,WAAW,GAAG,IAAI,YAAY,CAAC,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QAEtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,6CAA6C;IAC7C,UAAU;QACR,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACrD,IAAI,CAAC;gBACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,6DAA6D;IAC7D,IAAI;QACF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,yBAAyB;IACzB,MAAM;QACJ,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,4DAA4D;IAEpD,mBAAmB,CAAC,GAAQ;QAClC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,OAAO;gBACV,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnB,MAAM;YACR,KAAK,WAAW;gBACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClE,MAAM;YACR,KAAK,aAAa;gBAChB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9F,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;gBACtD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC,CAAC;gBAC9D,MAAM;QACV,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,SAAsB;QACtC,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAE9B,uCAAuC;QACvC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAChC,CAAC;QAED,4CAA4C;QAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACzF,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;QACrD,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAE7C,2CAA2C;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;QACzC,IAAI,IAAI,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;YAC5B,IAAI,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,sBAAsB;QACxD,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChC,IAAI,CAAC,YAAY,IAAI,WAAW,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAEO,cAAc,CAAC,OAAqB;QAC1C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;QAC7C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,QAAQ,CAAC,KAAmB,EAAE,QAAgB,EAAE,MAAc;QACpE,IAAI,QAAQ,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;YAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAE1B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;IACjB,CAAC;CACF"}
|