@fleettools/squawk 0.1.0 → 0.1.1

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 (66) hide show
  1. package/package.json +1 -1
  2. package/AGENTS.md +0 -28
  3. package/dist/src/db/checkpoint-storage.d.ts +0 -19
  4. package/dist/src/db/checkpoint-storage.d.ts.map +0 -1
  5. package/dist/src/db/checkpoint-storage.js +0 -355
  6. package/dist/src/db/checkpoint-storage.js.map +0 -1
  7. package/dist/src/db/index.d.ts +0 -30
  8. package/dist/src/db/index.d.ts.map +0 -1
  9. package/dist/src/db/index.js +0 -329
  10. package/dist/src/db/index.js.map +0 -1
  11. package/dist/src/db/sqlite.d.ts +0 -31
  12. package/dist/src/db/sqlite.d.ts.map +0 -1
  13. package/dist/src/db/sqlite.js +0 -558
  14. package/dist/src/db/sqlite.js.map +0 -1
  15. package/dist/src/db/types.d.ts +0 -611
  16. package/dist/src/db/types.d.ts.map +0 -1
  17. package/dist/src/db/types.js +0 -4
  18. package/dist/src/db/types.js.map +0 -1
  19. package/dist/src/index.d.ts +0 -2
  20. package/dist/src/index.d.ts.map +0 -1
  21. package/dist/src/index.js +0 -285
  22. package/dist/src/index.js.map +0 -1
  23. package/dist/src/recovery/checkpointing.d.ts +0 -244
  24. package/dist/src/recovery/checkpointing.d.ts.map +0 -1
  25. package/dist/src/recovery/checkpointing.js +0 -511
  26. package/dist/src/recovery/checkpointing.js.map +0 -1
  27. package/dist/src/recovery/detection.d.ts +0 -137
  28. package/dist/src/recovery/detection.d.ts.map +0 -1
  29. package/dist/src/recovery/detection.js +0 -240
  30. package/dist/src/recovery/detection.js.map +0 -1
  31. package/dist/src/recovery/detector.d.ts +0 -34
  32. package/dist/src/recovery/detector.d.ts.map +0 -1
  33. package/dist/src/recovery/detector.js +0 -42
  34. package/dist/src/recovery/detector.js.map +0 -1
  35. package/dist/src/recovery/index.d.ts +0 -3
  36. package/dist/src/recovery/index.d.ts.map +0 -1
  37. package/dist/src/recovery/index.js +0 -3
  38. package/dist/src/recovery/index.js.map +0 -1
  39. package/dist/src/recovery/restorer.d.ts +0 -51
  40. package/dist/src/recovery/restorer.d.ts.map +0 -1
  41. package/dist/src/recovery/restorer.js +0 -266
  42. package/dist/src/recovery/restorer.js.map +0 -1
  43. package/dist/src/schemas.d.ts +0 -142
  44. package/dist/src/schemas.d.ts.map +0 -1
  45. package/dist/src/schemas.js +0 -110
  46. package/dist/src/schemas.js.map +0 -1
  47. package/src/db/checkpoint-storage.ts +0 -443
  48. package/src/db/index.d.ts +0 -30
  49. package/src/db/index.d.ts.map +0 -1
  50. package/src/db/index.js.map +0 -1
  51. package/src/db/index.ts +0 -417
  52. package/src/db/schema.sql +0 -112
  53. package/src/db/sqlite.d.ts +0 -31
  54. package/src/db/sqlite.d.ts.map +0 -1
  55. package/src/db/sqlite.js +0 -667
  56. package/src/db/sqlite.js.map +0 -1
  57. package/src/db/sqlite.ts +0 -677
  58. package/src/db/types.d.ts +0 -612
  59. package/src/db/types.d.ts.map +0 -1
  60. package/src/db/types.js +0 -4
  61. package/src/db/types.js.map +0 -1
  62. package/src/db/types.ts +0 -771
  63. package/src/index.ts +0 -332
  64. package/src/recovery/detector.ts +0 -82
  65. package/src/recovery/index.ts +0 -3
  66. package/src/recovery/restorer.ts +0 -377
package/src/db/index.ts DELETED
@@ -1,417 +0,0 @@
1
-
2
- import path from 'path';
3
- import fs from 'fs';
4
- import { randomUUID } from 'crypto';
5
- import { SQLiteAdapter } from './sqlite.js';
6
- import type { Event, Mailbox, Cursor, Lock } from './types.js';
7
-
8
- // CONFIGURATION
9
-
10
- function getLegacyDbPath(): string {
11
- return path.join(
12
- process.env.HOME || '',
13
- '.local',
14
- 'share',
15
- 'fleet',
16
- 'squawk.json'
17
- );
18
- }
19
-
20
- function getSqliteDbPath(): string {
21
- return path.join(
22
- process.env.HOME || '',
23
- '.local',
24
- 'share',
25
- 'fleet',
26
- 'squawk.db'
27
- );
28
- }
29
-
30
- // PRIVATE STATE
31
-
32
- let adapter: SQLiteAdapter | null = null;
33
-
34
- // INITIALIZATION
35
-
36
- export async function initializeDatabase(dbPath?: string): Promise<void> {
37
- const targetPath = dbPath || getSqliteDbPath();
38
-
39
- const dbDir = path.dirname(targetPath);
40
- if (!fs.existsSync(dbDir)) {
41
- fs.mkdirSync(dbDir, { recursive: true });
42
- }
43
-
44
- const schemaPath = path.join(process.cwd(), 'squawk', 'src', 'db', 'schema.sql');
45
- adapter = new SQLiteAdapter(targetPath, schemaPath);
46
- await adapter.initialize();
47
-
48
- const legacyDbPath = getLegacyDbPath();
49
- if (fs.existsSync(legacyDbPath)) {
50
- await migrateFromJson(legacyDbPath);
51
- const backupPath = legacyDbPath + '.backup';
52
- fs.renameSync(legacyDbPath, backupPath);
53
- console.log(`[Migration] Legacy data migrated to SQLite`);
54
- console.log(`[Migration] Backup saved to: ${backupPath}`);
55
- }
56
- }
57
-
58
- export function getAdapter(): SQLiteAdapter {
59
- if (!adapter) {
60
- throw new Error(
61
- 'Database not initialized. Call initializeDatabase() first.'
62
- );
63
- }
64
- return adapter;
65
- }
66
-
67
- export async function closeDatabase(): Promise<void> {
68
- if (adapter) {
69
- await adapter.close();
70
- adapter = null;
71
- }
72
- }
73
-
74
- // JSON MIGRATION
75
-
76
- interface LegacyJsonData {
77
- mailboxes: Record<string, any>;
78
- events: Record<string, any[]>;
79
- cursors: Record<string, any>;
80
- locks: Record<string, any>;
81
- }
82
-
83
- async function migrateFromJson(jsonPath: string): Promise<void> {
84
- console.log(`[Migration] Starting migration from: ${jsonPath}`);
85
-
86
- try {
87
- const content = fs.readFileSync(jsonPath, 'utf-8');
88
- const legacyData: LegacyJsonData = JSON.parse(content);
89
-
90
- const stats = {
91
- mailboxes: 0,
92
- events: 0,
93
- cursors: 0,
94
- locks: 0,
95
- };
96
-
97
- for (const [id, mailbox] of Object.entries(legacyData.mailboxes || {})) {
98
- try {
99
- if (!mailbox.created_at || !mailbox.updated_at) {
100
- console.warn(`[Migration] Skipping mailbox ${id} due to missing required fields`);
101
- continue;
102
- }
103
-
104
- await (adapter as any).mailboxes.create({
105
- id,
106
- created_at: mailbox.created_at,
107
- updated_at: mailbox.updated_at,
108
- });
109
- stats.mailboxes++;
110
- } catch (error) {
111
- console.warn(`[Migration] Failed to migrate mailbox ${id}:`, error);
112
- }
113
- }
114
-
115
- for (const [mailboxId, events] of Object.entries(
116
- legacyData.events || {}
117
- )) {
118
- if (!(await (adapter as any).mailboxes.getById(mailboxId))) {
119
- await (adapter as any).mailboxes.create({
120
- id: mailboxId,
121
- created_at: new Date().toISOString(),
122
- updated_at: new Date().toISOString(),
123
- });
124
- stats.mailboxes++;
125
- }
126
-
127
- for (const event of events) {
128
- try {
129
- if (!event.type) {
130
- console.warn(`[Migration] Skipping event without type field in mailbox ${mailboxId}`);
131
- continue;
132
- }
133
-
134
- await (adapter as any).events.append({
135
- event_type: event.type,
136
- stream_type: 'squawk',
137
- stream_id: mailboxId,
138
- data:
139
- typeof event.data === 'string'
140
- ? JSON.parse(event.data)
141
- : event.data,
142
- occurred_at: event.occurred_at,
143
- causation_id: event.causation_id,
144
- correlation_id: event.correlation_id,
145
- metadata: event.metadata
146
- ? typeof event.metadata === 'string'
147
- ? JSON.parse(event.metadata)
148
- : event.metadata
149
- : undefined,
150
- });
151
- stats.events++;
152
- } catch (error) {
153
- console.warn(`[Migration] Failed to migrate event:`, error);
154
- }
155
- }
156
- }
157
-
158
- for (const [id, cursor] of Object.entries(legacyData.cursors || {})) {
159
- try {
160
- await (adapter as any).cursors.create({
161
- id,
162
- stream_type: 'squawk',
163
- stream_id: cursor.stream_id,
164
- position: cursor.position,
165
- consumer_id: cursor.consumer_id || 'migrated',
166
- });
167
- stats.cursors++;
168
- } catch (error) {
169
- console.warn(`[Migration] Failed to migrate cursor ${id}:`, error);
170
- }
171
- }
172
-
173
- for (const [id, lock] of Object.entries(legacyData.locks || {})) {
174
- const lockData = lock as any;
175
- if (!lockData.released_at) {
176
- try {
177
- await (adapter as any).locks.acquire({
178
- file: lockData.file,
179
- specialist_id: lockData.reserved_by,
180
- timeout_ms: lockData.timeout_ms || 30000,
181
- purpose:
182
- lockData.purpose === 'delete'
183
- ? 'delete'
184
- : lockData.purpose === 'read'
185
- ? 'read'
186
- : 'edit',
187
- checksum: lockData.checksum,
188
- });
189
- stats.locks++;
190
- } catch (error) {
191
- console.warn(`[Migration] Failed to migrate lock ${id}:`, error);
192
- }
193
- }
194
- }
195
-
196
- console.log(`[Migration] Complete:`);
197
- console.log(` - Mailboxes: ${stats.mailboxes}`);
198
- console.log(` - Events: ${stats.events}`);
199
- console.log(` - Cursors: ${stats.cursors}`);
200
- console.log(` - Locks: ${stats.locks}`);
201
- } catch (error) {
202
- console.error('[Migration] Failed:', error);
203
- throw error;
204
- }
205
- }
206
-
207
-
208
-
209
- export const mailboxOps = {
210
- getAll: async () => {
211
- const adapter = getAdapter() as any;
212
- const mailboxes = await adapter.mailboxes.getAll();
213
- return mailboxes.sort(
214
- (a: any, b: any) =>
215
- new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
216
- );
217
- },
218
-
219
- getById: async (id: string) => {
220
- const adapter = getAdapter() as any;
221
- return adapter.mailboxes.getById(id);
222
- },
223
-
224
- create: async (id: string) => {
225
- const adapter = getAdapter() as any;
226
- const now = new Date().toISOString();
227
- return adapter.mailboxes.create({
228
- id,
229
- created_at: now,
230
- updated_at: now,
231
- });
232
- },
233
-
234
- exists: async (id: string) => {
235
- const adapter = getAdapter() as any;
236
- const mailbox = await adapter.mailboxes.getById(id);
237
- return mailbox !== null;
238
- },
239
- };
240
-
241
- export const eventOps = {
242
- getByMailbox: async (mailboxId: string) => {
243
- const adapter = getAdapter() as any;
244
- const events = await adapter.events.queryByStream('squawk', mailboxId);
245
- return events.sort(
246
- (a: any, b: any) =>
247
- new Date(a.occurred_at).getTime() -
248
- new Date(b.occurred_at).getTime()
249
- );
250
- },
251
-
252
- append: async (mailboxId: string, events: any[]) => {
253
- const adapter = getAdapter() as any;
254
-
255
- if (!(await adapter.mailboxes.getById(mailboxId))) {
256
- await adapter.mailboxes.create({
257
- id: mailboxId,
258
- created_at: new Date().toISOString(),
259
- updated_at: new Date().toISOString(),
260
- });
261
- }
262
-
263
- const inserted: Event[] = [];
264
- for (const event of events) {
265
- const appended = await adapter.events.append({
266
- event_type: event.type,
267
- stream_type: 'squawk',
268
- stream_id: mailboxId,
269
- data:
270
- typeof event.data === 'string'
271
- ? JSON.parse(event.data)
272
- : event.data,
273
- occurred_at: event.occurred_at,
274
- causation_id: event.causation_id,
275
- correlation_id: event.correlation_id,
276
- metadata: event.metadata
277
- ? typeof event.metadata === 'string'
278
- ? JSON.parse(event.metadata)
279
- : event.metadata
280
- : undefined,
281
- });
282
- inserted.push(appended);
283
- }
284
-
285
- return inserted;
286
- },
287
- };
288
-
289
- export const cursorOps = {
290
- getById: async (id: string) => {
291
- const adapter = getAdapter() as any;
292
- return adapter.cursors.getById(id);
293
- },
294
-
295
- getByStream: async (streamId: string) => {
296
- const adapter = getAdapter() as any;
297
- const cursors = await adapter.cursors.getAll();
298
- return (
299
- cursors.find((c: Cursor) => c.stream_id === streamId) ||
300
- null
301
- );
302
- },
303
-
304
- upsert: async (cursor: any) => {
305
- const adapter = getAdapter() as any;
306
- const id = cursor.id || `${cursor.stream_id}_cursor`;
307
- const now = new Date().toISOString();
308
-
309
- const existing = await adapter.cursors.getById(id);
310
-
311
- if (existing) {
312
- await adapter.cursors.update(id, {
313
- position: cursor.position,
314
- updated_at: now,
315
- });
316
- return existing;
317
- } else {
318
- return adapter.cursors.create({
319
- id,
320
- stream_type: 'squawk',
321
- stream_id: cursor.stream_id,
322
- position: cursor.position,
323
- consumer_id: cursor.consumer_id || 'default',
324
- });
325
- }
326
- },
327
- };
328
-
329
- export const lockOps = {
330
- getAll: async () => {
331
- const adapter = getAdapter() as any;
332
- const allLocks = await adapter.locks.getAll();
333
- const now = new Date().toISOString();
334
-
335
- return allLocks.filter((lock: any) => {
336
- if (lock.status === 'released') return false;
337
-
338
- const expiresAt = lock.expires_at;
339
- return expiresAt > now;
340
- });
341
- },
342
-
343
- getById: async (id: string) => {
344
- const adapter = getAdapter() as any;
345
- return adapter.locks.getById(id);
346
- },
347
-
348
- acquire: async (lock: any) => {
349
- const adapter = getAdapter() as any;
350
-
351
- const result = await adapter.locks.acquire({
352
- file: lock.file,
353
- specialist_id: lock.reserved_by || lock.specialist_id,
354
- timeout_ms: lock.timeout_ms || 30000,
355
- purpose:
356
- lock.purpose === 'delete'
357
- ? 'delete'
358
- : lock.purpose === 'read'
359
- ? 'read'
360
- : 'edit',
361
- checksum: lock.checksum,
362
- });
363
-
364
- if (result.conflict) {
365
- // (legacy behavior: acquire always returns a lock object)
366
- return result.existing_lock || {
367
- id: result.lock?.id || '',
368
- file: lock.file,
369
- reserved_by: result.lock?.reserved_by || '',
370
- reserved_at: result.lock?.reserved_at || '',
371
- released_at: null,
372
- purpose: lock.purpose || 'edit',
373
- checksum: lock.checksum,
374
- timeout_ms: lock.timeout_ms || 30000,
375
- metadata: lock.metadata,
376
- };
377
- }
378
-
379
- return result.lock;
380
- },
381
-
382
- release: async (id: string) => {
383
- const adapter = getAdapter() as any;
384
- const lock = await adapter.locks.getById(id);
385
- if (lock) {
386
- await adapter.locks.release(id);
387
- return lock;
388
- }
389
- return null;
390
- },
391
-
392
- getExpired: async () => {
393
- const adapter = getAdapter() as any;
394
- const allLocks = await adapter.locks.getAll();
395
- const now = new Date().toISOString();
396
-
397
- return allLocks.filter((lock: any) => {
398
- if (lock.status === 'released') return false;
399
-
400
- const expiresAt = lock.expires_at;
401
- return expiresAt <= now;
402
- });
403
- },
404
-
405
- releaseExpired: async () => {
406
- const expired = await lockOps.getExpired();
407
- for (const lock of expired) {
408
- await lockOps.release(lock.id);
409
- }
410
- return expired.length;
411
- },
412
- };
413
-
414
- // TYPE EXPORTS (Backward Compatibility)
415
-
416
-
417
- export type { Mailbox, Event, Cursor, Lock };
package/src/db/schema.sql DELETED
@@ -1,112 +0,0 @@
1
- -- FleetTools Squawk Database Schema
2
- -- Uses SQLite with WAL mode for better concurrency
3
-
4
- -- Missions table
5
- CREATE TABLE IF NOT EXISTS missions (
6
- id TEXT PRIMARY KEY,
7
- title TEXT NOT NULL,
8
- description TEXT,
9
- status TEXT NOT NULL DEFAULT 'pending',
10
- priority TEXT NOT NULL DEFAULT 'medium',
11
- created_at TEXT NOT NULL,
12
- started_at TEXT,
13
- completed_at TEXT,
14
- total_sorties INTEGER NOT NULL DEFAULT 0,
15
- completed_sorties INTEGER NOT NULL DEFAULT 0,
16
- result TEXT,
17
- metadata TEXT
18
- );
19
-
20
- -- Sorties table
21
- CREATE TABLE IF NOT EXISTS sorties (
22
- id TEXT PRIMARY KEY,
23
- mission_id TEXT,
24
- title TEXT NOT NULL,
25
- description TEXT,
26
- status TEXT NOT NULL DEFAULT 'pending',
27
- priority TEXT NOT NULL DEFAULT 'medium',
28
- assigned_to TEXT,
29
- files TEXT,
30
- progress INTEGER NOT NULL DEFAULT 0,
31
- progress_notes TEXT,
32
- started_at TEXT,
33
- completed_at TEXT,
34
- blocked_by TEXT,
35
- blocked_reason TEXT,
36
- result TEXT,
37
- metadata TEXT,
38
- FOREIGN KEY (mission_id) REFERENCES missions(id) ON DELETE CASCADE
39
- );
40
-
41
- -- Mailboxes table
42
- CREATE TABLE IF NOT EXISTS mailboxes (
43
- id TEXT PRIMARY KEY,
44
- created_at TEXT NOT NULL,
45
- updated_at TEXT NOT NULL
46
- );
47
-
48
- -- Events table - stores mailbox events
49
- CREATE TABLE IF NOT EXISTS events (
50
- id TEXT PRIMARY KEY,
51
- mailbox_id TEXT NOT NULL,
52
- type TEXT NOT NULL,
53
- stream_type TEXT NOT NULL,
54
- stream_id TEXT NOT NULL,
55
- sequence_number INTEGER NOT NULL,
56
- data TEXT NOT NULL,
57
- occurred_at TEXT NOT NULL,
58
- causation_id TEXT,
59
- correlation_id TEXT,
60
- metadata TEXT,
61
- FOREIGN KEY (mailbox_id) REFERENCES mailboxes(id) ON DELETE CASCADE
62
- );
63
-
64
- -- Cursors table - tracks read positions
65
- CREATE TABLE IF NOT EXISTS cursors (
66
- id TEXT PRIMARY KEY,
67
- stream_id TEXT NOT NULL,
68
- position INTEGER NOT NULL,
69
- consumer_id TEXT,
70
- updated_at TEXT NOT NULL,
71
- UNIQUE(stream_id)
72
- );
73
-
74
- -- Locks table - CTK file locks
75
- CREATE TABLE IF NOT EXISTS locks (
76
- id TEXT PRIMARY KEY,
77
- file TEXT NOT NULL,
78
- reserved_by TEXT NOT NULL,
79
- reserved_at TEXT NOT NULL,
80
- released_at TEXT,
81
- purpose TEXT DEFAULT 'edit',
82
- checksum TEXT,
83
- timeout_ms INTEGER DEFAULT 30000,
84
- expires_at TEXT,
85
- status TEXT DEFAULT 'active',
86
- metadata TEXT
87
- );
88
-
89
- -- Specialists table - tracks active specialists
90
- CREATE TABLE IF NOT EXISTS specialists (
91
- id TEXT PRIMARY KEY,
92
- name TEXT NOT NULL,
93
- status TEXT DEFAULT 'active',
94
- last_seen TEXT NOT NULL,
95
- metadata TEXT
96
- );
97
-
98
- -- Indexes for performance (created AFTER all tables)
99
- CREATE INDEX IF NOT EXISTS idx_events_mailbox ON events(mailbox_id);
100
- CREATE INDEX IF NOT EXISTS idx_events_stream ON events(stream_type, stream_id, occurred_at);
101
- CREATE INDEX IF NOT EXISTS idx_events_sequence ON events(stream_type, stream_id, sequence_number);
102
- CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
103
- CREATE INDEX IF NOT EXISTS idx_locks_file ON locks(file);
104
- CREATE INDEX IF NOT EXISTS idx_locks_reserved_by ON locks(reserved_by);
105
- CREATE INDEX IF NOT EXISTS idx_specialists_status ON specialists(status);
106
-
107
- -- Triggers for updated_at
108
- CREATE TRIGGER IF NOT EXISTS update_mailbox_timestamp
109
- AFTER UPDATE ON mailboxes
110
- BEGIN
111
- UPDATE mailboxes SET updated_at = datetime('now') WHERE id = NEW.id;
112
- END;
@@ -1,31 +0,0 @@
1
- import Database from 'bun:sqlite';
2
- import type { DatabaseAdapter, DatabaseStats, MissionOps, SortieOps, LockOps, EventOps, CheckpointOps, SpecialistOps, MessageOps, CursorOps } from './types.js';
3
- export declare class SQLiteAdapter implements DatabaseAdapter {
4
- version: "1.0.0";
5
- private db;
6
- private dbPath;
7
- private schemaPath;
8
- missions: MissionOps;
9
- sorties: SortieOps;
10
- locks: LockOps;
11
- events: EventOps;
12
- checkpoints: CheckpointOps;
13
- specialists: SpecialistOps;
14
- messages: MessageOps;
15
- cursors: CursorOps;
16
- constructor(dbPath?: string, schemaPath?: string);
17
- private resolveSchemaPath;
18
- initialize(): Promise<void>;
19
- private initializeOperations;
20
- close(): Promise<void>;
21
- isHealthy(): Promise<boolean>;
22
- getStats(): Promise<DatabaseStats>;
23
- maintenance(): Promise<void>;
24
- beginTransaction(): Promise<void>;
25
- commitTransaction(): Promise<void>;
26
- rollbackTransaction(): Promise<void>;
27
- getDatabase(): Database | null;
28
- }
29
- export declare function createSQLiteAdapter(dbPath?: string): Promise<SQLiteAdapter>;
30
- export declare function createInMemoryAdapter(): Promise<SQLiteAdapter>;
31
- //# sourceMappingURL=sqlite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,YAAY,CAAC;AAGlC,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EAEb,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,UAAU,EACV,SAAS,EAQV,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,EAAG,OAAO,CAAU;IAE3B,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAEpB,QAAQ,EAAE,UAAU,CAAoB;IACxC,OAAO,EAAE,SAAS,CAAmB;IACrC,KAAK,EAAE,OAAO,CAAiB;IAC/B,MAAM,EAAE,QAAQ,CAAkB;IAClC,WAAW,EAAE,aAAa,CAAuB;IACjD,WAAW,EAAE,aAAa,CAAuB;IACjD,QAAQ,EAAE,UAAU,CAAoB;IACxC,OAAO,EAAE,SAAS,CAAmB;gBAEhC,MAAM,GAAE,MAAmB,EAAE,UAAU,CAAC,EAAE,MAAM;IAW5D,OAAO,CAAC,iBAAiB;IA0CnB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC,OAAO,CAAC,oBAAoB;IAmjBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAa7B,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;IAuClC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAalC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAa1C,WAAW,IAAI,QAAQ,GAAG,IAAI;CAG/B;AAED,wBAAsB,mBAAmB,CAAC,MAAM,GAAE,MAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAI7F;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,aAAa,CAAC,CAEpE"}