@soulcraft/sdk 1.1.0 → 1.2.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/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/auth/service-token.d.ts +62 -0
- package/dist/modules/auth/service-token.d.ts.map +1 -0
- package/dist/modules/auth/service-token.js +99 -0
- package/dist/modules/auth/service-token.js.map +1 -0
- package/dist/modules/billing/index.d.ts +17 -5
- package/dist/modules/billing/index.d.ts.map +1 -1
- package/dist/modules/billing/index.js +24 -9
- package/dist/modules/billing/index.js.map +1 -1
- package/dist/modules/billing/portal-provider.d.ts +70 -0
- package/dist/modules/billing/portal-provider.d.ts.map +1 -0
- package/dist/modules/billing/portal-provider.js +204 -0
- package/dist/modules/billing/portal-provider.js.map +1 -0
- package/dist/modules/billing/types.d.ts +4 -3
- package/dist/modules/billing/types.d.ts.map +1 -1
- package/dist/modules/billing/types.js +4 -3
- package/dist/modules/billing/types.js.map +1 -1
- package/dist/modules/hall/browser.d.ts +88 -0
- package/dist/modules/hall/browser.d.ts.map +1 -0
- package/dist/modules/hall/browser.js +265 -0
- package/dist/modules/hall/browser.js.map +1 -0
- package/dist/modules/hall/protocol.d.ts +39 -0
- package/dist/modules/hall/protocol.d.ts.map +1 -0
- package/dist/modules/hall/protocol.js +52 -0
- package/dist/modules/hall/protocol.js.map +1 -0
- package/dist/modules/hall/server.d.ts +172 -0
- package/dist/modules/hall/server.d.ts.map +1 -0
- package/dist/modules/hall/server.js +457 -0
- package/dist/modules/hall/server.js.map +1 -0
- package/dist/modules/hall/types.d.ts +502 -31
- package/dist/modules/hall/types.d.ts.map +1 -1
- package/dist/modules/hall/types.js +13 -8
- package/dist/modules/hall/types.js.map +1 -1
- package/dist/server/hall-handlers.d.ts +90 -151
- package/dist/server/hall-handlers.d.ts.map +1 -1
- package/dist/server/hall-handlers.js +84 -204
- package/dist/server/hall-handlers.js.map +1 -1
- package/dist/server/index.d.ts +4 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -2
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +22 -18
- package/dist/types.d.ts.map +1 -1
- package/docs/USAGE.md +224 -1
- package/package.json +1 -6
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/protocol
|
|
3
|
+
* @description MessagePack encode/decode for Hall WebSocket frames.
|
|
4
|
+
*
|
|
5
|
+
* All Hall WebSocket frames are binary msgpack. The Rust server uses serde's
|
|
6
|
+
* `tag/content` encoding: `{ t: "messageType", d: { ...fields } }`.
|
|
7
|
+
*
|
|
8
|
+
* This module provides typed encode/decode functions that match the Rust
|
|
9
|
+
* protocol exactly. Runtime validation catches protocol drift early.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const bytes = encodeHallMessage({ t: 'createRoom', d: { roomId: 'abc', options: {} } })
|
|
14
|
+
* socket.send(bytes)
|
|
15
|
+
*
|
|
16
|
+
* socket.onmessage = (ev) => {
|
|
17
|
+
* const msg = decodeHallMessage(ev.data)
|
|
18
|
+
* if (msg.t === 'roomCreated') console.log(msg.d.sessionId)
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { HallClientMessage, HallServerMessage } from './types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Encode a {@link HallClientMessage} to msgpack bytes for transmission over WebSocket.
|
|
25
|
+
*
|
|
26
|
+
* @param msg - The typed client message to encode.
|
|
27
|
+
* @returns Binary msgpack payload ready to send via `WebSocket.send()`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function encodeHallMessage(msg: HallClientMessage): Uint8Array;
|
|
30
|
+
/**
|
|
31
|
+
* Decode a msgpack binary frame received from the Hall server.
|
|
32
|
+
*
|
|
33
|
+
* @param data - Raw bytes from a WebSocket binary message (`ev.data`).
|
|
34
|
+
* @returns The decoded {@link HallServerMessage}.
|
|
35
|
+
* @throws {Error} If the bytes are not valid msgpack or the decoded value is
|
|
36
|
+
* not a recognised server message object (missing `t` field).
|
|
37
|
+
*/
|
|
38
|
+
export declare function decodeHallMessage(data: ArrayBuffer | Uint8Array): HallServerMessage;
|
|
39
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/modules/hall/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEtE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,GAAG,UAAU,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,iBAAiB,CAiBnF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/protocol
|
|
3
|
+
* @description MessagePack encode/decode for Hall WebSocket frames.
|
|
4
|
+
*
|
|
5
|
+
* All Hall WebSocket frames are binary msgpack. The Rust server uses serde's
|
|
6
|
+
* `tag/content` encoding: `{ t: "messageType", d: { ...fields } }`.
|
|
7
|
+
*
|
|
8
|
+
* This module provides typed encode/decode functions that match the Rust
|
|
9
|
+
* protocol exactly. Runtime validation catches protocol drift early.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const bytes = encodeHallMessage({ t: 'createRoom', d: { roomId: 'abc', options: {} } })
|
|
14
|
+
* socket.send(bytes)
|
|
15
|
+
*
|
|
16
|
+
* socket.onmessage = (ev) => {
|
|
17
|
+
* const msg = decodeHallMessage(ev.data)
|
|
18
|
+
* if (msg.t === 'roomCreated') console.log(msg.d.sessionId)
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { encode, decode } from '@msgpack/msgpack';
|
|
23
|
+
/**
|
|
24
|
+
* Encode a {@link HallClientMessage} to msgpack bytes for transmission over WebSocket.
|
|
25
|
+
*
|
|
26
|
+
* @param msg - The typed client message to encode.
|
|
27
|
+
* @returns Binary msgpack payload ready to send via `WebSocket.send()`.
|
|
28
|
+
*/
|
|
29
|
+
export function encodeHallMessage(msg) {
|
|
30
|
+
return encode(msg);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Decode a msgpack binary frame received from the Hall server.
|
|
34
|
+
*
|
|
35
|
+
* @param data - Raw bytes from a WebSocket binary message (`ev.data`).
|
|
36
|
+
* @returns The decoded {@link HallServerMessage}.
|
|
37
|
+
* @throws {Error} If the bytes are not valid msgpack or the decoded value is
|
|
38
|
+
* not a recognised server message object (missing `t` field).
|
|
39
|
+
*/
|
|
40
|
+
export function decodeHallMessage(data) {
|
|
41
|
+
const raw = decode(data instanceof ArrayBuffer ? new Uint8Array(data) : data);
|
|
42
|
+
if (typeof raw !== 'object' ||
|
|
43
|
+
raw === null ||
|
|
44
|
+
!('t' in raw) ||
|
|
45
|
+
typeof raw.t !== 'string') {
|
|
46
|
+
throw new Error(`Invalid Hall message: expected object with string "t" field, got ${JSON.stringify(raw)}`);
|
|
47
|
+
}
|
|
48
|
+
// Trust the server to send well-formed messages — full schema validation
|
|
49
|
+
// would duplicate the Rust type definitions and add runtime cost.
|
|
50
|
+
return raw;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/modules/hall/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAGjD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAsB;IACtD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA8B;IAC9D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAE7E,IACE,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACZ,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QACb,OAAQ,GAA+B,CAAC,CAAC,KAAK,QAAQ,EACtD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,oEAAoE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAC1F,CAAA;IACH,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,OAAO,GAAwB,CAAA;AACjC,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/server
|
|
3
|
+
* @description Server-side Hall client — product backend to Hall server control plane.
|
|
4
|
+
*
|
|
5
|
+
* `HallClient` maintains a single authenticated WebSocket connection from the product
|
|
6
|
+
* backend to `hall.soulcraft.com`. All room management (createRoom, closeRoom, session
|
|
7
|
+
* tokens, recording) goes through this connection.
|
|
8
|
+
*
|
|
9
|
+
* This module is **server-only** — it uses WebSocket, reconnect timers, and the
|
|
10
|
+
* product shared secret, none of which should ever reach a browser bundle.
|
|
11
|
+
*
|
|
12
|
+
* Use `createHallModule(options)` from `@soulcraft/sdk/server` to get a fully wired
|
|
13
|
+
* `HallModule` instance. Direct use of `HallClient` is for advanced scenarios.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { createHallModule } from '@soulcraft/sdk/server'
|
|
18
|
+
*
|
|
19
|
+
* const hall = createHallModule({
|
|
20
|
+
* url: process.env.HALL_URL!,
|
|
21
|
+
* productName: 'academy',
|
|
22
|
+
* secret: process.env.HALL_ACADEMY_SECRET!,
|
|
23
|
+
* })
|
|
24
|
+
* await hall.connect()
|
|
25
|
+
* const room = await hall.createRoom('cohort-123', { enableTranscription: true })
|
|
26
|
+
* room.on('transcript', (t) => console.log(t.text))
|
|
27
|
+
* const { token } = await hall.createSessionToken('cohort-123', 'user-456')
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import type { HallConnectionOptions, HallModule, HallRoom, HallRoomEvents, RoomOptions } from './types.js';
|
|
31
|
+
type Listener<T> = (event: T) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Concrete implementation of the {@link HallRoom} interface.
|
|
34
|
+
*
|
|
35
|
+
* Stores per-event listener sets and provides a typed dispatch method called
|
|
36
|
+
* internally by `HallClient` when the server pushes room events.
|
|
37
|
+
*/
|
|
38
|
+
export declare class HallRoomImpl implements HallRoom {
|
|
39
|
+
#private;
|
|
40
|
+
readonly roomId: string;
|
|
41
|
+
readonly sessionId: string;
|
|
42
|
+
constructor(roomId: string, sessionId: string);
|
|
43
|
+
on<K extends keyof HallRoomEvents>(event: K, listener: Listener<HallRoomEvents[K]>): this;
|
|
44
|
+
off<K extends keyof HallRoomEvents>(event: K, listener: Listener<HallRoomEvents[K]>): this;
|
|
45
|
+
/** @internal Dispatches an incoming server event to all registered listeners. */
|
|
46
|
+
_dispatch<K extends keyof HallRoomEvents>(event: K, payload: HallRoomEvents[K]): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Product-backend WebSocket client for the Hall real-time communication server.
|
|
50
|
+
*
|
|
51
|
+
* Create one instance per product process. Maintains a single authenticated control-plane
|
|
52
|
+
* WebSocket to `hall.soulcraft.com`. All room management and event routing goes through
|
|
53
|
+
* this single connection — do not create multiple instances per product.
|
|
54
|
+
*
|
|
55
|
+
* Auto-reconnects on unexpected disconnect (configurable via `reconnectDelayMs`).
|
|
56
|
+
* In-flight promises are rejected on disconnect; register `onReconnect` to re-create rooms.
|
|
57
|
+
*/
|
|
58
|
+
export declare class HallClient implements HallModule {
|
|
59
|
+
#private;
|
|
60
|
+
readonly url: string;
|
|
61
|
+
/**
|
|
62
|
+
* @param options - Connection options: url, productName, secret, and optional reconnectDelayMs.
|
|
63
|
+
*/
|
|
64
|
+
constructor(options: HallConnectionOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Connect to the Hall server and authenticate with the product shared secret.
|
|
67
|
+
* Must be called once at startup before any other method.
|
|
68
|
+
*
|
|
69
|
+
* @returns Resolves when `authOk` is received from the server.
|
|
70
|
+
* @throws {Error} If auth fails or the WebSocket cannot connect.
|
|
71
|
+
*/
|
|
72
|
+
connect(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Gracefully close all active rooms and disconnect from the Hall server.
|
|
75
|
+
* After calling this, the instance cannot be reconnected.
|
|
76
|
+
*/
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Register a listener for unexpected disconnects (not triggered by `close()`).
|
|
80
|
+
* Use this to log the event and prepare to re-create rooms after reconnect.
|
|
81
|
+
*
|
|
82
|
+
* @param listener - Called with a human-readable reason string (e.g. `"code 1006"`).
|
|
83
|
+
*/
|
|
84
|
+
onDisconnect(listener: (reason: string) => void): void;
|
|
85
|
+
/**
|
|
86
|
+
* Register a listener for successful reconnections.
|
|
87
|
+
* On reconnect, rooms from before the disconnect are gone — re-create them here.
|
|
88
|
+
*
|
|
89
|
+
* @param listener - Called with no arguments when the reconnect auth succeeds.
|
|
90
|
+
*/
|
|
91
|
+
onReconnect(listener: () => void): void;
|
|
92
|
+
/**
|
|
93
|
+
* Create a new room on the Hall server.
|
|
94
|
+
*
|
|
95
|
+
* @param roomId - Unique room identifier (e.g. Brainy session entity ID).
|
|
96
|
+
* @param options - Room configuration: peer limit, transcription, recording, concept list.
|
|
97
|
+
* @returns The HallRoom handle — register event listeners on it immediately.
|
|
98
|
+
* @throws {Error} If a room with the same ID already exists or the server returns an error.
|
|
99
|
+
*/
|
|
100
|
+
createRoom(roomId: string, options?: RoomOptions): Promise<HallRoomImpl>;
|
|
101
|
+
/**
|
|
102
|
+
* Close a room and disconnect all its peers.
|
|
103
|
+
*
|
|
104
|
+
* @param roomId - The room ID passed to `createRoom`.
|
|
105
|
+
* @throws {Error} If the server returns an error.
|
|
106
|
+
*/
|
|
107
|
+
closeRoom(roomId: string): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Return the IDs of all active rooms managed by this connection.
|
|
110
|
+
*
|
|
111
|
+
* @returns Array of room ID strings currently active on the server.
|
|
112
|
+
*/
|
|
113
|
+
listRooms(): Promise<string[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Return an active room handle by ID, or `undefined` if not found.
|
|
116
|
+
*
|
|
117
|
+
* @param roomId - The room ID passed to `createRoom`.
|
|
118
|
+
*/
|
|
119
|
+
getRoom(roomId: string): HallRoomImpl | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Mint a short-lived HMAC session token for a browser peer.
|
|
122
|
+
* Pass `{ token, hallUrl }` to the browser — **never** the product secret.
|
|
123
|
+
*
|
|
124
|
+
* @param roomId - The room the browser peer will join.
|
|
125
|
+
* @param peerId - The peer's unique identifier (e.g. authenticated user ID).
|
|
126
|
+
* @param ttlSecs - Token lifetime in seconds (default: 300).
|
|
127
|
+
* @returns `{ token, expiresAt }` — send `token` and `this.url` to the browser.
|
|
128
|
+
*/
|
|
129
|
+
createSessionToken(roomId: string, peerId: string, ttlSecs?: number): Promise<{
|
|
130
|
+
token: string;
|
|
131
|
+
expiresAt: number;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Start per-track MKV recording for an active room.
|
|
135
|
+
* The room emits `recordingManifest` when `stopRecording` is called.
|
|
136
|
+
*
|
|
137
|
+
* @param roomId - The room to start recording.
|
|
138
|
+
*/
|
|
139
|
+
startRecording(roomId: string): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Stop recording for a room. Hall writes track files and emits `recordingManifest`
|
|
142
|
+
* on the room handle with absolute paths to the recorded MKV files.
|
|
143
|
+
*
|
|
144
|
+
* @param roomId - The room to stop recording.
|
|
145
|
+
*/
|
|
146
|
+
stopRecording(roomId: string): Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a server-mode Hall module that connects to the Hall standalone server.
|
|
150
|
+
*
|
|
151
|
+
* Returns a `HallModule` backed by a `HallClient`. Call `connect()` once at startup.
|
|
152
|
+
* In typical server mode SDK usage, `createSDK` calls this automatically when
|
|
153
|
+
* `hall` options are provided in `ServerSDKOptions`.
|
|
154
|
+
*
|
|
155
|
+
* @param options - Connection options: url, productName, secret, reconnectDelayMs.
|
|
156
|
+
* @returns A `HallModule` instance (not yet connected — call `module.connect()`).
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* import { createHallModule } from '@soulcraft/sdk/server'
|
|
161
|
+
*
|
|
162
|
+
* const hall = createHallModule({
|
|
163
|
+
* url: process.env.HALL_URL!,
|
|
164
|
+
* productName: 'academy',
|
|
165
|
+
* secret: process.env.HALL_ACADEMY_SECRET!,
|
|
166
|
+
* })
|
|
167
|
+
* await hall.connect()
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare function createHallModule(options: HallConnectionOptions): HallModule;
|
|
171
|
+
export {};
|
|
172
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/modules/hall/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EACV,qBAAqB,EACrB,UAAU,EACV,QAAQ,EACR,cAAc,EAEd,WAAW,EAQZ,MAAM,YAAY,CAAA;AAInB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;AAGrC;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,QAAQ;;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBAad,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAK7C,EAAE,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAKzF,GAAG,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAK1F,iFAAiF;IACjF,SAAS,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;CAStF;AAWD;;;;;;;;;GASG;AACH,qBAAa,UAAW,YAAW,UAAU;;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IAwBpB;;OAEG;gBACS,OAAO,EAAE,qBAAqB;IAS1C;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAItD;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAMvC;;;;;;;OAOG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ5E;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC;;;;OAIG;IACH,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ9B;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIjD;;;;;;;;OAQG;IACH,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAShD;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAyN7C;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAE3E"}
|