crbro-memory 1.1.0 → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // ─── CRBRO License Engine ────────────────────────────────────────
3
- // Server-side license validation against Firestore + local cache
3
+ // Server-side license validation against Firestore + device limit + local cache
4
4
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
5
  if (k2 === undefined) k2 = k;
6
6
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -39,9 +39,12 @@ exports.LicenseEngine = void 0;
39
39
  const https = __importStar(require("https"));
40
40
  const path = __importStar(require("path"));
41
41
  const fs = __importStar(require("fs"));
42
+ const os = __importStar(require("os"));
43
+ const crypto = __importStar(require("crypto"));
42
44
  // Firestore project for license validation
43
45
  const FIRESTORE_PROJECT = 'synthetica-decks';
44
46
  const COLLECTION = 'license-checks';
47
+ const MAX_DEVICES = 3;
45
48
  // Cache duration: 7 days in milliseconds
46
49
  const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
47
50
  // Valid license key prefix — Synthetica Zero Deck keys
@@ -49,12 +52,14 @@ const LICENSE_PREFIX = 'SYNTH-ZERO-';
49
52
  class LicenseEngine {
50
53
  brain;
51
54
  cacheFile;
55
+ deviceId;
52
56
  constructor(brain) {
53
57
  this.brain = brain;
54
58
  this.cacheFile = path.join(brain.paths.root, '.license-cache.json');
59
+ this.deviceId = this.generateDeviceFingerprint();
55
60
  }
56
61
  /**
57
- * Check if the license is valid (server-verified).
62
+ * Check if the license is valid (server-verified + device limit).
58
63
  * Uses local cache if verified within 7 days.
59
64
  */
60
65
  async isPremium() {
@@ -66,22 +71,38 @@ class LicenseEngine {
66
71
  return false;
67
72
  // Check local cache first
68
73
  const cached = await this.readCache();
69
- if (cached && cached.key === key && cached.valid) {
74
+ if (cached && cached.key === key && cached.valid && cached.deviceId === this.deviceId) {
70
75
  const age = Date.now() - cached.verifiedAt;
71
76
  if (age < CACHE_TTL_MS) {
72
- return true; // Cache still valid
77
+ return true;
73
78
  }
74
79
  }
75
80
  // Cache expired or missing — verify against Firestore
76
- const serverResult = await this.verifyWithServer(key);
81
+ const result = await this.verifyAndRegisterDevice(key);
77
82
  // Save result to cache
78
83
  await this.writeCache({
79
84
  key,
80
- valid: serverResult,
85
+ valid: result.valid,
81
86
  verifiedAt: Date.now(),
82
- status: serverResult ? 'active' : 'invalid',
87
+ deviceId: this.deviceId,
88
+ status: result.status,
83
89
  });
84
- return serverResult;
90
+ return result.valid;
91
+ }
92
+ /**
93
+ * Get the rejection reason (for error messages).
94
+ */
95
+ async getRejectionReason() {
96
+ const key = await this.resolveKey();
97
+ if (!key)
98
+ return 'no_key';
99
+ if (!this.validateFormat(key))
100
+ return 'invalid_format';
101
+ const cached = await this.readCache();
102
+ if (cached && cached.key === key && !cached.valid) {
103
+ return cached.status;
104
+ }
105
+ return null;
85
106
  }
86
107
  /**
87
108
  * Get current license info.
@@ -92,27 +113,42 @@ class LicenseEngine {
92
113
  return this.getInfo(valid ? key : null);
93
114
  }
94
115
  /**
95
- * Legacy compatibility — canUse now just checks isPremium for everything.
116
+ * Legacy compatibility.
96
117
  */
97
118
  async canUse(_toolName) {
98
119
  return this.isPremium();
99
120
  }
100
121
  // ─── Private ─────────────────────────────────────────────────
122
+ /**
123
+ * Generate a unique device fingerprint from hardware characteristics.
124
+ */
125
+ generateDeviceFingerprint() {
126
+ const raw = [
127
+ os.hostname(),
128
+ os.userInfo().username,
129
+ os.platform(),
130
+ os.arch(),
131
+ os.cpus()[0]?.model || 'unknown',
132
+ ].join('|');
133
+ return crypto.createHash('sha256').update(raw).digest('hex').substring(0, 16);
134
+ }
101
135
  /**
102
136
  * Resolve the license key — env var takes priority over manifest.
103
137
  */
104
138
  async resolveKey() {
105
- // 1. Check environment variable first (set in mcp_config.json env block)
106
139
  const envKey = process.env.CRBRO_LICENSE_KEY || null;
107
140
  if (envKey && this.validateFormat(envKey))
108
141
  return envKey;
109
- // 2. Fall back to manifest (set via CLI activate)
110
- const manifest = await this.brain.getManifest();
111
- return manifest.license_key || null;
142
+ try {
143
+ const manifest = await this.brain.getManifest();
144
+ return manifest.license_key || null;
145
+ }
146
+ catch {
147
+ return null;
148
+ }
112
149
  }
113
150
  /**
114
151
  * Basic format validation — prefix + length + characters.
115
- * Does NOT verify the key is real. Use verifyWithServer() for that.
116
152
  */
117
153
  validateFormat(key) {
118
154
  if (!key)
@@ -127,10 +163,45 @@ class LicenseEngine {
127
163
  return true;
128
164
  }
129
165
  /**
130
- * Verify license key against Firestore REST API.
131
- * Checks if document exists in license-checks/{key} with status 'active'.
166
+ * Verify license AND register this device.
167
+ * Returns { valid, status } where status explains why if invalid.
168
+ */
169
+ async verifyAndRegisterDevice(key) {
170
+ // Step 1: Fetch the license document
171
+ const doc = await this.fetchLicenseDoc(key);
172
+ if (!doc) {
173
+ return { valid: false, status: 'key_not_found' };
174
+ }
175
+ const status = doc.fields?.status?.stringValue;
176
+ if (status !== 'active') {
177
+ return { valid: false, status: 'license_revoked' };
178
+ }
179
+ // Step 2: Check device limit
180
+ const devicesArray = doc.fields?.devices?.arrayValue?.values || [];
181
+ const registeredDevices = devicesArray.map(v => v.stringValue || '');
182
+ // This device is already registered — all good
183
+ if (registeredDevices.includes(this.deviceId)) {
184
+ return { valid: true, status: 'active' };
185
+ }
186
+ // Check if there's room for another device
187
+ if (registeredDevices.length >= MAX_DEVICES) {
188
+ return { valid: false, status: 'device_limit_exceeded' };
189
+ }
190
+ // Step 3: Register this device
191
+ const newDevices = [...registeredDevices, this.deviceId];
192
+ const registered = await this.updateDevices(key, newDevices);
193
+ if (registered) {
194
+ return { valid: true, status: 'active' };
195
+ }
196
+ else {
197
+ // Registration failed (possibly race condition or rule violation)
198
+ return { valid: false, status: 'device_registration_failed' };
199
+ }
200
+ }
201
+ /**
202
+ * Fetch license document from Firestore REST API.
132
203
  */
133
- verifyWithServer(key) {
204
+ fetchLicenseDoc(key) {
134
205
  return new Promise((resolve) => {
135
206
  const encodedKey = encodeURIComponent(key);
136
207
  const url = `https://firestore.googleapis.com/v1/projects/${FIRESTORE_PROJECT}/databases/(default)/documents/${COLLECTION}/${encodedKey}`;
@@ -140,48 +211,60 @@ class LicenseEngine {
140
211
  res.on('end', () => {
141
212
  try {
142
213
  if (res.statusCode === 200) {
143
- const doc = JSON.parse(data);
144
- // Check that the document has status = 'active'
145
- const status = doc?.fields?.status?.stringValue;
146
- resolve(status === 'active');
147
- }
148
- else if (res.statusCode === 404) {
149
- // Document doesn't exist — key is not valid
150
- resolve(false);
214
+ resolve(JSON.parse(data));
151
215
  }
152
216
  else {
153
- // Server error or unexpected response — fail closed
154
- resolve(false);
217
+ resolve(null);
155
218
  }
156
219
  }
157
220
  catch {
158
- resolve(false);
221
+ resolve(null);
159
222
  }
160
223
  });
161
224
  });
162
- req.on('error', () => {
163
- // Network error check cache as fallback
164
- this.readCache().then((cached) => {
165
- if (cached && cached.key === key && cached.valid) {
166
- resolve(true); // Trust cache if offline
167
- }
168
- else {
169
- resolve(false);
170
- }
171
- }).catch(() => resolve(false));
225
+ req.on('error', () => resolve(null));
226
+ req.on('timeout', () => { req.destroy(); resolve(null); });
227
+ });
228
+ }
229
+ /**
230
+ * Update the devices array in Firestore via REST API PATCH.
231
+ */
232
+ updateDevices(key, devices) {
233
+ return new Promise((resolve) => {
234
+ const encodedKey = encodeURIComponent(key);
235
+ const url = `https://firestore.googleapis.com/v1/projects/${FIRESTORE_PROJECT}/databases/(default)/documents/${COLLECTION}/${encodedKey}?updateMask.fieldPaths=devices`;
236
+ const body = JSON.stringify({
237
+ fields: {
238
+ devices: {
239
+ arrayValue: {
240
+ values: devices.map(d => ({ stringValue: d })),
241
+ },
242
+ },
243
+ },
172
244
  });
173
- req.on('timeout', () => {
174
- req.destroy();
175
- // Timeout — same fallback as network error
176
- this.readCache().then((cached) => {
177
- if (cached && cached.key === key && cached.valid) {
178
- resolve(true);
179
- }
180
- else {
181
- resolve(false);
182
- }
183
- }).catch(() => resolve(false));
245
+ const parsed = new URL(url);
246
+ const options = {
247
+ hostname: parsed.hostname,
248
+ path: parsed.pathname + parsed.search,
249
+ method: 'PATCH',
250
+ timeout: 10000,
251
+ headers: {
252
+ 'Content-Type': 'application/json',
253
+ 'Content-Length': Buffer.byteLength(body),
254
+ },
255
+ };
256
+ const req = https.request(options, (res) => {
257
+ let data = '';
258
+ res.on('data', (chunk) => { data += chunk.toString(); });
259
+ res.on('end', () => {
260
+ // 200 = success, 403 = device limit exceeded (security rule violation)
261
+ resolve(res.statusCode === 200);
262
+ });
184
263
  });
264
+ req.on('error', () => resolve(false));
265
+ req.on('timeout', () => { req.destroy(); resolve(false); });
266
+ req.write(body);
267
+ req.end();
185
268
  });
186
269
  }
187
270
  // ─── Cache management ──────────────────────────────────────────
@@ -201,7 +284,7 @@ class LicenseEngine {
201
284
  fs.writeFileSync(this.cacheFile, JSON.stringify(cache, null, 2), 'utf-8');
202
285
  }
203
286
  catch {
204
- // Silent fail — cache is a convenience, not critical
287
+ // Silent fail
205
288
  }
206
289
  }
207
290
  getInfo(key) {
@@ -1 +1 @@
1
- {"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/engine/license.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/engine/license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface ExtractedContent {
2
+ topics: string[];
3
+ facts: string[];
4
+ decisions: string[];
5
+ technologies: string[];
6
+ summary: string;
7
+ }
8
+ /**
9
+ * Extract structured content from a markdown file's text.
10
+ */
11
+ export declare function extractContent(text: string, filename: string): ExtractedContent;
12
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/miner/extractor.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAiDD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAqE/E"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ // ─── CRBRO Miner: Text Extractor ──────────────────────────────
3
+ // Simple keyword/fact/decision extraction from markdown files.
4
+ // No AI required — uses regex patterns and basic NLP.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractContent = extractContent;
7
+ // Common technology keywords to detect
8
+ const TECH_KEYWORDS = new Set([
9
+ 'react', 'vue', 'angular', 'svelte', 'next.js', 'nextjs', 'nuxt', 'vite',
10
+ 'node', 'nodejs', 'deno', 'bun', 'express', 'fastify', 'koa',
11
+ 'python', 'django', 'flask', 'fastapi',
12
+ 'typescript', 'javascript', 'php', 'ruby', 'go', 'rust', 'java', 'kotlin', 'swift',
13
+ 'firebase', 'supabase', 'mongodb', 'postgresql', 'mysql', 'redis', 'sqlite',
14
+ 'docker', 'kubernetes', 'terraform', 'ansible',
15
+ 'aws', 'gcp', 'azure', 'cloudflare', 'vercel', 'netlify',
16
+ 'github', 'gitlab', 'bitbucket',
17
+ 'wordpress', 'shopify', 'strapi', 'sanity',
18
+ 'tailwind', 'css', 'sass', 'less',
19
+ 'graphql', 'rest', 'grpc', 'websocket',
20
+ 'stripe', 'paypal', 'openai', 'gemini', 'claude', 'ollama',
21
+ 'electron', 'tauri', 'flutter', 'react native',
22
+ 'cloud run', 'cloud functions', 'lambda', 'ec2', 's3',
23
+ 'firestore', 'realtime database', 'cloud storage',
24
+ 'seo', 'rank math', 'yoast', 'schema markup',
25
+ 'mcp', 'model context protocol',
26
+ ]);
27
+ // Decision indicator patterns (multilingual)
28
+ const DECISION_PATTERNS = [
29
+ // English
30
+ /(?:decided|chose|selected|opted|switched|migrated|moved|changed|replaced|upgraded|downgraded)\s+(?:to|from|for)\s+(.+)/gi,
31
+ /(?:we(?:'ll| will)|going to|plan to|need to)\s+(migrate|switch|move|change|replace|implement|build|create|use)\s+(.+)/gi,
32
+ // Spanish
33
+ /(?:decidimos|elegimos|optamos|migramos|cambiamos|reemplazamos)\s+(.+)/gi,
34
+ /(?:vamos a|hay que|necesitamos)\s+(migrar|cambiar|reemplazar|implementar|crear|usar)\s+(.+)/gi,
35
+ // French
36
+ /(?:décidé|choisi|opté|migré|changé|remplacé)\s+(?:de|pour|à)\s+(.+)/gi,
37
+ // German
38
+ /(?:entschieden|gewählt|migriert|gewechselt|ersetzt)\s+(.+)/gi,
39
+ // Italian
40
+ /(?:deciso|scelto|migrato|cambiato|sostituito)\s+(?:di|per|a)\s+(.+)/gi,
41
+ ];
42
+ // Fact indicator patterns
43
+ const FACT_PATTERNS = [
44
+ /(?:uses?|utilizes?|runs? on|built with|powered by|depends? on|requires?)\s+(.+)/gi,
45
+ /(?:usa|utiliza|funciona con|construido con|depende de|requiere)\s+(.+)/gi,
46
+ /(?:deployed?|hosted?|served?)\s+(?:on|at|via|through)\s+(.+)/gi,
47
+ /(?:desplegado|alojado|servido)\s+(?:en|vía|a través de)\s+(.+)/gi,
48
+ /(?:version|v)\s*(\d+\.\d+(?:\.\d+)?)/gi,
49
+ /(?:port|puerto)\s*(\d{2,5})/gi,
50
+ ];
51
+ /**
52
+ * Extract structured content from a markdown file's text.
53
+ */
54
+ function extractContent(text, filename) {
55
+ const lines = text.split('\n');
56
+ const topics = new Set();
57
+ const facts = [];
58
+ const decisions = [];
59
+ const technologies = new Set();
60
+ // Extract topics from headers
61
+ for (const line of lines) {
62
+ const headerMatch = line.match(/^#{1,3}\s+(.+)/);
63
+ if (headerMatch) {
64
+ const header = headerMatch[1].trim();
65
+ if (header.length > 3 && header.length < 100) {
66
+ topics.add(header);
67
+ }
68
+ }
69
+ }
70
+ // Extract from filename
71
+ const fileBaseName = filename.replace(/\.(md|txt)$/i, '').replace(/[_-]/g, ' ');
72
+ if (fileBaseName.length > 3) {
73
+ topics.add(fileBaseName);
74
+ }
75
+ const textLower = text.toLowerCase();
76
+ // Detect technologies
77
+ for (const tech of TECH_KEYWORDS) {
78
+ // Word boundary check to avoid partial matches
79
+ const regex = new RegExp(`\\b${tech.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i');
80
+ if (regex.test(textLower)) {
81
+ technologies.add(tech);
82
+ }
83
+ }
84
+ // Extract decisions
85
+ for (const pattern of DECISION_PATTERNS) {
86
+ pattern.lastIndex = 0;
87
+ let match;
88
+ while ((match = pattern.exec(text)) !== null) {
89
+ const decision = match[0].trim();
90
+ if (decision.length > 10 && decision.length < 200) {
91
+ decisions.push(cleanExtract(decision));
92
+ }
93
+ }
94
+ }
95
+ // Extract facts
96
+ for (const pattern of FACT_PATTERNS) {
97
+ pattern.lastIndex = 0;
98
+ let match;
99
+ while ((match = pattern.exec(text)) !== null) {
100
+ const fact = match[0].trim();
101
+ if (fact.length > 10 && fact.length < 200) {
102
+ facts.push(cleanExtract(fact));
103
+ }
104
+ }
105
+ }
106
+ // Generate summary from first substantial paragraph
107
+ const summary = generateSummary(lines);
108
+ return {
109
+ topics: [...topics].slice(0, 10),
110
+ facts: deduplicateStrings(facts).slice(0, 15),
111
+ decisions: deduplicateStrings(decisions).slice(0, 10),
112
+ technologies: [...technologies],
113
+ summary,
114
+ };
115
+ }
116
+ /**
117
+ * Clean an extracted string: remove markdown artifacts, trim whitespace.
118
+ */
119
+ function cleanExtract(text) {
120
+ return text
121
+ .replace(/[`*_~\[\]]/g, '')
122
+ .replace(/\s+/g, ' ')
123
+ .trim();
124
+ }
125
+ /**
126
+ * Generate a one-line summary from the first meaningful paragraph.
127
+ */
128
+ function generateSummary(lines) {
129
+ for (const line of lines) {
130
+ const trimmed = line.trim();
131
+ // Skip empty lines, headers, code blocks, frontmatter
132
+ if (!trimmed)
133
+ continue;
134
+ if (trimmed.startsWith('#'))
135
+ continue;
136
+ if (trimmed.startsWith('```'))
137
+ continue;
138
+ if (trimmed.startsWith('---'))
139
+ continue;
140
+ if (trimmed.startsWith('|'))
141
+ continue;
142
+ if (trimmed.startsWith('-') && trimmed.length < 20)
143
+ continue;
144
+ // Found a substantial line
145
+ if (trimmed.length > 30) {
146
+ const clean = cleanExtract(trimmed);
147
+ return clean.length > 150 ? clean.substring(0, 150) + '...' : clean;
148
+ }
149
+ }
150
+ return '';
151
+ }
152
+ /**
153
+ * Simple deduplication by normalized similarity.
154
+ */
155
+ function deduplicateStrings(arr) {
156
+ const seen = new Set();
157
+ const result = [];
158
+ for (const item of arr) {
159
+ const normalized = item.toLowerCase().replace(/\s+/g, ' ').trim();
160
+ if (!seen.has(normalized)) {
161
+ seen.add(normalized);
162
+ result.push(item);
163
+ }
164
+ }
165
+ return result;
166
+ }
167
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/miner/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { MineResult } from './types.js';
2
+ export interface MinerConfig {
3
+ /** Directories to scan for artifacts */
4
+ scanDirs: string[];
5
+ /** Minimum file size in bytes to consider */
6
+ minFileSize: number;
7
+ /** File extensions to include */
8
+ extensions: string[];
9
+ /** Patterns to exclude from scanning */
10
+ excludePatterns: string[];
11
+ }
12
+ interface MinerState {
13
+ mined_files: Record<string, string>;
14
+ last_run: string | null;
15
+ total_mined: number;
16
+ }
17
+ export type { MineResult };
18
+ /**
19
+ * Auto-detect IDE conversation directories on the system.
20
+ */
21
+ export declare function detectScanDirs(): string[];
22
+ /**
23
+ * Main miner class — scans directories and feeds CRBRO.
24
+ */
25
+ export declare class Miner {
26
+ private brain;
27
+ private cortex;
28
+ private config;
29
+ private statePath;
30
+ constructor(config?: Partial<MinerConfig>);
31
+ /**
32
+ * Run the miner on all configured directories.
33
+ */
34
+ mine(targetDir?: string): Promise<MineResult>;
35
+ /**
36
+ * Recursively collect files matching the config criteria.
37
+ */
38
+ private collectFiles;
39
+ /**
40
+ * Feed extracted content into CRBRO's cortex.
41
+ */
42
+ private feedCortex;
43
+ /**
44
+ * Load miner state from disk.
45
+ */
46
+ private loadState;
47
+ /**
48
+ * Save miner state to disk.
49
+ */
50
+ private saveState;
51
+ /**
52
+ * Get miner status info.
53
+ */
54
+ getStatus(): Promise<{
55
+ configured_dirs: string[];
56
+ detected_dirs: string[];
57
+ state: MinerState;
58
+ }>;
59
+ }
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/miner/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,wCAAwC;IACxC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,YAAY,EAAE,UAAU,EAAE,CAAC;AAgB3B;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CA0BzC;AAED;;GAEG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAYzC;;OAEG;IACG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmFnD;;OAEG;YACW,YAAY;IAkC1B;;OAEG;YACW,UAAU;IAsExB;;OAEG;YACW,SAAS;IAevB;;OAEG;YACW,SAAS;IAQvB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,KAAK,EAAE,UAAU,CAAC;KACnB,CAAC;CAOH"}