@ruvector/ruvllm 0.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.
Files changed (75) hide show
  1. package/README.md +406 -0
  2. package/bin/cli.js +387 -0
  3. package/dist/cjs/engine.d.ts +90 -0
  4. package/dist/cjs/engine.d.ts.map +1 -0
  5. package/dist/cjs/engine.js +301 -0
  6. package/dist/cjs/export.d.ts +182 -0
  7. package/dist/cjs/export.d.ts.map +1 -0
  8. package/dist/cjs/export.js +422 -0
  9. package/dist/cjs/federated.d.ts +233 -0
  10. package/dist/cjs/federated.d.ts.map +1 -0
  11. package/dist/cjs/federated.js +525 -0
  12. package/dist/cjs/index.d.ts +64 -0
  13. package/dist/cjs/index.d.ts.map +1 -0
  14. package/dist/cjs/index.js +96 -0
  15. package/dist/cjs/lora.d.ts +240 -0
  16. package/dist/cjs/lora.d.ts.map +1 -0
  17. package/dist/cjs/lora.js +494 -0
  18. package/dist/cjs/native.d.ts +83 -0
  19. package/dist/cjs/native.d.ts.map +1 -0
  20. package/dist/cjs/native.js +70 -0
  21. package/dist/cjs/session.d.ts +80 -0
  22. package/dist/cjs/session.d.ts.map +1 -0
  23. package/dist/cjs/session.js +203 -0
  24. package/dist/cjs/simd.d.ts +90 -0
  25. package/dist/cjs/simd.d.ts.map +1 -0
  26. package/dist/cjs/simd.js +209 -0
  27. package/dist/cjs/sona.d.ts +187 -0
  28. package/dist/cjs/sona.d.ts.map +1 -0
  29. package/dist/cjs/sona.js +500 -0
  30. package/dist/cjs/streaming.d.ts +55 -0
  31. package/dist/cjs/streaming.d.ts.map +1 -0
  32. package/dist/cjs/streaming.js +131 -0
  33. package/dist/cjs/training.d.ts +254 -0
  34. package/dist/cjs/training.d.ts.map +1 -0
  35. package/dist/cjs/training.js +480 -0
  36. package/dist/cjs/types.d.ts +599 -0
  37. package/dist/cjs/types.d.ts.map +1 -0
  38. package/dist/cjs/types.js +6 -0
  39. package/dist/esm/engine.d.ts +90 -0
  40. package/dist/esm/engine.d.ts.map +1 -0
  41. package/dist/esm/engine.js +297 -0
  42. package/dist/esm/export.d.ts +182 -0
  43. package/dist/esm/export.d.ts.map +1 -0
  44. package/dist/esm/export.js +414 -0
  45. package/dist/esm/federated.d.ts +233 -0
  46. package/dist/esm/federated.d.ts.map +1 -0
  47. package/dist/esm/federated.js +520 -0
  48. package/dist/esm/index.d.ts +64 -0
  49. package/dist/esm/index.d.ts.map +1 -0
  50. package/dist/esm/index.js +76 -0
  51. package/dist/esm/lora.d.ts +240 -0
  52. package/dist/esm/lora.d.ts.map +1 -0
  53. package/dist/esm/lora.js +489 -0
  54. package/dist/esm/native.d.ts +83 -0
  55. package/dist/esm/native.d.ts.map +1 -0
  56. package/dist/esm/native.js +65 -0
  57. package/dist/esm/session.d.ts +80 -0
  58. package/dist/esm/session.d.ts.map +1 -0
  59. package/dist/esm/session.js +199 -0
  60. package/dist/esm/simd.d.ts +90 -0
  61. package/dist/esm/simd.d.ts.map +1 -0
  62. package/dist/esm/simd.js +205 -0
  63. package/dist/esm/sona.d.ts +187 -0
  64. package/dist/esm/sona.d.ts.map +1 -0
  65. package/dist/esm/sona.js +494 -0
  66. package/dist/esm/streaming.d.ts +55 -0
  67. package/dist/esm/streaming.d.ts.map +1 -0
  68. package/dist/esm/streaming.js +126 -0
  69. package/dist/esm/training.d.ts +254 -0
  70. package/dist/esm/training.d.ts.map +1 -0
  71. package/dist/esm/training.js +473 -0
  72. package/dist/esm/types.d.ts +599 -0
  73. package/dist/esm/types.d.ts.map +1 -0
  74. package/dist/esm/types.js +5 -0
  75. package/package.json +121 -0
package/bin/cli.js ADDED
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * RuvLLM CLI - Self-learning LLM orchestration
4
+ *
5
+ * Usage:
6
+ * ruvllm query "What is machine learning?"
7
+ * ruvllm generate "Write a haiku about AI"
8
+ * ruvllm memory add "Important context"
9
+ * ruvllm memory search "context"
10
+ * ruvllm stats
11
+ * ruvllm benchmark
12
+ */
13
+
14
+ const { RuvLLM, SimdOps, version, hasSimdSupport } = require('../dist/cjs/index.js');
15
+
16
+ const args = process.argv.slice(2);
17
+ const command = args[0];
18
+
19
+ // Parse CLI arguments
20
+ function parseArgs(args) {
21
+ const result = { flags: {}, positional: [] };
22
+ for (let i = 0; i < args.length; i++) {
23
+ const arg = args[i];
24
+ if (arg.startsWith('--')) {
25
+ const key = arg.slice(2);
26
+ const nextArg = args[i + 1];
27
+ if (nextArg && !nextArg.startsWith('--')) {
28
+ result.flags[key] = nextArg;
29
+ i++;
30
+ } else {
31
+ result.flags[key] = true;
32
+ }
33
+ } else if (!result.command) {
34
+ result.command = arg;
35
+ } else {
36
+ result.positional.push(arg);
37
+ }
38
+ }
39
+ return result;
40
+ }
41
+
42
+ // Format output
43
+ function formatJson(obj) {
44
+ return JSON.stringify(obj, null, 2);
45
+ }
46
+
47
+ function formatTable(data) {
48
+ const maxKeyLen = Math.max(...Object.keys(data).map(k => k.length));
49
+ return Object.entries(data)
50
+ .map(([k, v]) => ` ${k.padEnd(maxKeyLen)} : ${v}`)
51
+ .join('\n');
52
+ }
53
+
54
+ // Commands
55
+ async function runQuery(llm, text, flags) {
56
+ const config = {};
57
+ if (flags.temperature) config.temperature = parseFloat(flags.temperature);
58
+ if (flags['max-tokens']) config.maxTokens = parseInt(flags['max-tokens']);
59
+ if (flags['top-p']) config.topP = parseFloat(flags['top-p']);
60
+ if (flags['top-k']) config.topK = parseInt(flags['top-k']);
61
+
62
+ const response = llm.query(text, config);
63
+
64
+ if (flags.json) {
65
+ console.log(formatJson(response));
66
+ } else {
67
+ console.log('\n' + response.text);
68
+ console.log(`\n--- Model: ${response.model} | Confidence: ${(response.confidence * 100).toFixed(1)}% | Latency: ${response.latencyMs.toFixed(2)}ms ---`);
69
+ }
70
+ }
71
+
72
+ async function runGenerate(llm, prompt, flags) {
73
+ const config = {};
74
+ if (flags.temperature) config.temperature = parseFloat(flags.temperature);
75
+ if (flags['max-tokens']) config.maxTokens = parseInt(flags['max-tokens']);
76
+ if (flags['top-p']) config.topP = parseFloat(flags['top-p']);
77
+
78
+ const text = llm.generate(prompt, config);
79
+ console.log(text);
80
+ }
81
+
82
+ async function runMemoryAdd(llm, content, flags) {
83
+ const metadata = flags.metadata ? JSON.parse(flags.metadata) : undefined;
84
+ const id = llm.addMemory(content, metadata);
85
+ console.log(`Added memory with ID: ${id}`);
86
+ }
87
+
88
+ async function runMemorySearch(llm, query, flags) {
89
+ const k = flags.k ? parseInt(flags.k) : 10;
90
+ const results = llm.searchMemory(query, k);
91
+
92
+ if (flags.json) {
93
+ console.log(formatJson(results));
94
+ } else {
95
+ if (results.length === 0) {
96
+ console.log('No results found.');
97
+ return;
98
+ }
99
+ results.forEach((r, i) => {
100
+ console.log(`\n[${i + 1}] Score: ${r.score.toFixed(4)} | ID: ${r.id}`);
101
+ console.log(` ${r.content.slice(0, 100)}${r.content.length > 100 ? '...' : ''}`);
102
+ });
103
+ }
104
+ }
105
+
106
+ async function runStats(llm, flags) {
107
+ const stats = llm.stats();
108
+
109
+ if (flags.json) {
110
+ console.log(formatJson(stats));
111
+ } else {
112
+ console.log('\nRuvLLM Statistics:');
113
+ console.log(formatTable({
114
+ 'Total Queries': stats.totalQueries,
115
+ 'Memory Nodes': stats.memoryNodes,
116
+ 'Patterns Learned': stats.patternsLearned,
117
+ 'Avg Latency': `${stats.avgLatencyMs.toFixed(2)}ms`,
118
+ 'Cache Hit Rate': `${(stats.cacheHitRate * 100).toFixed(1)}%`,
119
+ 'Router Accuracy': `${(stats.routerAccuracy * 100).toFixed(1)}%`,
120
+ }));
121
+ }
122
+ }
123
+
124
+ async function runRoute(llm, text, flags) {
125
+ const decision = llm.route(text);
126
+
127
+ if (flags.json) {
128
+ console.log(formatJson(decision));
129
+ } else {
130
+ console.log('\nRouting Decision:');
131
+ console.log(formatTable({
132
+ 'Model': decision.model,
133
+ 'Context Size': decision.contextSize,
134
+ 'Temperature': decision.temperature.toFixed(2),
135
+ 'Top-P': decision.topP.toFixed(2),
136
+ 'Confidence': `${(decision.confidence * 100).toFixed(1)}%`,
137
+ }));
138
+ }
139
+ }
140
+
141
+ async function runEmbed(llm, text, flags) {
142
+ const embedding = llm.embed(text);
143
+
144
+ if (flags.json) {
145
+ console.log(formatJson({ embedding, dimensions: embedding.length }));
146
+ } else {
147
+ console.log(`Embedding (${embedding.length} dimensions):`);
148
+ console.log(` First 10: [${embedding.slice(0, 10).map(x => x.toFixed(4)).join(', ')}...]`);
149
+ console.log(` Norm: ${Math.sqrt(embedding.reduce((s, x) => s + x * x, 0)).toFixed(4)}`);
150
+ }
151
+ }
152
+
153
+ async function runSimilarity(llm, text1, text2, flags) {
154
+ const score = llm.similarity(text1, text2);
155
+
156
+ if (flags.json) {
157
+ console.log(formatJson({ text1, text2, similarity: score }));
158
+ } else {
159
+ console.log(`Similarity: ${(score * 100).toFixed(2)}%`);
160
+ }
161
+ }
162
+
163
+ async function runBenchmark(flags) {
164
+ const simd = new SimdOps();
165
+ const dims = flags.dims ? parseInt(flags.dims) : 768;
166
+ const iterations = flags.iterations ? parseInt(flags.iterations) : 1000;
167
+
168
+ // Generate test vectors
169
+ const a = Array.from({ length: dims }, () => Math.random());
170
+ const b = Array.from({ length: dims }, () => Math.random());
171
+
172
+ console.log(`\nBenchmark: ${dims} dimensions, ${iterations} iterations`);
173
+ console.log(`SIMD: ${simd.isNative() ? 'Native' : 'JavaScript fallback'}`);
174
+ console.log(`Capabilities: ${simd.capabilities().join(', ')}`);
175
+ console.log('');
176
+
177
+ // Dot product benchmark
178
+ let start = Date.now();
179
+ for (let i = 0; i < iterations; i++) {
180
+ simd.dotProduct(a, b);
181
+ }
182
+ let elapsed = Date.now() - start;
183
+ console.log(`Dot Product: ${elapsed}ms (${(iterations / elapsed * 1000).toFixed(0)} ops/sec)`);
184
+
185
+ // Cosine similarity benchmark
186
+ start = Date.now();
187
+ for (let i = 0; i < iterations; i++) {
188
+ simd.cosineSimilarity(a, b);
189
+ }
190
+ elapsed = Date.now() - start;
191
+ console.log(`Cosine Similarity: ${elapsed}ms (${(iterations / elapsed * 1000).toFixed(0)} ops/sec)`);
192
+
193
+ // L2 distance benchmark
194
+ start = Date.now();
195
+ for (let i = 0; i < iterations; i++) {
196
+ simd.l2Distance(a, b);
197
+ }
198
+ elapsed = Date.now() - start;
199
+ console.log(`L2 Distance: ${elapsed}ms (${(iterations / elapsed * 1000).toFixed(0)} ops/sec)`);
200
+
201
+ // Softmax benchmark
202
+ start = Date.now();
203
+ for (let i = 0; i < iterations; i++) {
204
+ simd.softmax(a);
205
+ }
206
+ elapsed = Date.now() - start;
207
+ console.log(`Softmax: ${elapsed}ms (${(iterations / elapsed * 1000).toFixed(0)} ops/sec)`);
208
+ }
209
+
210
+ async function runInfo(flags) {
211
+ const llm = new RuvLLM();
212
+
213
+ const info = {
214
+ version: version(),
215
+ native: llm.isNativeLoaded(),
216
+ simd: hasSimdSupport(),
217
+ capabilities: llm.simdCapabilities(),
218
+ platform: process.platform,
219
+ arch: process.arch,
220
+ nodeVersion: process.version,
221
+ };
222
+
223
+ if (flags.json) {
224
+ console.log(formatJson(info));
225
+ } else {
226
+ console.log('\nRuvLLM Info:');
227
+ console.log(formatTable({
228
+ 'Version': info.version,
229
+ 'Native Module': info.native ? 'Loaded' : 'Fallback (JS)',
230
+ 'SIMD Support': info.simd ? 'Yes' : 'No',
231
+ 'Capabilities': info.capabilities.join(', '),
232
+ 'Platform': `${info.platform}-${info.arch}`,
233
+ 'Node.js': info.nodeVersion,
234
+ }));
235
+ }
236
+ }
237
+
238
+ function printHelp() {
239
+ console.log(`
240
+ RuvLLM - Self-learning LLM Orchestration
241
+
242
+ Usage: ruvllm <command> [options]
243
+
244
+ Commands:
245
+ query <text> Query the LLM with automatic routing
246
+ generate <prompt> Generate text with SIMD inference
247
+ route <text> Get routing decision for query
248
+ memory add <content> Add content to memory
249
+ memory search <query> Search memory for similar content
250
+ embed <text> Get embedding for text
251
+ similarity <t1> <t2> Compute similarity between texts
252
+ stats Show engine statistics
253
+ benchmark Run SIMD performance benchmark
254
+ info Show system information
255
+ help Show this help message
256
+
257
+ Options:
258
+ --json Output as JSON
259
+ --temperature <float> Sampling temperature (0.0-2.0)
260
+ --max-tokens <int> Maximum tokens to generate
261
+ --top-p <float> Nucleus sampling (0.0-1.0)
262
+ --top-k <int> Top-k sampling
263
+ --k <int> Number of results for search
264
+ --metadata <json> Metadata for memory add
265
+ --dims <int> Dimensions for benchmark (default: 768)
266
+ --iterations <int> Iterations for benchmark (default: 1000)
267
+
268
+ Examples:
269
+ ruvllm query "What is machine learning?"
270
+ ruvllm generate "Write a poem about AI" --temperature 0.9
271
+ ruvllm memory add "Important context" --metadata '{"type":"note"}'
272
+ ruvllm memory search "context" --k 5
273
+ ruvllm similarity "hello world" "hi there"
274
+ ruvllm benchmark --dims 1024 --iterations 5000
275
+
276
+ Learn more: https://github.com/ruvnet/ruvector
277
+ `);
278
+ }
279
+
280
+ // Main
281
+ async function main() {
282
+ const parsed = parseArgs(args);
283
+ const { command, positional, flags } = parsed;
284
+
285
+ if (!command || command === 'help' || flags.help) {
286
+ printHelp();
287
+ return;
288
+ }
289
+
290
+ // Create engine for commands that need it
291
+ const llm = new RuvLLM({
292
+ embeddingDim: flags.dim ? parseInt(flags.dim) : 768,
293
+ learningEnabled: flags['no-learning'] ? false : true,
294
+ });
295
+
296
+ try {
297
+ switch (command) {
298
+ case 'query':
299
+ if (!positional[0]) {
300
+ console.error('Error: query text required');
301
+ process.exit(1);
302
+ }
303
+ await runQuery(llm, positional[0], flags);
304
+ break;
305
+
306
+ case 'generate':
307
+ if (!positional[0]) {
308
+ console.error('Error: prompt required');
309
+ process.exit(1);
310
+ }
311
+ await runGenerate(llm, positional[0], flags);
312
+ break;
313
+
314
+ case 'route':
315
+ if (!positional[0]) {
316
+ console.error('Error: text required');
317
+ process.exit(1);
318
+ }
319
+ await runRoute(llm, positional[0], flags);
320
+ break;
321
+
322
+ case 'memory':
323
+ const subcommand = positional[0];
324
+ if (subcommand === 'add') {
325
+ if (!positional[1]) {
326
+ console.error('Error: content required');
327
+ process.exit(1);
328
+ }
329
+ await runMemoryAdd(llm, positional[1], flags);
330
+ } else if (subcommand === 'search') {
331
+ if (!positional[1]) {
332
+ console.error('Error: query required');
333
+ process.exit(1);
334
+ }
335
+ await runMemorySearch(llm, positional[1], flags);
336
+ } else {
337
+ console.error('Error: unknown memory subcommand. Use "add" or "search"');
338
+ process.exit(1);
339
+ }
340
+ break;
341
+
342
+ case 'embed':
343
+ if (!positional[0]) {
344
+ console.error('Error: text required');
345
+ process.exit(1);
346
+ }
347
+ await runEmbed(llm, positional[0], flags);
348
+ break;
349
+
350
+ case 'similarity':
351
+ if (!positional[0] || !positional[1]) {
352
+ console.error('Error: two texts required');
353
+ process.exit(1);
354
+ }
355
+ await runSimilarity(llm, positional[0], positional[1], flags);
356
+ break;
357
+
358
+ case 'stats':
359
+ await runStats(llm, flags);
360
+ break;
361
+
362
+ case 'benchmark':
363
+ await runBenchmark(flags);
364
+ break;
365
+
366
+ case 'info':
367
+ await runInfo(flags);
368
+ break;
369
+
370
+ default:
371
+ console.error(`Unknown command: ${command}`);
372
+ console.error('Run "ruvllm help" for usage information.');
373
+ process.exit(1);
374
+ }
375
+ } catch (error) {
376
+ console.error('Error:', error.message);
377
+ if (flags.verbose) {
378
+ console.error(error.stack);
379
+ }
380
+ process.exit(1);
381
+ }
382
+ }
383
+
384
+ main().catch(err => {
385
+ console.error('Fatal error:', err);
386
+ process.exit(1);
387
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * RuvLLM Engine - Main orchestrator for self-learning LLM
3
+ */
4
+ import { RuvLLMConfig, GenerationConfig, QueryResponse, RoutingDecision, MemoryResult, RuvLLMStats, Feedback, Embedding, BatchQueryRequest, BatchQueryResponse } from './types';
5
+ /**
6
+ * RuvLLM - Self-learning LLM orchestrator
7
+ *
8
+ * Combines SONA adaptive learning with HNSW memory,
9
+ * FastGRNN routing, and SIMD-optimized inference.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { RuvLLM } from '@ruvector/ruvllm';
14
+ *
15
+ * const llm = new RuvLLM({ embeddingDim: 768 });
16
+ *
17
+ * // Query with automatic routing
18
+ * const response = await llm.query('What is machine learning?');
19
+ * console.log(response.text);
20
+ *
21
+ * // Provide feedback for learning
22
+ * llm.feedback({ requestId: response.requestId, rating: 5 });
23
+ * ```
24
+ */
25
+ export declare class RuvLLM {
26
+ private native;
27
+ private config;
28
+ private fallbackState;
29
+ /**
30
+ * Create a new RuvLLM instance
31
+ */
32
+ constructor(config?: RuvLLMConfig);
33
+ /**
34
+ * Query the LLM with automatic routing
35
+ */
36
+ query(text: string, config?: GenerationConfig): QueryResponse;
37
+ /**
38
+ * Generate text with SIMD-optimized inference
39
+ */
40
+ generate(prompt: string, config?: GenerationConfig): string;
41
+ /**
42
+ * Get routing decision for a query
43
+ */
44
+ route(text: string): RoutingDecision;
45
+ /**
46
+ * Search memory for similar content
47
+ */
48
+ searchMemory(text: string, k?: number): MemoryResult[];
49
+ /**
50
+ * Add content to memory
51
+ */
52
+ addMemory(content: string, metadata?: Record<string, unknown>): number;
53
+ /**
54
+ * Provide feedback for learning
55
+ */
56
+ feedback(fb: Feedback): boolean;
57
+ /**
58
+ * Get engine statistics
59
+ */
60
+ stats(): RuvLLMStats;
61
+ /**
62
+ * Force router learning cycle
63
+ */
64
+ forceLearn(): string;
65
+ /**
66
+ * Get embedding for text
67
+ */
68
+ embed(text: string): Embedding;
69
+ /**
70
+ * Compute similarity between two texts
71
+ */
72
+ similarity(text1: string, text2: string): number;
73
+ /**
74
+ * Check if SIMD is available
75
+ */
76
+ hasSimd(): boolean;
77
+ /**
78
+ * Get SIMD capabilities
79
+ */
80
+ simdCapabilities(): string[];
81
+ /**
82
+ * Batch query multiple prompts
83
+ */
84
+ batchQuery(request: BatchQueryRequest): BatchQueryResponse;
85
+ /**
86
+ * Check if native module is loaded
87
+ */
88
+ isNativeLoaded(): boolean;
89
+ }
90
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AA0CjB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,aAAa,CAInB;IAEF;;OAEG;gBACS,MAAM,CAAC,EAAE,YAAY;IAajC;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,aAAa;IAyB7D;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,MAAM;IAS3D;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAsBpC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,SAAK,GAAG,YAAY,EAAE;IAsBlD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;IAetE;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO;IAO/B;;OAEG;IACH,KAAK,IAAI,WAAW;IAwBpB;;OAEG;IACH,UAAU,IAAI,MAAM;IAOpB;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAmB9B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAyBhD;;OAEG;IACH,OAAO,IAAI,OAAO;IAOlB;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAO5B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,kBAAkB;IAS1D;;OAEG;IACH,cAAc,IAAI,OAAO;CAG1B"}