@memberjunction/ai-bridge-livekit 0.0.1 → 5.42.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 CHANGED
@@ -1,45 +1,139 @@
1
1
  # @memberjunction/ai-bridge-livekit
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@memberjunction/ai-bridge-livekit`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
3
+ The **LiveKit** Realtime Bridge driver — the **MJ-native multi-party room**. Unlike every other bridge
4
+ in MemberJunction's Realtime Bridges program (which connect **out** to a 3rd-party meeting platform like
5
+ Zoom/Teams/Meet or a telephony carrier), LiveKit is a **self-hosted WebRTC SFU that MJ runs itself**. The
6
+ architecture treats a Zoom meeting and an MJ-native LiveKit room **identically** — both are multi-party
7
+ media transports — so this is "*another bridge, not a special build.*"
8
+
9
+ It connects the one realtime agent engine to a **LiveKit room** as a bot participant: bidirectional
10
+ audio (and full video/screen), a per-participant diarized roster, room-admin mute, data-channel chat, and
11
+ a **Meeting Controls** facilitator channel — all behind an injectable LiveKit room SDK seam so the driver
12
+ builds and unit-tests with **no network and no real LiveKit SDK**.
13
+
14
+ See the [Realtime Bridges Guide](../../../../guides/REALTIME_BRIDGES_GUIDE.md) and
15
+ [`/plans/realtime/realtime-bridges-architecture.md`](../../../../plans/realtime/realtime-bridges-architecture.md)
16
+ (§4c multi-party / MJ-native room, §3 provider abstraction, §4b channels) for the full architecture.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install @memberjunction/ai-bridge-livekit
22
+ ```
23
+
24
+ ## Self-hosted vs. connecting out
25
+
26
+ | | The other bridges (Zoom, Teams, Meet, Webex, Slack, Discord, Twilio…) | **LiveKit (this package)** |
27
+ |---|---|---|
28
+ | Who owns the room | a 3rd-party platform | **MJ — self-hosted SFU** |
29
+ | How you join | a join URL / number you were handed | a room URL + a **token MJ mints** |
30
+ | Bot admission | per-platform review/quirks | none — MJ controls the room |
31
+ | Use case | meet the customer where they already are | an MJ-native multi-party experience (e.g. embedded in Explorer) |
32
+
33
+ The same multi-party machinery (§4c) works either way: put **1+ agents into a shared room** and the room
34
+ itself is the shared media plane.
35
+
36
+ ## What it provides
37
+
38
+ - **`LiveKitBridge`** — `@RegisterClass(BaseRealtimeBridge, 'LiveKitBridge')`. The `MJ: AI Bridge
39
+ Providers` row with `DriverClass = 'LiveKitBridge'` resolves to this driver via the `ClassFactory`.
40
+ Implements the four `BaseRealtimeBridge` abstracts (`Connect` / `Disconnect` / `SendMedia` / `OnMedia`)
41
+ and the capability-gated virtuals LiveKit supports (`GetParticipants`, `OnParticipantChange`), plus
42
+ `GetMeetingControlsEventSource` for the facilitator channel and a `SendDataMessage` helper.
43
+ - **`ILiveKitRoomSdk`** — the **injectable seam** the driver depends on instead of the real SDK.
44
+ - **`LiveKitMeetingControlsEventSource`** — adapts the seam's roster / speaking / mute into the bridge's
45
+ `IBridgeMeetingControlsEventSource`, so the engine wires the Meeting Controls channel.
46
+
47
+ ## Capability coverage (the LiveKit seed row)
48
+
49
+ | Capability | Status |
50
+ |---|---|
51
+ | On-demand join | ✅ |
52
+ | Audio in / out | ✅ |
53
+ | Video in / out | ✅ (LiveKit does full A/V) |
54
+ | Screen in / out | ✅ (full screen share) |
55
+ | Speaker diarization (per-participant tracks → labels) | ✅ — **native**, the SFU delivers tracks per participant |
56
+ | Room-admin mute (Meeting Controls) | ✅ |
57
+ | Data-channel chat | ✅ |
58
+ | Scheduled / invite / native-invite join, DTMF / transfer / recording | ➖ not LiveKit-room features — the gated base methods throw `BridgeCapabilityNotSupportedError` |
59
+
60
+ Capability gating is two-layer (defense-in-depth): the engine checks the provider's `SupportedFeatures`
61
+ first, and the driver re-asserts each flag with `RequireFeature` at the top of its overrides.
62
+
63
+ ## The LiveKit room SDK seam (`ILiveKitRoomSdk`)
64
+
65
+ The driver never imports the real LiveKit SDK. It depends only on this minimal interface:
66
+
67
+ ```typescript
68
+ export interface ILiveKitRoomSdk {
69
+ connect(args: LiveKitConnectArgs): Promise<LiveKitConnectResult>; // roomUrl + signed token → join as bot
70
+ disconnect(): Promise<void>;
71
+ publishAudioFrame(pcm: ArrayBuffer): void; // agent's voice out
72
+ onAudioTrack(cb: (frame: LiveKitAudioFrame) => void): void; // per-participant audio in (diarization)
73
+ publishVideoFrame(frame: ArrayBuffer): void; // full video out
74
+ publishScreenFrame(frame: ArrayBuffer): void; // full screen share out
75
+ onParticipantJoin(cb: (p: LiveKitParticipant) => void): void;
76
+ onParticipantLeave(cb: (id: string) => void): void;
77
+ getParticipants(): Promise<LiveKitParticipant[]>;
78
+ sendDataMessage(text: string): Promise<void>; // data-channel chat
79
+ onDisconnected(cb: () => void): void;
80
+ }
81
+ ```
82
+
83
+ **Native binding:** this package ships **`LiveKitNativeMeetingSdk`** (`livekit-native-sdk.ts`) — the
84
+ two-way adapter over the LiveKit room client, activated with `bridge.SetSdkFactory(BindLiveKitNative())`
85
+ (auto-bound by the engine as the registered default for `DriverClass = 'LiveKitBridge'`). It's the MJ-side
86
+ adapter, unit-tested against a fake module; none of the SDK types leak into this package.
87
+
88
+ **The real room client now ships too:** [`@memberjunction/ai-bridge-livekit-native`](../LiveKitNative)
89
+ wraps `@livekit/rtc-node` behind this adapter's `NativeRoomModule` contract. The LiveKit coordinator points
90
+ `NativeModuleSpecifier` at it by default (overridable via the `LIVEKIT_NATIVE_MODULE` env), so a deployment
91
+ just needs to `npm install @livekit/rtc-node` on the agent host. Until a module is configured, `connect`
92
+ throws an explicit "load the native LiveKit module" error.
93
+
94
+ LiveKit is the recommended **internal proving ground** (pair with the `mj-livekit-room` Explorer tab or the
95
+ LiveKit Agents Playground) — see
96
+ [`plans/realtime/native-bridge-buildout-plan.md`](../../../../plans/realtime/native-bridge-buildout-plan.md) §6.
97
+
98
+ ## Echo / self-audio
99
+
100
+ A LiveKit SFU **never delivers a participant its own published track back** — the bot does not hear its
101
+ own voice, so no echo gate is needed. This is exactly the property the multi-party model relies on
102
+ (§4c): each agent in a room hears the *others'* mix natively, never itself, so two agents can converse
103
+ without a transcript-relay hack.
104
+
105
+ ## Usage
106
+
107
+ ```typescript
108
+ import { LiveKitBridge } from '@memberjunction/ai-bridge-livekit';
109
+ import { AIBridgeEngine } from '@memberjunction/ai-bridge-server';
110
+
111
+ // The engine resolves the driver by DriverClass via the ClassFactory; you do not new it up directly.
112
+ // In production, bind the real SDK factory once at boot:
113
+ // (resolved per provider config) — LiveKitBridge instances call SetSdkFactory with a real adapter.
114
+
115
+ const active = await AIBridgeEngine.Instance.StartBridgeSession({
116
+ AgentSessionID: sessionId,
117
+ Provider: liveKitProvider, // MJ: AI Bridge Providers row, DriverClass='LiveKitBridge'
118
+ RealtimeSession: realtimeSession, // injected IRealtimeSession
119
+ Address: 'wss://livekit.myorg.com', // the MJ-native room server
120
+ Configuration: { AccessToken: signedToken, BotDisplayName: 'Sage' },
121
+ MetadataProvider: provider,
122
+ ContextUser: user,
123
+ });
124
+ ```
125
+
126
+ For multiple agents in one LiveKit room, register each session with the engine's room coordinator — see
127
+ the [Multi-party section of the guide](../../../../guides/REALTIME_BRIDGES_GUIDE.md) and
128
+ `MultiAgentRoomCoordinator` in `@memberjunction/ai-bridge-server`.
129
+
130
+ ## Testing
131
+
132
+ `FakeLiveKitRoomSdk` (in the test file) implements `ILiveKitRoomSdk` in memory with drive helpers and
133
+ capture sinks — connect/disconnect, audio in→`OnMedia` (speaker labels) + out→track, video/screen out,
134
+ participant join/leave→roster, speaking attribution, data-channel chat, and capability gating. **24
135
+ tests, no network.** Run with `npm test`.
136
+
137
+ ## License
138
+
139
+ ISC
@@ -0,0 +1,6 @@
1
+ export * from './livekit-sdk.js';
2
+ export * from './livekit-native-sdk.js';
3
+ export * from './livekit-meeting-controls.js';
4
+ export * from './livekit-bridge.js';
5
+ export * from './register-native.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export * from './livekit-sdk.js';
2
+ export * from './livekit-native-sdk.js';
3
+ export * from './livekit-meeting-controls.js';
4
+ export * from './livekit-bridge.js';
5
+ export * from './register-native.js';
6
+ import { LoadLiveKitBridge } from './livekit-bridge.js';
7
+ import { RegisterLiveKitNativeSdk } from './register-native.js';
8
+ // Static reference so bundlers cannot tree-shake the @RegisterClass(BaseRealtimeBridge, 'LiveKitBridge')
9
+ // registration. Calling the no-op here keeps the driver resolvable by the engine's ClassFactory.
10
+ LoadLiveKitBridge();
11
+ // Register LiveKit's native two-way SDK binding so the engine auto-binds it at StartBridgeSession.
12
+ RegisterLiveKitNativeSdk();
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,yGAAyG;AACzG,iGAAiG;AACjG,iBAAiB,EAAE,CAAC;AACpB,mGAAmG;AACnG,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @fileoverview `LiveKitBridge` — the **MJ-native multi-party room** Realtime Bridge driver. Unlike
3
+ * every other bridge (which connects OUT to a 3rd-party meeting/telephony platform), LiveKit is a
4
+ * **self-hosted WebRTC SFU that MJ runs itself** — the "MJ-native room"
5
+ * (`/plans/realtime/realtime-bridges-architecture.md` §4c). The architecture treats a Zoom meeting and
6
+ * an MJ-native LiveKit room **identically** — both are multi-party media transports — so this is
7
+ * "*another bridge, not a special build*."
8
+ *
9
+ * Implements the {@link BaseRealtimeBridge} contract against an injectable {@link ILiveKitRoomSdk} seam
10
+ * so it builds + unit-tests with NO network and NO real LiveKit SDK (the Zoom `SetSdkFactory`
11
+ * testability pattern).
12
+ *
13
+ * LiveKit capability coverage (per the §4c / §8 seed row): on-demand join, **full** audio/video/screen
14
+ * in+out (LiveKit does the lot), and per-participant diarization (`SpeakerDiarization`) — the SFU
15
+ * delivers tracks per participant, so speaker labels come free. No scheduled/invite/telephony features.
16
+ * Those virtual base methods keep throwing `BridgeCapabilityNotSupportedError`.
17
+ *
18
+ * ## Echo / self-audio
19
+ * A LiveKit SFU **never delivers a participant its own published track back**, so the bot does not hear
20
+ * its own voice — no echo gate is required (see {@link wireInboundAudio}). This is exactly the property
21
+ * §4c relies on for putting **multiple agents in one room**: each agent hears the *others'* mixed audio
22
+ * natively, not its own, so two agents converse without a transcript-relay hack.
23
+ *
24
+ * @module @memberjunction/ai-bridge-livekit
25
+ * @author MemberJunction.com
26
+ */
27
+ import { BaseRealtimeBridge, BridgeConnectResult, BridgeDisconnectReason, BridgeMediaFrame, BridgeMediaTrackKind, BridgeParticipantInfo, RealtimeBridgeContext, IBridgeMeetingControlsEventSource } from '@memberjunction/ai-bridge-base';
28
+ import { LiveKitRoomSdkFactory } from './livekit-sdk.js';
29
+ /**
30
+ * The `DriverClass` key {@link LiveKitBridge} registers under. A `MJ: AI Bridge Providers` row with
31
+ * `DriverClass = 'LiveKitBridge'` resolves to this driver via the `ClassFactory`.
32
+ */
33
+ export declare const LIVEKIT_BRIDGE_DRIVER_CLASS = "LiveKitBridge";
34
+ /**
35
+ * Realtime Bridge driver for the **MJ-native LiveKit room**.
36
+ *
37
+ * Construct the driver with the default constructor (the engine's `ClassFactory` path) — it lazily
38
+ * builds the LiveKit room SDK from the {@link sdkFactory} at {@link Connect} time. Tests inject a
39
+ * `FakeLiveKitRoomSdk` by overriding the factory via {@link SetSdkFactory} (the creation seam) before
40
+ * connecting.
41
+ *
42
+ * Registered via `@RegisterClass(BaseRealtimeBridge, 'LiveKitBridge')`.
43
+ */
44
+ export declare class LiveKitBridge extends BaseRealtimeBridge {
45
+ /** The live LiveKit SDK seam for this session, created at {@link Connect}. */
46
+ private sdk;
47
+ /** The bot's own participant identity in the joined room (set at {@link Connect}). */
48
+ private botIdentity;
49
+ /** The inbound-media handler registered via {@link OnMedia}; raw audio frames are forwarded to it. */
50
+ private mediaHandler?;
51
+ /** The roster-change handler registered via {@link OnParticipantChange}. */
52
+ private participantHandler?;
53
+ /** The Meeting Controls event source for this session (only when diarization is supported). */
54
+ private meetingControls;
55
+ /**
56
+ * The SDK creation seam. Defaults to a factory that throws an explicit "bind the real LiveKit SDK"
57
+ * error, since this package ships WITHOUT the real SDK adapter (a deployment concern). Production
58
+ * sets a real factory via {@link SetSdkFactory}; tests inject a `FakeLiveKitRoomSdk`.
59
+ */
60
+ private sdkFactory;
61
+ /**
62
+ * Sets the {@link LiveKitRoomSdkFactory} this driver uses to construct its SDK seam at connect — the
63
+ * creation seam (mirroring Zoom's `SetSdkFactory`). Production binds the real LiveKit room SDK
64
+ * adapter here; tests inject a `FakeLiveKitRoomSdk`.
65
+ *
66
+ * @param factory The factory that builds the {@link ILiveKitRoomSdk} for a session.
67
+ */
68
+ SetSdkFactory(factory: LiveKitRoomSdkFactory): void;
69
+ /**
70
+ * Connects to the MJ-native LiveKit room and brings the bot online. Captures the capability context,
71
+ * builds the SDK from the {@link sdkFactory}, wires the inbound per-participant audio path and
72
+ * room-disconnected callback, connects, and (when the provider diarizes) constructs + seeds the
73
+ * Meeting Controls event source.
74
+ *
75
+ * @param ctx The bridge context (features, provider name, the room URL as `Address`, config carrying
76
+ * the signed access token).
77
+ * @returns The bot identity + room (external connection) identifiers, persisted by the engine.
78
+ */
79
+ Connect(ctx: RealtimeBridgeContext): Promise<BridgeConnectResult>;
80
+ /**
81
+ * Disconnects from the LiveKit room and releases all SDK resources. Tolerant of teardown errors.
82
+ *
83
+ * @param _reason Why the disconnect happened (LiveKit teardown is uniform; the bot simply leaves).
84
+ */
85
+ Disconnect(_reason: BridgeDisconnectReason): Promise<void>;
86
+ /**
87
+ * Sends an outbound media frame into the room. LiveKit does the FULL media set, so audio, video, and
88
+ * screen are all published on their respective tracks (gated by the directional capability flags —
89
+ * the realtime models light audio first, video/screen ride the same path once a model emits them).
90
+ *
91
+ * @param track The outbound track the frame targets.
92
+ * @param frame The media frame to send.
93
+ */
94
+ /** Flushes the agent's queued outbound voice on barge-in (the user interrupted the agent). */
95
+ FlushOutboundMedia(): void;
96
+ SendMedia(track: BridgeMediaTrackKind, frame: BridgeMediaFrame): void;
97
+ /**
98
+ * Registers the inbound-media handler. The driver forwards each raw per-participant audio frame
99
+ * (with its speaker identity) to this handler; the engine routes it to `IRealtimeSession.SendInput`.
100
+ *
101
+ * @param handler Invoked with each inbound media frame.
102
+ */
103
+ OnMedia(handler: (frame: BridgeMediaFrame) => void): void;
104
+ /**
105
+ * Returns the current LiveKit participant roster (gated by `SpeakerDiarization`). Re-asserts the
106
+ * flag (defense-in-depth) so even an engine-bypassing caller cannot pull a roster a disabled
107
+ * provider forbids.
108
+ *
109
+ * @returns The current participants.
110
+ * @throws {BridgeCapabilityNotSupportedError} when diarization is not enabled for the provider.
111
+ */
112
+ GetParticipants(): Promise<BridgeParticipantInfo[]>;
113
+ /**
114
+ * Registers a roster-change handler (gated by `SpeakerDiarization`). The driver fires it from the
115
+ * SDK's participant join/leave stream with the full current roster.
116
+ *
117
+ * @param handler Invoked with the updated participant list on each change.
118
+ * @throws {BridgeCapabilityNotSupportedError} when diarization is not enabled.
119
+ */
120
+ OnParticipantChange(handler: (participants: BridgeParticipantInfo[]) => void): void;
121
+ /**
122
+ * Returns the LiveKit Meeting Controls event source for this session (roster · speaking · mute), or
123
+ * `null` when diarization is off (no roster to facilitate). The engine wires the Meeting Controls
124
+ * channel from this.
125
+ */
126
+ GetMeetingControlsEventSource(): IBridgeMeetingControlsEventSource | null;
127
+ /**
128
+ * Sends a message on the LiveKit data channel — the room-native "chat". Exposed for the channel
129
+ * plane / turn-taking hybrid mode (the social-cost-free "raise hand"). Best-effort — a failure is
130
+ * logged, never fatal.
131
+ *
132
+ * @param text The data/chat message to send.
133
+ */
134
+ SendDataMessage(text: string): Promise<void>;
135
+ /** The bot's participant identity in the joined room (or `null` before {@link Connect}). */
136
+ get BotIdentity(): string | null;
137
+ /**
138
+ * Wires the SDK's inbound per-participant audio callback to a diarized inbound
139
+ * {@link BridgeMediaFrame}. The SFU never echoes the bot's own audio, so no self-audio gate is
140
+ * needed; the frame's `SpeakerLabel` is the source participant identity.
141
+ */
142
+ private wireInboundAudio;
143
+ /**
144
+ * Wires the SDK's participant join/leave streams ONCE (the driver is the single owner; the SDK seam
145
+ * is latest-handler-wins). Each roster change fans out to both the driver's own roster-change
146
+ * handler and the Meeting Controls source.
147
+ */
148
+ private wireRoster;
149
+ /** Pulls the current roster from the SDK and fans it out to both the participant handler + Meeting Controls. */
150
+ private refreshRoster;
151
+ /** Handles the SDK's room-disconnected signal: surface an empty roster so the engine sees everyone gone. */
152
+ private handleRoomDisconnected;
153
+ /** Builds the SDK connect args from the bridge context (Address is the room URL; token from config). */
154
+ private buildConnectArgs;
155
+ /** Returns the bytes of an outbound media frame, preferring the binary payload. */
156
+ private framePcm;
157
+ /** Decodes a base64 payload to an `ArrayBuffer` (Node `Buffer` fast path, `atob` fallback). */
158
+ private decodeBase64;
159
+ }
160
+ /**
161
+ * Tree-shaking-prevention loader. Modern bundlers cannot see the `@RegisterClass` dynamic registration
162
+ * of {@link LiveKitBridge} and may eliminate it. Import and call this no-op from a static code path
163
+ * (the package entry point does) so the `ClassFactory` can resolve `'LiveKitBridge'`.
164
+ */
165
+ export declare function LoadLiveKitBridge(): void;
166
+ //# sourceMappingURL=livekit-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-bridge.d.ts","sourceRoot":"","sources":["../src/livekit-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EAErB,qBAAqB,EACrB,iCAAiC,EACpC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEH,qBAAqB,EAKxB,MAAM,eAAe,CAAC;AAGvB;;;GAGG;AACH,eAAO,MAAM,2BAA2B,kBAAkB,CAAC;AA0C3D;;;;;;;;;GASG;AACH,qBACa,aAAc,SAAQ,kBAAkB;IACjD,8EAA8E;IAC9E,OAAO,CAAC,GAAG,CAAgC;IAE3C,sFAAsF;IACtF,OAAO,CAAC,WAAW,CAAuB;IAE1C,sGAAsG;IACtG,OAAO,CAAC,YAAY,CAAC,CAAoC;IAEzD,4EAA4E;IAC5E,OAAO,CAAC,kBAAkB,CAAC,CAAkD;IAE7E,+FAA+F;IAC/F,OAAO,CAAC,eAAe,CAAkD;IAEzE;;;;OAIG;IACH,OAAO,CAAC,UAAU,CAKhB;IAEF;;;;;;OAMG;IACI,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAM1D;;;;;;;;;OASG;IACU,OAAO,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA2B9E;;;;OAIG;IACU,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvE;;;;;;;OAOG;IACH,8FAA8F;IAC9E,kBAAkB,IAAI,IAAI;IAInC,SAAS,CAAC,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IA4B5E;;;;;OAKG;IACI,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAMhE;;;;;;;OAOG;IACmB,eAAe,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IASzE;;;;;;OAMG;IACa,mBAAmB,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,qBAAqB,EAAE,KAAK,IAAI,GAAG,IAAI;IAKnG;;;;OAIG;IACa,6BAA6B,IAAI,iCAAiC,GAAG,IAAI;IAMzF;;;;;;OAMG;IACU,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzD,4FAA4F;IAC5F,IAAW,WAAW,IAAI,MAAM,GAAG,IAAI,CAEtC;IAID;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAKlB,gHAAgH;YAClG,aAAa;IAU3B,4GAA4G;IAC5G,OAAO,CAAC,sBAAsB;IAK9B,wGAAwG;IACxG,OAAO,CAAC,gBAAgB;IASxB,mFAAmF;IACnF,OAAO,CAAC,QAAQ;IAUhB,+FAA+F;IAC/F,OAAO,CAAC,YAAY;CAcvB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}