@framers/agentos 0.9.123 → 0.9.125

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 (60) hide show
  1. package/dist/io/avatar/index.d.ts +13 -0
  2. package/dist/io/avatar/index.d.ts.map +1 -0
  3. package/dist/io/avatar/index.js +12 -0
  4. package/dist/io/avatar/index.js.map +1 -0
  5. package/dist/io/avatar/providerCatalog.d.ts +24 -0
  6. package/dist/io/avatar/providerCatalog.d.ts.map +1 -0
  7. package/dist/io/avatar/providerCatalog.js +21 -0
  8. package/dist/io/avatar/providerCatalog.js.map +1 -0
  9. package/dist/io/avatar/providers/SimliAvatarProvider.d.ts +44 -0
  10. package/dist/io/avatar/providers/SimliAvatarProvider.d.ts.map +1 -0
  11. package/dist/io/avatar/providers/SimliAvatarProvider.js +90 -0
  12. package/dist/io/avatar/providers/SimliAvatarProvider.js.map +1 -0
  13. package/dist/io/avatar/providers/SimliServerSession.d.ts +78 -0
  14. package/dist/io/avatar/providers/SimliServerSession.d.ts.map +1 -0
  15. package/dist/io/avatar/providers/SimliServerSession.js +178 -0
  16. package/dist/io/avatar/providers/SimliServerSession.js.map +1 -0
  17. package/dist/io/avatar/types.d.ts +77 -0
  18. package/dist/io/avatar/types.d.ts.map +1 -0
  19. package/dist/io/avatar/types.js +19 -0
  20. package/dist/io/avatar/types.js.map +1 -0
  21. package/dist/io/voice-pipeline/env-constructor.d.ts +5 -3
  22. package/dist/io/voice-pipeline/env-constructor.d.ts.map +1 -1
  23. package/dist/io/voice-pipeline/env-constructor.js +25 -0
  24. package/dist/io/voice-pipeline/env-constructor.js.map +1 -1
  25. package/dist/io/voice-pipeline/provider-family.d.ts +1 -1
  26. package/dist/io/voice-pipeline/provider-family.d.ts.map +1 -1
  27. package/dist/io/voice-pipeline/provider-family.js +4 -0
  28. package/dist/io/voice-pipeline/provider-family.js.map +1 -1
  29. package/dist/io/voice-pipeline/providers/CartesiaBatchTTS.d.ts +79 -0
  30. package/dist/io/voice-pipeline/providers/CartesiaBatchTTS.d.ts.map +1 -0
  31. package/dist/io/voice-pipeline/providers/CartesiaBatchTTS.js +163 -0
  32. package/dist/io/voice-pipeline/providers/CartesiaBatchTTS.js.map +1 -0
  33. package/dist/io/voice-pipeline/providers/CartesiaStreamingTTS.d.ts +57 -0
  34. package/dist/io/voice-pipeline/providers/CartesiaStreamingTTS.d.ts.map +1 -0
  35. package/dist/io/voice-pipeline/providers/CartesiaStreamingTTS.js +235 -0
  36. package/dist/io/voice-pipeline/providers/CartesiaStreamingTTS.js.map +1 -0
  37. package/dist/io/voice-pipeline/providers/HumeBatchTTS.d.ts +81 -0
  38. package/dist/io/voice-pipeline/providers/HumeBatchTTS.d.ts.map +1 -0
  39. package/dist/io/voice-pipeline/providers/HumeBatchTTS.js +177 -0
  40. package/dist/io/voice-pipeline/providers/HumeBatchTTS.js.map +1 -0
  41. package/dist/io/voice-pipeline/providers/HumeStreamingTTS.d.ts +58 -0
  42. package/dist/io/voice-pipeline/providers/HumeStreamingTTS.d.ts.map +1 -0
  43. package/dist/io/voice-pipeline/providers/HumeStreamingTTS.js +240 -0
  44. package/dist/io/voice-pipeline/providers/HumeStreamingTTS.js.map +1 -0
  45. package/dist/io/voice-pipeline/providers/index.d.ts +4 -0
  46. package/dist/io/voice-pipeline/providers/index.d.ts.map +1 -1
  47. package/dist/io/voice-pipeline/providers/index.js +4 -0
  48. package/dist/io/voice-pipeline/providers/index.js.map +1 -1
  49. package/dist/io/voice-pipeline/types.d.ts +8 -0
  50. package/dist/io/voice-pipeline/types.d.ts.map +1 -1
  51. package/dist/safety/sandbox/executor/CodeSandbox.d.ts.map +1 -1
  52. package/dist/safety/sandbox/executor/CodeSandbox.js +19 -1
  53. package/dist/safety/sandbox/executor/CodeSandbox.js.map +1 -1
  54. package/dist/safety/sandbox/subprocess/CLIRegistry.d.ts.map +1 -1
  55. package/dist/safety/sandbox/subprocess/CLIRegistry.js +18 -1
  56. package/dist/safety/sandbox/subprocess/CLIRegistry.js.map +1 -1
  57. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.d.ts.map +1 -1
  58. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.js +21 -1
  59. package/dist/safety/sandbox/subprocess/CLISubprocessBridge.js.map +1 -1
  60. package/package.json +6 -1
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @module io/avatar
3
+ *
4
+ * Realtime-avatar seam: provider-agnostic control plane
5
+ * ({@link IAvatarProvider}), discovery catalog, and the Simli
6
+ * implementation (client-delegated handle + server-driven WS/WebRTC
7
+ * session).
8
+ */
9
+ export type { AvatarIceServer, AvatarMediaMode, AvatarSessionConfig, AvatarSessionHandle, IAvatarProvider, } from './types.js';
10
+ export { AVATAR_PROVIDER_CATALOG, type AvatarProviderCatalogEntry, } from './providerCatalog.js';
11
+ export { SimliAvatarProvider, type SimliAvatarProviderConfig, } from './providers/SimliAvatarProvider.js';
12
+ export { createSimliServerSession, SimliServerSession, type SimliServerSessionOptions, } from './providers/SimliServerSession.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/io/avatar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,KAAK,0BAA0B,GAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,KAAK,yBAAyB,GAC/B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,yBAAyB,GAC/B,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module io/avatar
3
+ *
4
+ * Realtime-avatar seam: provider-agnostic control plane
5
+ * ({@link IAvatarProvider}), discovery catalog, and the Simli
6
+ * implementation (client-delegated handle + server-driven WS/WebRTC
7
+ * session).
8
+ */
9
+ export { AVATAR_PROVIDER_CATALOG, } from './providerCatalog.js';
10
+ export { SimliAvatarProvider, } from './providers/SimliAvatarProvider.js';
11
+ export { createSimliServerSession, SimliServerSession, } from './providers/SimliServerSession.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/io/avatar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,EACL,uBAAuB,GAExB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,GAEpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,wBAAwB,EACxB,kBAAkB,GAEnB,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @module io/avatar/providerCatalog
3
+ *
4
+ * Discovery catalog for realtime-avatar providers — the avatar sibling of
5
+ * `SPEECH_PROVIDER_CATALOG`. Deliberately small and separate: realtime
6
+ * avatars are a different concern from speech vendors, and the catalog only
7
+ * grows when a provider actually ships in `providers/`.
8
+ */
9
+ import type { AvatarMediaMode } from './types.js';
10
+ /** One discoverable avatar provider. */
11
+ export interface AvatarProviderCatalogEntry {
12
+ id: string;
13
+ label: string;
14
+ /** Env vars whose presence unlocks the provider. */
15
+ envVars: string[];
16
+ description: string;
17
+ mediaModes: AvatarMediaMode[];
18
+ audioFormat: 'pcm16';
19
+ /** Default upstream sample rate (Hz); provider-config overridable. */
20
+ defaultSampleRate: number;
21
+ features: string[];
22
+ }
23
+ export declare const AVATAR_PROVIDER_CATALOG: readonly AvatarProviderCatalogEntry[];
24
+ //# sourceMappingURL=providerCatalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerCatalog.d.ts","sourceRoot":"","sources":["../../../src/io/avatar/providerCatalog.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wCAAwC;AACxC,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,uBAAuB,EAAE,SAAS,0BAA0B,EAWxE,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @module io/avatar/providerCatalog
3
+ *
4
+ * Discovery catalog for realtime-avatar providers — the avatar sibling of
5
+ * `SPEECH_PROVIDER_CATALOG`. Deliberately small and separate: realtime
6
+ * avatars are a different concern from speech vendors, and the catalog only
7
+ * grows when a provider actually ships in `providers/`.
8
+ */
9
+ export const AVATAR_PROVIDER_CATALOG = [
10
+ {
11
+ id: 'simli',
12
+ label: 'Simli',
13
+ envVars: ['SIMLI_API_KEY'],
14
+ description: 'Realtime lip-synced avatar over WebRTC (Compose API).',
15
+ mediaModes: ['client-delegated', 'server-driven'],
16
+ audioFormat: 'pcm16',
17
+ defaultSampleRate: 16000,
18
+ features: ['webrtc', 'lipsync', 'barge-in', 'sfu-relay'],
19
+ },
20
+ ];
21
+ //# sourceMappingURL=providerCatalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerCatalog.js","sourceRoot":"","sources":["../../../src/io/avatar/providerCatalog.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,MAAM,CAAC,MAAM,uBAAuB,GAA0C;IAC5E;QACE,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,CAAC,eAAe,CAAC;QAC1B,WAAW,EAAE,uDAAuD;QACpE,UAAU,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC;QACjD,WAAW,EAAE,OAAO;QACpB,iBAAiB,EAAE,KAAK;QACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC;KACzD;CACF,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @module io/avatar/providers/SimliAvatarProvider
3
+ *
4
+ * Simli realtime-avatar provider — control plane. Mints Compose sessions
5
+ * (`POST /compose/token`) and resolves ICE servers (`GET /compose/ice`).
6
+ * Media is joined per {@link AvatarMediaMode}: hand the returned
7
+ * {@link AvatarSessionHandle} to the browser SDK (client-delegated), or to
8
+ * `createSimliServerSession()` for the Node-owned WebRTC path.
9
+ *
10
+ * Contract (verified 2026-07-08 against the Compose REST + AsyncAPI docs):
11
+ * auth header `x-simli-api-key`; token body `{ faceId, apiVersion: 'v2',
12
+ * handleSilence, maxSessionLength, maxIdleTime, audioInputFormat: 'pcm16' }`;
13
+ * the upstream sample rate is NOT publicly pinned — 16000 Hz is the
14
+ * SDK-observed default, carried as config-overridable data.
15
+ */
16
+ import type { AvatarIceServer, AvatarSessionConfig, AvatarSessionHandle, IAvatarProvider } from '../types.js';
17
+ /** Configuration for the Simli avatar provider. */
18
+ export interface SimliAvatarProviderConfig {
19
+ /** Simli API key. */
20
+ apiKey: string;
21
+ /** Base URL for the Simli API. @default 'https://api.simli.ai' */
22
+ baseUrl?: string;
23
+ /** Upstream pcm16 sample rate (Hz). @default 16000 */
24
+ sampleRate?: number;
25
+ }
26
+ /**
27
+ * Control-plane implementation of {@link IAvatarProvider} for Simli.
28
+ */
29
+ export declare class SimliAvatarProvider implements IAvatarProvider {
30
+ readonly providerId = "simli";
31
+ readonly capabilities: IAvatarProvider['capabilities'];
32
+ private readonly apiKey;
33
+ private readonly baseUrl;
34
+ private readonly sampleRate;
35
+ constructor(config: SimliAvatarProviderConfig);
36
+ /**
37
+ * Mint a Compose session token and resolve ICE, returning the complete
38
+ * media-join handle.
39
+ */
40
+ createSession(config: AvatarSessionConfig): Promise<AvatarSessionHandle>;
41
+ /** Fetch ICE servers (`GET /compose/ice`). */
42
+ getIceServers(): Promise<AvatarIceServer[]>;
43
+ }
44
+ //# sourceMappingURL=SimliAvatarProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimliAvatarProvider.d.ts","sourceRoot":"","sources":["../../../../src/io/avatar/providers/SimliAvatarProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EAChB,MAAM,aAAa,CAAC;AAKrB,mDAAmD;AACnD,MAAM,WAAW,yBAAyB;IACxC,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC;IAEvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,yBAAyB;IAW7C;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAoC9E,8CAA8C;IACxC,aAAa,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;CAoBlD"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @module io/avatar/providers/SimliAvatarProvider
3
+ *
4
+ * Simli realtime-avatar provider — control plane. Mints Compose sessions
5
+ * (`POST /compose/token`) and resolves ICE servers (`GET /compose/ice`).
6
+ * Media is joined per {@link AvatarMediaMode}: hand the returned
7
+ * {@link AvatarSessionHandle} to the browser SDK (client-delegated), or to
8
+ * `createSimliServerSession()` for the Node-owned WebRTC path.
9
+ *
10
+ * Contract (verified 2026-07-08 against the Compose REST + AsyncAPI docs):
11
+ * auth header `x-simli-api-key`; token body `{ faceId, apiVersion: 'v2',
12
+ * handleSilence, maxSessionLength, maxIdleTime, audioInputFormat: 'pcm16' }`;
13
+ * the upstream sample rate is NOT publicly pinned — 16000 Hz is the
14
+ * SDK-observed default, carried as config-overridable data.
15
+ */
16
+ /** Per-request control-plane timeout (session minting must be snappy). */
17
+ const CONTROL_PLANE_TIMEOUT_MS = 10000;
18
+ /**
19
+ * Control-plane implementation of {@link IAvatarProvider} for Simli.
20
+ */
21
+ export class SimliAvatarProvider {
22
+ constructor(config) {
23
+ this.providerId = 'simli';
24
+ this.apiKey = config.apiKey;
25
+ this.baseUrl = config.baseUrl ?? 'https://api.simli.ai';
26
+ this.sampleRate = config.sampleRate ?? 16000;
27
+ this.capabilities = {
28
+ mediaModes: ['client-delegated', 'server-driven'],
29
+ audioFormat: 'pcm16',
30
+ sampleRate: this.sampleRate,
31
+ };
32
+ }
33
+ /**
34
+ * Mint a Compose session token and resolve ICE, returning the complete
35
+ * media-join handle.
36
+ */
37
+ async createSession(config) {
38
+ const res = await fetch(`${this.baseUrl}/compose/token`, {
39
+ method: 'POST',
40
+ headers: {
41
+ 'x-simli-api-key': this.apiKey,
42
+ 'Content-Type': 'application/json',
43
+ },
44
+ body: JSON.stringify({
45
+ faceId: config.faceId,
46
+ apiVersion: 'v2',
47
+ handleSilence: true,
48
+ audioInputFormat: 'pcm16',
49
+ ...(config.maxSessionLengthSec != null
50
+ ? { maxSessionLength: config.maxSessionLengthSec }
51
+ : {}),
52
+ ...(config.maxIdleTimeSec != null ? { maxIdleTime: config.maxIdleTimeSec } : {}),
53
+ ...(config.providerOptions ?? {}),
54
+ }),
55
+ signal: AbortSignal.timeout(CONTROL_PLANE_TIMEOUT_MS),
56
+ });
57
+ if (!res.ok) {
58
+ const detail = await res.text().catch(() => '');
59
+ throw new Error(`Simli session mint failed: ${res.status} ${detail.slice(0, 200)}`);
60
+ }
61
+ const payload = (await res.json());
62
+ if (!payload.session_token) {
63
+ throw new Error('Simli session mint returned no session_token');
64
+ }
65
+ return {
66
+ sessionToken: payload.session_token,
67
+ iceServers: await this.getIceServers(),
68
+ audioFormat: 'pcm16',
69
+ sampleRate: this.sampleRate,
70
+ };
71
+ }
72
+ /** Fetch ICE servers (`GET /compose/ice`). */
73
+ async getIceServers() {
74
+ const res = await fetch(`${this.baseUrl}/compose/ice`, {
75
+ headers: { 'x-simli-api-key': this.apiKey },
76
+ signal: AbortSignal.timeout(CONTROL_PLANE_TIMEOUT_MS),
77
+ });
78
+ if (!res.ok) {
79
+ const detail = await res.text().catch(() => '');
80
+ throw new Error(`Simli ICE fetch failed: ${res.status} ${detail.slice(0, 200)}`);
81
+ }
82
+ const payload = (await res.json());
83
+ return payload.map((s) => ({
84
+ urls: s.urls,
85
+ ...(s.username != null ? { username: s.username } : {}),
86
+ ...(s.credential != null ? { credential: s.credential } : {}),
87
+ }));
88
+ }
89
+ }
90
+ //# sourceMappingURL=SimliAvatarProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimliAvatarProvider.js","sourceRoot":"","sources":["../../../../src/io/avatar/providers/SimliAvatarProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @module io/avatar/providers/SimliServerSession
3
+ *
4
+ * Server-driven media path for Simli: Node owns the WebRTC peer connection
5
+ * and drives the avatar over Simli's documented AsyncAPI websocket protocol
6
+ * (`wss …/compose/webrtc/peer_to_peer`).
7
+ *
8
+ * Protocol (verified 2026-07-08 against api.simli.ai/asyncapi.yaml):
9
+ * - Session token rides the query string; optional `enableSFU=true` relays
10
+ * traffic through Cloudflare for reliability.
11
+ * - The FIRST websocket message must be an RTC offer (`{type:'offer',sdp}`)
12
+ * within 30 seconds; the server replies `{type:'answer',sdp}`.
13
+ * - Upstream audio is BINARY frames (pcm16 chunks as raw bytes — never
14
+ * base64/JSON).
15
+ * - Control strings: `"SKIP"` (avatar stops speaking immediately and drops
16
+ * all buffered audio — the barge-in primitive) and `"DONE"` (close after
17
+ * playing out remaining audio).
18
+ * - Server events arrive as text (`START|ACK|STOP|SPEAK|SILENT`); terminal
19
+ * strings matching `ERROR|RATE|CLOSING …` surface as errors.
20
+ *
21
+ * The native `wrtc` dependency is dynamically imported inside
22
+ * {@link createSimliServerSession} (mirroring `createWebRTCTransport()`), so
23
+ * importing this module never requires the native dep — only USING the
24
+ * server-driven mode does. Client-delegated consumers never touch this file.
25
+ */
26
+ import { EventEmitter } from 'node:events';
27
+ import WebSocket from 'ws';
28
+ import type { AvatarSessionHandle } from '../types.js';
29
+ /** Options for {@link createSimliServerSession}. */
30
+ export interface SimliServerSessionOptions {
31
+ /** Relay traffic through Cloudflare's network (AsyncAPI `enableSFU`). */
32
+ enableSFU?: boolean;
33
+ /** Websocket base. @default 'wss://api.simli.ai' */
34
+ wsBaseUrl?: string;
35
+ /** Injectable wrtc loader for tests. @default dynamic `import('wrtc')` */
36
+ loadWrtc?: () => Promise<unknown>;
37
+ /** Injectable websocket factory for tests. */
38
+ wsFactory?: (url: string) => WebSocket;
39
+ }
40
+ /**
41
+ * One live server-driven Simli session: an owned RTCPeerConnection (media
42
+ * downlink) plus the control/audio websocket (uplink).
43
+ *
44
+ * Events: `'event'` (protocol strings SPEAK/SILENT/…), `'track'` (inbound
45
+ * media track from the peer), `'error'`, `'close'`.
46
+ */
47
+ export declare class SimliServerSession extends EventEmitter {
48
+ private readonly ws;
49
+ private readonly pc;
50
+ private closed;
51
+ constructor(ws: WebSocket, pc: {
52
+ setRemoteDescription(desc: unknown): Promise<void>;
53
+ close(): void;
54
+ });
55
+ private onMessage;
56
+ /**
57
+ * Ship one pcm16 audio chunk for the avatar to lip-sync — BINARY frame,
58
+ * exactly as the AsyncAPI documents (UInt8Array/octet-stream).
59
+ */
60
+ sendAudio(chunk: Buffer): void;
61
+ /** Barge-in: avatar stops speaking NOW and drops all buffered audio. */
62
+ interrupt(): void;
63
+ /** Final segment sent — server closes after playing out the remainder. */
64
+ finish(): void;
65
+ /** Tear down the socket and the peer connection (idempotent). */
66
+ close(): void;
67
+ }
68
+ /**
69
+ * Open a server-driven Simli session: dynamically load `wrtc`, create the
70
+ * peer, connect the websocket, send the offer as the FIRST message, and
71
+ * return the live session. The 30-second offer budget is comfortably met by
72
+ * sending it on socket open.
73
+ *
74
+ * @throws Error with install guidance when the optional `wrtc` native
75
+ * dependency is not available.
76
+ */
77
+ export declare function createSimliServerSession(handle: AvatarSessionHandle, opts?: SimliServerSessionOptions): Promise<SimliServerSession>;
78
+ //# sourceMappingURL=SimliServerSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimliServerSession.d.ts","sourceRoot":"","sources":["../../../../src/io/avatar/providers/SimliServerSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQvD,oDAAoD;AACpD,MAAM,WAAW,yBAAyB;IACxC,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;CACxC;AAED;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAIhD,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJrB,OAAO,CAAC,MAAM,CAAS;gBAGJ,EAAE,EAAE,SAAS,EACb,EAAE,EAAE;QACnB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,KAAK,IAAI,IAAI,CAAC;KACf;IAeH,OAAO,CAAC,SAAS;IA2BjB;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK9B,wEAAwE;IACxE,SAAS,IAAI,IAAI;IAKjB,0EAA0E;IAC1E,MAAM,IAAI,IAAI;IAKd,iEAAiE;IACjE,KAAK,IAAI,IAAI;CAed;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,mBAAmB,EAC3B,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,kBAAkB,CAAC,CA0D7B"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @module io/avatar/providers/SimliServerSession
3
+ *
4
+ * Server-driven media path for Simli: Node owns the WebRTC peer connection
5
+ * and drives the avatar over Simli's documented AsyncAPI websocket protocol
6
+ * (`wss …/compose/webrtc/peer_to_peer`).
7
+ *
8
+ * Protocol (verified 2026-07-08 against api.simli.ai/asyncapi.yaml):
9
+ * - Session token rides the query string; optional `enableSFU=true` relays
10
+ * traffic through Cloudflare for reliability.
11
+ * - The FIRST websocket message must be an RTC offer (`{type:'offer',sdp}`)
12
+ * within 30 seconds; the server replies `{type:'answer',sdp}`.
13
+ * - Upstream audio is BINARY frames (pcm16 chunks as raw bytes — never
14
+ * base64/JSON).
15
+ * - Control strings: `"SKIP"` (avatar stops speaking immediately and drops
16
+ * all buffered audio — the barge-in primitive) and `"DONE"` (close after
17
+ * playing out remaining audio).
18
+ * - Server events arrive as text (`START|ACK|STOP|SPEAK|SILENT`); terminal
19
+ * strings matching `ERROR|RATE|CLOSING …` surface as errors.
20
+ *
21
+ * The native `wrtc` dependency is dynamically imported inside
22
+ * {@link createSimliServerSession} (mirroring `createWebRTCTransport()`), so
23
+ * importing this module never requires the native dep — only USING the
24
+ * server-driven mode does. Client-delegated consumers never touch this file.
25
+ */
26
+ import { EventEmitter } from 'node:events';
27
+ import WebSocket from 'ws';
28
+ /** Server event strings the protocol documents. */
29
+ const SERVER_EVENTS = new Set(['START', 'ACK', 'STOP', 'SPEAK', 'SILENT']);
30
+ /** Terminal error prefixes per the AsyncAPI error message contract. */
31
+ const ERROR_PREFIX = /^(ERROR|RATE|CLOSING)\b/i;
32
+ /**
33
+ * One live server-driven Simli session: an owned RTCPeerConnection (media
34
+ * downlink) plus the control/audio websocket (uplink).
35
+ *
36
+ * Events: `'event'` (protocol strings SPEAK/SILENT/…), `'track'` (inbound
37
+ * media track from the peer), `'error'`, `'close'`.
38
+ */
39
+ export class SimliServerSession extends EventEmitter {
40
+ constructor(ws, pc) {
41
+ super();
42
+ this.ws = ws;
43
+ this.pc = pc;
44
+ this.closed = false;
45
+ ws.on('message', (raw, isBinary) => this.onMessage(raw, isBinary));
46
+ ws.on('close', () => {
47
+ if (!this.closed) {
48
+ this.closed = true;
49
+ this.emit('close');
50
+ }
51
+ });
52
+ ws.on('error', (err) => {
53
+ if (!this.closed)
54
+ this.emit('error', err);
55
+ });
56
+ }
57
+ onMessage(raw, isBinary) {
58
+ if (this.closed || isBinary)
59
+ return;
60
+ const text = String(raw);
61
+ // Answer to our offer → apply to the peer.
62
+ if (text.startsWith('{')) {
63
+ try {
64
+ const msg = JSON.parse(text);
65
+ if (msg.type === 'answer' && typeof msg.sdp === 'string') {
66
+ void this.pc
67
+ .setRemoteDescription({ type: 'answer', sdp: msg.sdp })
68
+ .catch((err) => this.emit('error', err));
69
+ }
70
+ }
71
+ catch {
72
+ /* non-JSON braces — not part of the documented surface */
73
+ }
74
+ return;
75
+ }
76
+ if (SERVER_EVENTS.has(text)) {
77
+ this.emit('event', text);
78
+ return;
79
+ }
80
+ if (ERROR_PREFIX.test(text)) {
81
+ this.emit('error', new Error(`Simli session terminated: ${text}`));
82
+ this.close();
83
+ }
84
+ }
85
+ /**
86
+ * Ship one pcm16 audio chunk for the avatar to lip-sync — BINARY frame,
87
+ * exactly as the AsyncAPI documents (UInt8Array/octet-stream).
88
+ */
89
+ sendAudio(chunk) {
90
+ if (this.closed || this.ws.readyState !== WebSocket.OPEN)
91
+ return;
92
+ this.ws.send(chunk);
93
+ }
94
+ /** Barge-in: avatar stops speaking NOW and drops all buffered audio. */
95
+ interrupt() {
96
+ if (this.closed || this.ws.readyState !== WebSocket.OPEN)
97
+ return;
98
+ this.ws.send('SKIP');
99
+ }
100
+ /** Final segment sent — server closes after playing out the remainder. */
101
+ finish() {
102
+ if (this.closed || this.ws.readyState !== WebSocket.OPEN)
103
+ return;
104
+ this.ws.send('DONE');
105
+ }
106
+ /** Tear down the socket and the peer connection (idempotent). */
107
+ close() {
108
+ if (this.closed)
109
+ return;
110
+ this.closed = true;
111
+ try {
112
+ this.ws.close();
113
+ }
114
+ catch {
115
+ /* already gone */
116
+ }
117
+ try {
118
+ this.pc.close();
119
+ }
120
+ catch {
121
+ /* already gone */
122
+ }
123
+ this.emit('close');
124
+ }
125
+ }
126
+ /**
127
+ * Open a server-driven Simli session: dynamically load `wrtc`, create the
128
+ * peer, connect the websocket, send the offer as the FIRST message, and
129
+ * return the live session. The 30-second offer budget is comfortably met by
130
+ * sending it on socket open.
131
+ *
132
+ * @throws Error with install guidance when the optional `wrtc` native
133
+ * dependency is not available.
134
+ */
135
+ export async function createSimliServerSession(handle, opts = {}) {
136
+ const loadWrtc = opts.loadWrtc ?? (() => import('wrtc'));
137
+ let wrtcModule;
138
+ try {
139
+ wrtcModule = await loadWrtc();
140
+ }
141
+ catch (err) {
142
+ throw new Error('Simli server-driven mode requires the optional `wrtc` package ' +
143
+ '(npm install wrtc, or a compatible polyfill). Client-delegated mode ' +
144
+ `needs no native deps. Underlying error: ${err.message}`);
145
+ }
146
+ const { RTCPeerConnection } = wrtcModule;
147
+ const pc = new RTCPeerConnection({ iceServers: handle.iceServers });
148
+ // Receive-only media: the avatar's audio+video come DOWN the peer; our
149
+ // audio goes UP the websocket as binary chunks.
150
+ pc.addTransceiver?.('video', { direction: 'recvonly' });
151
+ pc.addTransceiver?.('audio', { direction: 'recvonly' });
152
+ const base = opts.wsBaseUrl ?? 'wss://api.simli.ai';
153
+ const url = `${base}/compose/webrtc/peer_to_peer?session_token=${encodeURIComponent(handle.sessionToken)}` +
154
+ (opts.enableSFU ? '&enableSFU=true' : '');
155
+ const ws = opts.wsFactory ? opts.wsFactory(url) : new WebSocket(url);
156
+ const session = new SimliServerSession(ws, pc);
157
+ pc.ontrack = (ev) => session.emit('track', ev);
158
+ const offer = await pc.createOffer();
159
+ await pc.setLocalDescription(offer);
160
+ await new Promise((resolve, reject) => {
161
+ const onError = (err) => reject(err);
162
+ ws.once('error', onError);
163
+ if (ws.readyState === WebSocket.OPEN) {
164
+ ws.off('error', onError);
165
+ resolve();
166
+ }
167
+ else {
168
+ ws.once('open', () => {
169
+ ws.off('error', onError);
170
+ resolve();
171
+ });
172
+ }
173
+ });
174
+ // FIRST message on the wire must be the offer (30s budget per AsyncAPI).
175
+ ws.send(JSON.stringify({ type: 'offer', sdp: offer.sdp }));
176
+ return session;
177
+ }
178
+ //# sourceMappingURL=SimliServerSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimliServerSession.js","sourceRoot":"","sources":["../../../../src/io/avatar/providers/SimliServerSession.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @module io/avatar/types
3
+ *
4
+ * Provider-agnostic REALTIME avatar seam: control-plane session minting plus
5
+ * media-mode contracts. Distinct from the 2D avatar GEN pipeline in
6
+ * `io/media/avatar` (image generation) — that produces portraits; this
7
+ * animates a live, lip-synced talking head.
8
+ *
9
+ * Media modes:
10
+ * - `client-delegated` — the host hands an {@link AvatarSessionHandle} to a
11
+ * browser SDK which owns the peer connection (the typical web-app path).
12
+ * Node never touches WebRTC; no native deps involved.
13
+ * - `server-driven` — Node owns the WebRTC peer via the optional `wrtc`
14
+ * native dependency (dynamically imported by the session helper, mirroring
15
+ * `createWebRTCTransport()`), signals over the provider's WebSocket, and
16
+ * streams audio server-side.
17
+ */
18
+ /** How the media plane is owned for an avatar session. */
19
+ export type AvatarMediaMode = 'client-delegated' | 'server-driven';
20
+ /** One ICE server entry as handed to an RTCPeerConnection. */
21
+ export interface AvatarIceServer {
22
+ urls: string | string[];
23
+ username?: string;
24
+ credential?: string;
25
+ }
26
+ /** Configuration for minting one avatar session. */
27
+ export interface AvatarSessionConfig {
28
+ /** Provider-specific face/persona id (Simli: `faceId`). */
29
+ faceId: string;
30
+ /** Hard session cap in seconds. Provider default applies when omitted
31
+ * (Simli: 3600). */
32
+ maxSessionLengthSec?: number;
33
+ /** Idle timeout in seconds. Provider default applies when omitted
34
+ * (Simli: 300). */
35
+ maxIdleTimeSec?: number;
36
+ /** Pass-through options forwarded verbatim to the provider API. */
37
+ providerOptions?: Record<string, unknown>;
38
+ }
39
+ /**
40
+ * Everything a media-plane consumer needs to join the avatar session.
41
+ * Client-delegated consumers forward this to the browser SDK; server-driven
42
+ * consumers feed it to the provider's server-session helper.
43
+ */
44
+ export interface AvatarSessionHandle {
45
+ /** Opaque session token the media plane authenticates with. */
46
+ sessionToken: string;
47
+ /** ICE servers for the peer connection. */
48
+ iceServers: AvatarIceServer[];
49
+ /** Upstream audio encoding the avatar lip-syncs to. */
50
+ audioFormat: 'pcm16';
51
+ /**
52
+ * Upstream audio sample rate (Hz). Simli's default is 16000 —
53
+ * config-overridable, and deliberately carried as data rather than a type
54
+ * constant because the vendor spec does not publicly pin it.
55
+ */
56
+ sampleRate: number;
57
+ }
58
+ /**
59
+ * A realtime-avatar provider: mints sessions and exposes the audio contract.
60
+ * Control-plane-first — media ownership is chosen per session by which
61
+ * consumer the handle is given to.
62
+ */
63
+ export interface IAvatarProvider {
64
+ /** Unique, stable identifier for this provider (e.g. 'simli'). */
65
+ readonly providerId: string;
66
+ /** What the provider supports and the audio contract it expects. */
67
+ readonly capabilities: {
68
+ mediaModes: AvatarMediaMode[];
69
+ audioFormat: 'pcm16';
70
+ sampleRate: number;
71
+ };
72
+ /** Mint a session (control plane only — no media is opened here). */
73
+ createSession(config: AvatarSessionConfig): Promise<AvatarSessionHandle>;
74
+ /** Fetch ICE servers for the peer connection. */
75
+ getIceServers(): Promise<AvatarIceServer[]>;
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/io/avatar/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,0DAA0D;AAC1D,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEnE,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;yBACqB;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;wBACoB;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,YAAY,EAAE;QACrB,UAAU,EAAE,eAAe,EAAE,CAAC;QAC9B,WAAW,EAAE,OAAO,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,qEAAqE;IACrE,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,iDAAiD;IACjD,aAAa,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC7C"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @module io/avatar/types
3
+ *
4
+ * Provider-agnostic REALTIME avatar seam: control-plane session minting plus
5
+ * media-mode contracts. Distinct from the 2D avatar GEN pipeline in
6
+ * `io/media/avatar` (image generation) — that produces portraits; this
7
+ * animates a live, lip-synced talking head.
8
+ *
9
+ * Media modes:
10
+ * - `client-delegated` — the host hands an {@link AvatarSessionHandle} to a
11
+ * browser SDK which owns the peer connection (the typical web-app path).
12
+ * Node never touches WebRTC; no native deps involved.
13
+ * - `server-driven` — Node owns the WebRTC peer via the optional `wrtc`
14
+ * native dependency (dynamically imported by the session helper, mirroring
15
+ * `createWebRTCTransport()`), signals over the provider's WebSocket, and
16
+ * streams audio server-side.
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/io/avatar/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
@@ -30,10 +30,12 @@ export interface VoiceProviderEnvConfig {
30
30
  /**
31
31
  * Which TTS vendor to prefer for first-try synthesis. `'deepgram'` (default)
32
32
  * ranks Deepgram Aura ahead of ElevenLabs; `'elevenlabs'` ranks ElevenLabs
33
- * first (used for a paid-tier premium-voice opt-in). Either way the other
34
- * vendors stay in the chain as automatic fallbacks.
33
+ * first (used for a paid-tier premium-voice opt-in); `'cartesia'` / `'hume'`
34
+ * promote those vendors' streaming providers to first-try when their keys
35
+ * are present. Either way the other vendors stay in the chain as automatic
36
+ * fallbacks.
35
37
  */
36
- ttsPreference?: 'deepgram' | 'elevenlabs';
38
+ ttsPreference?: 'deepgram' | 'elevenlabs' | 'cartesia' | 'hume';
37
39
  /** Whether the STT chain keeps a ring buffer + re-routes mid-utterance.
38
40
  * Default true — this is the whole point of the resilience work. */
39
41
  enableMidUtteranceFailover?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"env-constructor.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/env-constructor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIjE,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE;CAO9B;AAED,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;kCAG8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IAC1C;yEACqE;IACrE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;iCAC6B;IAC7B,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB;;+BAE2B;IAC3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAgB,2BAA2B,CACzC,MAAM,GAAE,sBAA2B,GAClC,mBAAmB,CAsFrB"}
1
+ {"version":3,"file":"env-constructor.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/env-constructor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIjE,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE;CAO9B;AAED,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;kCAG8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;IAChE;yEACqE;IACrE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;iCAC6B;IAC7B,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB;;+BAE2B;IAC3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAgB,2BAA2B,CACzC,MAAM,GAAE,sBAA2B,GAClC,mBAAmB,CAkHrB"}