@danielsimonjr/memory-mcp 11.0.1 → 11.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.
- package/LICENSE +22 -22
- package/dist/core/EntityManager.d.ts +10 -15
- package/dist/core/EntityManager.d.ts.map +1 -1
- package/dist/core/EntityManager.js +21 -54
- package/dist/core/GraphStorage.d.ts +0 -51
- package/dist/core/GraphStorage.d.ts.map +1 -1
- package/dist/core/GraphStorage.js +2 -79
- package/dist/core/GraphTraversal.d.ts +2 -7
- package/dist/core/GraphTraversal.d.ts.map +1 -1
- package/dist/core/GraphTraversal.js +2 -19
- package/dist/core/ManagerContext.d.ts +0 -4
- package/dist/core/ManagerContext.d.ts.map +1 -1
- package/dist/core/ManagerContext.js +2 -12
- package/dist/core/RelationManager.d.ts.map +1 -1
- package/dist/core/RelationManager.js +4 -5
- package/dist/core/SQLiteStorage.d.ts.map +1 -1
- package/dist/core/SQLiteStorage.js +2 -3
- package/dist/core/TransactionManager.d.ts +2 -207
- package/dist/core/TransactionManager.d.ts.map +1 -1
- package/dist/core/TransactionManager.js +6 -482
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -3
- package/dist/features/ArchiveManager.d.ts +2 -14
- package/dist/features/ArchiveManager.d.ts.map +1 -1
- package/dist/features/ArchiveManager.js +3 -44
- package/dist/features/CompressionManager.d.ts +4 -14
- package/dist/features/CompressionManager.d.ts.map +1 -1
- package/dist/features/CompressionManager.js +9 -74
- package/dist/features/IOManager.d.ts +2 -6
- package/dist/features/IOManager.d.ts.map +1 -1
- package/dist/features/IOManager.js +10 -105
- package/dist/features/StreamingExporter.d.ts +4 -27
- package/dist/features/StreamingExporter.d.ts.map +1 -1
- package/dist/features/StreamingExporter.js +4 -65
- package/dist/features/index.d.ts +0 -2
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +0 -3
- package/dist/search/EmbeddingService.d.ts +9 -108
- package/dist/search/EmbeddingService.d.ts.map +1 -1
- package/dist/search/EmbeddingService.js +15 -187
- package/dist/search/FuzzySearch.js +1 -1
- package/dist/search/SavedSearchManager.d.ts.map +1 -1
- package/dist/search/SavedSearchManager.js +2 -3
- package/dist/search/SearchManager.d.ts +1 -42
- package/dist/search/SearchManager.d.ts.map +1 -1
- package/dist/search/SearchManager.js +0 -115
- package/dist/search/SemanticSearch.d.ts +1 -4
- package/dist/search/SemanticSearch.d.ts.map +1 -1
- package/dist/search/SemanticSearch.js +2 -12
- package/dist/search/TFIDFIndexManager.d.ts +0 -88
- package/dist/search/TFIDFIndexManager.d.ts.map +1 -1
- package/dist/search/TFIDFIndexManager.js +0 -217
- package/dist/search/index.d.ts +1 -18
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -32
- package/dist/server/MCPServer.d.ts.map +1 -1
- package/dist/server/MCPServer.js +4 -1
- package/dist/server/responseCompressor.js +5 -5
- package/dist/server/toolDefinitions.d.ts.map +1 -1
- package/dist/server/toolDefinitions.js +5 -1
- package/dist/server/toolHandlers.d.ts +9 -5
- package/dist/server/toolHandlers.d.ts.map +1 -1
- package/dist/server/toolHandlers.js +23 -8
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +2 -579
- package/dist/types/types.d.ts.map +1 -1
- package/dist/utils/compressedCache.d.ts +0 -29
- package/dist/utils/compressedCache.d.ts.map +1 -1
- package/dist/utils/compressedCache.js +0 -39
- package/dist/utils/entityUtils.d.ts +1 -59
- package/dist/utils/entityUtils.d.ts.map +1 -1
- package/dist/utils/entityUtils.js +3 -113
- package/dist/utils/errors.d.ts +0 -18
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +0 -24
- package/dist/utils/index.d.ts +2 -6
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -14
- package/dist/utils/logger.d.ts +0 -7
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -9
- package/dist/utils/parallelUtils.d.ts +1 -5
- package/dist/utils/parallelUtils.d.ts.map +1 -1
- package/dist/utils/parallelUtils.js +1 -23
- package/dist/utils/schemas.d.ts +16 -16
- package/dist/utils/schemas.d.ts.map +1 -1
- package/dist/utils/schemas.js +12 -12
- package/dist/utils/taskScheduler.d.ts +0 -4
- package/dist/utils/taskScheduler.d.ts.map +1 -1
- package/dist/utils/taskScheduler.js +1 -21
- package/dist/workers/WorkerPool.d.ts +81 -0
- package/dist/workers/WorkerPool.d.ts.map +1 -0
- package/dist/workers/WorkerPool.js +121 -0
- package/dist/workers/index.d.ts +1 -1
- package/dist/workers/index.d.ts.map +1 -1
- package/dist/workers/levenshteinWorker.js +1 -1
- package/package.json +1 -4
- package/dist/__tests__/file-path.test.js +0 -119
- package/dist/__tests__/knowledge-graph.test.js +0 -318
- package/dist/core/GraphEventEmitter.d.ts +0 -202
- package/dist/core/GraphEventEmitter.d.ts.map +0 -1
- package/dist/core/GraphEventEmitter.js +0 -346
- package/dist/features/KeywordExtractor.d.ts +0 -61
- package/dist/features/KeywordExtractor.d.ts.map +0 -1
- package/dist/features/KeywordExtractor.js +0 -126
- package/dist/features/ObservationNormalizer.d.ts +0 -90
- package/dist/features/ObservationNormalizer.d.ts.map +0 -1
- package/dist/features/ObservationNormalizer.js +0 -193
- package/dist/memory.jsonl +0 -1
- package/dist/search/BM25Search.d.ts +0 -148
- package/dist/search/BM25Search.d.ts.map +0 -1
- package/dist/search/BM25Search.js +0 -339
- package/dist/search/EarlyTerminationManager.d.ts +0 -140
- package/dist/search/EarlyTerminationManager.d.ts.map +0 -1
- package/dist/search/EarlyTerminationManager.js +0 -279
- package/dist/search/EmbeddingCache.d.ts +0 -175
- package/dist/search/EmbeddingCache.d.ts.map +0 -1
- package/dist/search/EmbeddingCache.js +0 -246
- package/dist/search/HybridScorer.d.ts +0 -181
- package/dist/search/HybridScorer.d.ts.map +0 -1
- package/dist/search/HybridScorer.js +0 -257
- package/dist/search/HybridSearchManager.d.ts +0 -80
- package/dist/search/HybridSearchManager.d.ts.map +0 -1
- package/dist/search/HybridSearchManager.js +0 -187
- package/dist/search/IncrementalIndexer.d.ts +0 -201
- package/dist/search/IncrementalIndexer.d.ts.map +0 -1
- package/dist/search/IncrementalIndexer.js +0 -342
- package/dist/search/OptimizedInvertedIndex.d.ts +0 -163
- package/dist/search/OptimizedInvertedIndex.d.ts.map +0 -1
- package/dist/search/OptimizedInvertedIndex.js +0 -358
- package/dist/search/ParallelSearchExecutor.d.ts +0 -172
- package/dist/search/ParallelSearchExecutor.d.ts.map +0 -1
- package/dist/search/ParallelSearchExecutor.js +0 -309
- package/dist/search/QuantizedVectorStore.d.ts +0 -171
- package/dist/search/QuantizedVectorStore.d.ts.map +0 -1
- package/dist/search/QuantizedVectorStore.js +0 -307
- package/dist/search/QueryAnalyzer.d.ts +0 -76
- package/dist/search/QueryAnalyzer.d.ts.map +0 -1
- package/dist/search/QueryAnalyzer.js +0 -227
- package/dist/search/QueryCostEstimator.d.ts +0 -244
- package/dist/search/QueryCostEstimator.d.ts.map +0 -1
- package/dist/search/QueryCostEstimator.js +0 -652
- package/dist/search/QueryPlanCache.d.ts +0 -220
- package/dist/search/QueryPlanCache.d.ts.map +0 -1
- package/dist/search/QueryPlanCache.js +0 -379
- package/dist/search/QueryPlanner.d.ts +0 -58
- package/dist/search/QueryPlanner.d.ts.map +0 -1
- package/dist/search/QueryPlanner.js +0 -137
- package/dist/search/ReflectionManager.d.ts +0 -120
- package/dist/search/ReflectionManager.d.ts.map +0 -1
- package/dist/search/ReflectionManager.js +0 -231
- package/dist/search/SymbolicSearch.d.ts +0 -61
- package/dist/search/SymbolicSearch.d.ts.map +0 -1
- package/dist/search/SymbolicSearch.js +0 -163
- package/dist/search/TFIDFEventSync.d.ts +0 -85
- package/dist/search/TFIDFEventSync.d.ts.map +0 -1
- package/dist/search/TFIDFEventSync.js +0 -133
- package/dist/utils/BatchProcessor.d.ts +0 -271
- package/dist/utils/BatchProcessor.d.ts.map +0 -1
- package/dist/utils/BatchProcessor.js +0 -376
- package/dist/utils/MemoryMonitor.d.ts +0 -176
- package/dist/utils/MemoryMonitor.d.ts.map +0 -1
- package/dist/utils/MemoryMonitor.js +0 -305
- package/dist/utils/WorkerPoolManager.d.ts +0 -233
- package/dist/utils/WorkerPoolManager.d.ts.map +0 -1
- package/dist/utils/WorkerPoolManager.js +0 -420
- package/dist/utils/operationUtils.d.ts +0 -124
- package/dist/utils/operationUtils.d.ts.map +0 -1
- package/dist/utils/operationUtils.js +0 -175
- package/dist/vitest.config.js +0 -13
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { IOManager } from '../features/IOManager.js';
|
|
11
11
|
import { KnowledgeGraphError } from '../utils/errors.js';
|
|
12
|
-
import { checkCancellation, createProgressReporter, createProgress, sanitizeObject } from '../utils/index.js';
|
|
13
12
|
/**
|
|
14
13
|
* Types of operations that can be performed in a transaction.
|
|
15
14
|
*/
|
|
@@ -192,11 +191,7 @@ export class TransactionManager {
|
|
|
192
191
|
* Creates a backup before applying changes. If any operation fails,
|
|
193
192
|
* automatically rolls back to the pre-transaction state.
|
|
194
193
|
*
|
|
195
|
-
* Phase 9B: Supports progress tracking and cancellation via LongRunningOperationOptions.
|
|
196
|
-
*
|
|
197
|
-
* @param options - Optional progress/cancellation options (Phase 9B)
|
|
198
194
|
* @returns Promise resolving to transaction result
|
|
199
|
-
* @throws {OperationCancelledError} If operation is cancelled via signal (Phase 9B)
|
|
200
195
|
*
|
|
201
196
|
* @example
|
|
202
197
|
* ```typescript
|
|
@@ -210,53 +205,27 @@ export class TransactionManager {
|
|
|
210
205
|
* } else {
|
|
211
206
|
* console.error(`Transaction failed: ${result.error}`);
|
|
212
207
|
* }
|
|
213
|
-
*
|
|
214
|
-
* // With progress tracking (Phase 9B)
|
|
215
|
-
* const result = await txManager.commit({
|
|
216
|
-
* onProgress: (p) => console.log(`${p.percentage}% complete`),
|
|
217
|
-
* });
|
|
218
208
|
* ```
|
|
219
209
|
*/
|
|
220
|
-
async commit(
|
|
210
|
+
async commit() {
|
|
221
211
|
this.ensureInTransaction();
|
|
222
|
-
// Setup progress reporter
|
|
223
|
-
const reportProgress = createProgressReporter(options?.onProgress);
|
|
224
|
-
const totalOperations = this.operations.length;
|
|
225
|
-
reportProgress?.(createProgress(0, 100, 'commit'));
|
|
226
212
|
try {
|
|
227
|
-
//
|
|
228
|
-
checkCancellation(options?.signal, 'commit');
|
|
229
|
-
// Phase 1: Create backup for rollback (0-20% progress)
|
|
230
|
-
reportProgress?.(createProgress(5, 100, 'creating backup'));
|
|
213
|
+
// Create backup for rollback
|
|
231
214
|
const backupResult = await this.ioManager.createBackup({
|
|
232
215
|
description: 'Transaction backup (auto-created)',
|
|
233
216
|
});
|
|
234
217
|
this.transactionBackup = backupResult.path;
|
|
235
|
-
//
|
|
236
|
-
checkCancellation(options?.signal, 'commit');
|
|
237
|
-
reportProgress?.(createProgress(20, 100, 'backup created'));
|
|
238
|
-
// Phase 2: Load graph (20-30% progress)
|
|
239
|
-
reportProgress?.(createProgress(25, 100, 'loading graph'));
|
|
218
|
+
// Load mutable copy of graph for transaction
|
|
240
219
|
const graph = await this.storage.getGraphForMutation();
|
|
241
220
|
const timestamp = new Date().toISOString();
|
|
242
|
-
|
|
243
|
-
// Phase 3: Apply all operations (30-80% progress)
|
|
221
|
+
// Apply all operations
|
|
244
222
|
let operationsExecuted = 0;
|
|
245
223
|
for (const operation of this.operations) {
|
|
246
|
-
// Check for cancellation between operations
|
|
247
|
-
checkCancellation(options?.signal, 'commit');
|
|
248
224
|
this.applyOperation(graph, operation, timestamp);
|
|
249
225
|
operationsExecuted++;
|
|
250
|
-
// Map operation progress (0-100%) to overall progress (30-80%)
|
|
251
|
-
const opProgress = totalOperations > 0 ? Math.round(30 + (operationsExecuted / totalOperations) * 50) : 80;
|
|
252
|
-
reportProgress?.(createProgress(opProgress, 100, 'applying operations'));
|
|
253
226
|
}
|
|
254
|
-
//
|
|
255
|
-
checkCancellation(options?.signal, 'commit');
|
|
256
|
-
// Phase 4: Save the modified graph (80-95% progress)
|
|
257
|
-
reportProgress?.(createProgress(85, 100, 'saving graph'));
|
|
227
|
+
// Save the modified graph
|
|
258
228
|
await this.storage.saveGraph(graph);
|
|
259
|
-
reportProgress?.(createProgress(95, 100, 'graph saved'));
|
|
260
229
|
// Clean up transaction state
|
|
261
230
|
this.inTransaction = false;
|
|
262
231
|
this.operations = [];
|
|
@@ -265,8 +234,6 @@ export class TransactionManager {
|
|
|
265
234
|
await this.ioManager.deleteBackup(this.transactionBackup);
|
|
266
235
|
this.transactionBackup = undefined;
|
|
267
236
|
}
|
|
268
|
-
// Report completion
|
|
269
|
-
reportProgress?.(createProgress(100, 100, 'commit'));
|
|
270
237
|
return {
|
|
271
238
|
success: true,
|
|
272
239
|
operationsExecuted,
|
|
@@ -377,8 +344,7 @@ export class TransactionManager {
|
|
|
377
344
|
if (!entity) {
|
|
378
345
|
throw new KnowledgeGraphError(`Entity "${name}" not found`, 'ENTITY_NOT_FOUND');
|
|
379
346
|
}
|
|
380
|
-
|
|
381
|
-
Object.assign(entity, sanitizeObject(updates));
|
|
347
|
+
Object.assign(entity, updates);
|
|
382
348
|
entity.lastModified = timestamp;
|
|
383
349
|
break;
|
|
384
350
|
}
|
|
@@ -424,445 +390,3 @@ export class TransactionManager {
|
|
|
424
390
|
}
|
|
425
391
|
}
|
|
426
392
|
}
|
|
427
|
-
// ==================== Phase 10 Sprint 1: BatchTransaction ====================
|
|
428
|
-
/**
|
|
429
|
-
* Phase 10 Sprint 1: Fluent API for building and executing batch transactions.
|
|
430
|
-
*
|
|
431
|
-
* BatchTransaction provides a builder pattern for accumulating multiple
|
|
432
|
-
* graph operations and executing them atomically in a single transaction.
|
|
433
|
-
* This reduces I/O overhead and ensures consistency across related changes.
|
|
434
|
-
*
|
|
435
|
-
* @example
|
|
436
|
-
* ```typescript
|
|
437
|
-
* const storage = new GraphStorage('/data/memory.jsonl');
|
|
438
|
-
* const batch = new BatchTransaction(storage);
|
|
439
|
-
*
|
|
440
|
-
* // Build the batch with fluent API
|
|
441
|
-
* const result = await batch
|
|
442
|
-
* .createEntity({ name: 'Alice', entityType: 'person', observations: ['Developer'] })
|
|
443
|
-
* .createEntity({ name: 'Bob', entityType: 'person', observations: ['Designer'] })
|
|
444
|
-
* .createRelation({ from: 'Alice', to: 'Bob', relationType: 'knows' })
|
|
445
|
-
* .updateEntity('Alice', { importance: 8 })
|
|
446
|
-
* .execute();
|
|
447
|
-
*
|
|
448
|
-
* if (result.success) {
|
|
449
|
-
* console.log(`Batch completed: ${result.operationsExecuted} operations in ${result.executionTimeMs}ms`);
|
|
450
|
-
* }
|
|
451
|
-
* ```
|
|
452
|
-
*/
|
|
453
|
-
export class BatchTransaction {
|
|
454
|
-
operations = [];
|
|
455
|
-
storage;
|
|
456
|
-
/**
|
|
457
|
-
* Create a new BatchTransaction instance.
|
|
458
|
-
*
|
|
459
|
-
* @param storage - GraphStorage instance to execute operations against
|
|
460
|
-
*/
|
|
461
|
-
constructor(storage) {
|
|
462
|
-
this.storage = storage;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Add a create entity operation to the batch.
|
|
466
|
-
*
|
|
467
|
-
* @param entity - Entity to create (without timestamps)
|
|
468
|
-
* @returns This BatchTransaction for chaining
|
|
469
|
-
*
|
|
470
|
-
* @example
|
|
471
|
-
* ```typescript
|
|
472
|
-
* batch.createEntity({
|
|
473
|
-
* name: 'Alice',
|
|
474
|
-
* entityType: 'person',
|
|
475
|
-
* observations: ['Software engineer'],
|
|
476
|
-
* importance: 8
|
|
477
|
-
* });
|
|
478
|
-
* ```
|
|
479
|
-
*/
|
|
480
|
-
createEntity(entity) {
|
|
481
|
-
this.operations.push({ type: 'createEntity', data: entity });
|
|
482
|
-
return this;
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Add an update entity operation to the batch.
|
|
486
|
-
*
|
|
487
|
-
* @param name - Name of entity to update
|
|
488
|
-
* @param updates - Partial entity updates
|
|
489
|
-
* @returns This BatchTransaction for chaining
|
|
490
|
-
*
|
|
491
|
-
* @example
|
|
492
|
-
* ```typescript
|
|
493
|
-
* batch.updateEntity('Alice', { importance: 9 });
|
|
494
|
-
* ```
|
|
495
|
-
*/
|
|
496
|
-
updateEntity(name, updates) {
|
|
497
|
-
this.operations.push({ type: 'updateEntity', data: { name, updates } });
|
|
498
|
-
return this;
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Add a delete entity operation to the batch.
|
|
502
|
-
*
|
|
503
|
-
* @param name - Name of entity to delete
|
|
504
|
-
* @returns This BatchTransaction for chaining
|
|
505
|
-
*
|
|
506
|
-
* @example
|
|
507
|
-
* ```typescript
|
|
508
|
-
* batch.deleteEntity('OldEntity');
|
|
509
|
-
* ```
|
|
510
|
-
*/
|
|
511
|
-
deleteEntity(name) {
|
|
512
|
-
this.operations.push({ type: 'deleteEntity', data: { name } });
|
|
513
|
-
return this;
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Add a create relation operation to the batch.
|
|
517
|
-
*
|
|
518
|
-
* @param relation - Relation to create (without timestamps)
|
|
519
|
-
* @returns This BatchTransaction for chaining
|
|
520
|
-
*
|
|
521
|
-
* @example
|
|
522
|
-
* ```typescript
|
|
523
|
-
* batch.createRelation({
|
|
524
|
-
* from: 'Alice',
|
|
525
|
-
* to: 'Bob',
|
|
526
|
-
* relationType: 'mentors'
|
|
527
|
-
* });
|
|
528
|
-
* ```
|
|
529
|
-
*/
|
|
530
|
-
createRelation(relation) {
|
|
531
|
-
this.operations.push({ type: 'createRelation', data: relation });
|
|
532
|
-
return this;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* Add a delete relation operation to the batch.
|
|
536
|
-
*
|
|
537
|
-
* @param from - Source entity name
|
|
538
|
-
* @param to - Target entity name
|
|
539
|
-
* @param relationType - Type of relation
|
|
540
|
-
* @returns This BatchTransaction for chaining
|
|
541
|
-
*
|
|
542
|
-
* @example
|
|
543
|
-
* ```typescript
|
|
544
|
-
* batch.deleteRelation('Alice', 'Bob', 'mentors');
|
|
545
|
-
* ```
|
|
546
|
-
*/
|
|
547
|
-
deleteRelation(from, to, relationType) {
|
|
548
|
-
this.operations.push({ type: 'deleteRelation', data: { from, to, relationType } });
|
|
549
|
-
return this;
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Add observations to an existing entity.
|
|
553
|
-
*
|
|
554
|
-
* @param name - Name of entity to add observations to
|
|
555
|
-
* @param observations - Observations to add
|
|
556
|
-
* @returns This BatchTransaction for chaining
|
|
557
|
-
*
|
|
558
|
-
* @example
|
|
559
|
-
* ```typescript
|
|
560
|
-
* batch.addObservations('Alice', ['Knows TypeScript', 'Leads team']);
|
|
561
|
-
* ```
|
|
562
|
-
*/
|
|
563
|
-
addObservations(name, observations) {
|
|
564
|
-
this.operations.push({ type: 'addObservations', data: { name, observations } });
|
|
565
|
-
return this;
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* Delete observations from an existing entity.
|
|
569
|
-
*
|
|
570
|
-
* @param name - Name of entity to delete observations from
|
|
571
|
-
* @param observations - Observations to delete
|
|
572
|
-
* @returns This BatchTransaction for chaining
|
|
573
|
-
*
|
|
574
|
-
* @example
|
|
575
|
-
* ```typescript
|
|
576
|
-
* batch.deleteObservations('Alice', ['Old fact']);
|
|
577
|
-
* ```
|
|
578
|
-
*/
|
|
579
|
-
deleteObservations(name, observations) {
|
|
580
|
-
this.operations.push({ type: 'deleteObservations', data: { name, observations } });
|
|
581
|
-
return this;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Add multiple operations from an array.
|
|
585
|
-
*
|
|
586
|
-
* @param operations - Array of batch operations
|
|
587
|
-
* @returns This BatchTransaction for chaining
|
|
588
|
-
*
|
|
589
|
-
* @example
|
|
590
|
-
* ```typescript
|
|
591
|
-
* batch.addOperations([
|
|
592
|
-
* { type: 'createEntity', data: { name: 'A', entityType: 'x', observations: [] } },
|
|
593
|
-
* { type: 'createEntity', data: { name: 'B', entityType: 'x', observations: [] } }
|
|
594
|
-
* ]);
|
|
595
|
-
* ```
|
|
596
|
-
*/
|
|
597
|
-
addOperations(operations) {
|
|
598
|
-
this.operations.push(...operations);
|
|
599
|
-
return this;
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Get the number of operations in this batch.
|
|
603
|
-
*
|
|
604
|
-
* @returns Number of operations queued
|
|
605
|
-
*/
|
|
606
|
-
size() {
|
|
607
|
-
return this.operations.length;
|
|
608
|
-
}
|
|
609
|
-
/**
|
|
610
|
-
* Clear all operations from the batch.
|
|
611
|
-
*
|
|
612
|
-
* @returns This BatchTransaction for chaining
|
|
613
|
-
*/
|
|
614
|
-
clear() {
|
|
615
|
-
this.operations = [];
|
|
616
|
-
return this;
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Get a copy of the operations in this batch.
|
|
620
|
-
*
|
|
621
|
-
* @returns Array of batch operations
|
|
622
|
-
*/
|
|
623
|
-
getOperations() {
|
|
624
|
-
return [...this.operations];
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
|
-
* Execute all operations in the batch atomically.
|
|
628
|
-
*
|
|
629
|
-
* All operations are applied within a single transaction. If any
|
|
630
|
-
* operation fails, all changes are rolled back (when stopOnError is true).
|
|
631
|
-
*
|
|
632
|
-
* @param options - Batch execution options
|
|
633
|
-
* @returns Promise resolving to batch result
|
|
634
|
-
*
|
|
635
|
-
* @example
|
|
636
|
-
* ```typescript
|
|
637
|
-
* const result = await batch.execute();
|
|
638
|
-
* if (result.success) {
|
|
639
|
-
* console.log(`Created ${result.entitiesCreated} entities`);
|
|
640
|
-
* } else {
|
|
641
|
-
* console.error(`Failed at operation ${result.failedOperationIndex}: ${result.error}`);
|
|
642
|
-
* }
|
|
643
|
-
* ```
|
|
644
|
-
*/
|
|
645
|
-
async execute(options = {}) {
|
|
646
|
-
const startTime = Date.now();
|
|
647
|
-
const { stopOnError = true, validateBeforeExecute = true } = options;
|
|
648
|
-
const result = {
|
|
649
|
-
success: true,
|
|
650
|
-
operationsExecuted: 0,
|
|
651
|
-
entitiesCreated: 0,
|
|
652
|
-
entitiesUpdated: 0,
|
|
653
|
-
entitiesDeleted: 0,
|
|
654
|
-
relationsCreated: 0,
|
|
655
|
-
relationsDeleted: 0,
|
|
656
|
-
executionTimeMs: 0,
|
|
657
|
-
};
|
|
658
|
-
if (this.operations.length === 0) {
|
|
659
|
-
result.executionTimeMs = Date.now() - startTime;
|
|
660
|
-
return result;
|
|
661
|
-
}
|
|
662
|
-
// Load graph for mutation
|
|
663
|
-
const graph = await this.storage.getGraphForMutation();
|
|
664
|
-
const timestamp = new Date().toISOString();
|
|
665
|
-
// Optional: Validate all operations before executing
|
|
666
|
-
if (validateBeforeExecute) {
|
|
667
|
-
const validationError = this.validateOperations(graph);
|
|
668
|
-
if (validationError) {
|
|
669
|
-
return {
|
|
670
|
-
...result,
|
|
671
|
-
success: false,
|
|
672
|
-
error: validationError.message,
|
|
673
|
-
failedOperationIndex: validationError.index,
|
|
674
|
-
executionTimeMs: Date.now() - startTime,
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
// Execute operations
|
|
679
|
-
for (let i = 0; i < this.operations.length; i++) {
|
|
680
|
-
const operation = this.operations[i];
|
|
681
|
-
try {
|
|
682
|
-
this.applyBatchOperation(graph, operation, timestamp, result);
|
|
683
|
-
result.operationsExecuted++;
|
|
684
|
-
}
|
|
685
|
-
catch (error) {
|
|
686
|
-
result.success = false;
|
|
687
|
-
result.error = error instanceof Error ? error.message : String(error);
|
|
688
|
-
result.failedOperationIndex = i;
|
|
689
|
-
if (stopOnError) {
|
|
690
|
-
result.executionTimeMs = Date.now() - startTime;
|
|
691
|
-
return result;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
// Save the modified graph if successful (or if stopOnError is false)
|
|
696
|
-
if (result.success || !stopOnError) {
|
|
697
|
-
try {
|
|
698
|
-
await this.storage.saveGraph(graph);
|
|
699
|
-
}
|
|
700
|
-
catch (error) {
|
|
701
|
-
result.success = false;
|
|
702
|
-
result.error = `Failed to save graph: ${error instanceof Error ? error.message : String(error)}`;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
result.executionTimeMs = Date.now() - startTime;
|
|
706
|
-
return result;
|
|
707
|
-
}
|
|
708
|
-
/**
|
|
709
|
-
* Validate all operations before executing.
|
|
710
|
-
* @private
|
|
711
|
-
*/
|
|
712
|
-
validateOperations(graph) {
|
|
713
|
-
const entityNames = new Set(graph.entities.map(e => e.name));
|
|
714
|
-
const pendingCreates = new Set();
|
|
715
|
-
const pendingDeletes = new Set();
|
|
716
|
-
for (let i = 0; i < this.operations.length; i++) {
|
|
717
|
-
const op = this.operations[i];
|
|
718
|
-
switch (op.type) {
|
|
719
|
-
case 'createEntity': {
|
|
720
|
-
const name = op.data.name;
|
|
721
|
-
if (entityNames.has(name) && !pendingDeletes.has(name)) {
|
|
722
|
-
return { message: `Entity "${name}" already exists`, index: i };
|
|
723
|
-
}
|
|
724
|
-
if (pendingCreates.has(name)) {
|
|
725
|
-
return { message: `Duplicate create for entity "${name}" in batch`, index: i };
|
|
726
|
-
}
|
|
727
|
-
pendingCreates.add(name);
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
case 'updateEntity':
|
|
731
|
-
case 'addObservations':
|
|
732
|
-
case 'deleteObservations': {
|
|
733
|
-
const name = op.data.name;
|
|
734
|
-
const exists = (entityNames.has(name) || pendingCreates.has(name)) && !pendingDeletes.has(name);
|
|
735
|
-
if (!exists) {
|
|
736
|
-
return { message: `Entity "${name}" not found`, index: i };
|
|
737
|
-
}
|
|
738
|
-
break;
|
|
739
|
-
}
|
|
740
|
-
case 'deleteEntity': {
|
|
741
|
-
const name = op.data.name;
|
|
742
|
-
const exists = (entityNames.has(name) || pendingCreates.has(name)) && !pendingDeletes.has(name);
|
|
743
|
-
if (!exists) {
|
|
744
|
-
return { message: `Entity "${name}" not found for deletion`, index: i };
|
|
745
|
-
}
|
|
746
|
-
pendingDeletes.add(name);
|
|
747
|
-
break;
|
|
748
|
-
}
|
|
749
|
-
case 'createRelation': {
|
|
750
|
-
const { from, to } = op.data;
|
|
751
|
-
const fromExists = (entityNames.has(from) || pendingCreates.has(from)) && !pendingDeletes.has(from);
|
|
752
|
-
const toExists = (entityNames.has(to) || pendingCreates.has(to)) && !pendingDeletes.has(to);
|
|
753
|
-
if (!fromExists) {
|
|
754
|
-
return { message: `Source entity "${from}" not found for relation`, index: i };
|
|
755
|
-
}
|
|
756
|
-
if (!toExists) {
|
|
757
|
-
return { message: `Target entity "${to}" not found for relation`, index: i };
|
|
758
|
-
}
|
|
759
|
-
break;
|
|
760
|
-
}
|
|
761
|
-
case 'deleteRelation': {
|
|
762
|
-
// Relations are validated at execution time
|
|
763
|
-
break;
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return null;
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Apply a single batch operation to the graph.
|
|
771
|
-
* @private
|
|
772
|
-
*/
|
|
773
|
-
applyBatchOperation(graph, operation, timestamp, result) {
|
|
774
|
-
switch (operation.type) {
|
|
775
|
-
case 'createEntity': {
|
|
776
|
-
const entity = {
|
|
777
|
-
...operation.data,
|
|
778
|
-
createdAt: timestamp,
|
|
779
|
-
lastModified: timestamp,
|
|
780
|
-
};
|
|
781
|
-
if (graph.entities.some(e => e.name === entity.name)) {
|
|
782
|
-
throw new KnowledgeGraphError(`Entity "${entity.name}" already exists`, 'DUPLICATE_ENTITY');
|
|
783
|
-
}
|
|
784
|
-
graph.entities.push(entity);
|
|
785
|
-
result.entitiesCreated++;
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
case 'updateEntity': {
|
|
789
|
-
const { name, updates } = operation.data;
|
|
790
|
-
const entity = graph.entities.find(e => e.name === name);
|
|
791
|
-
if (!entity) {
|
|
792
|
-
throw new KnowledgeGraphError(`Entity "${name}" not found`, 'ENTITY_NOT_FOUND');
|
|
793
|
-
}
|
|
794
|
-
// Sanitize updates to prevent prototype pollution
|
|
795
|
-
Object.assign(entity, sanitizeObject(updates));
|
|
796
|
-
entity.lastModified = timestamp;
|
|
797
|
-
result.entitiesUpdated++;
|
|
798
|
-
break;
|
|
799
|
-
}
|
|
800
|
-
case 'deleteEntity': {
|
|
801
|
-
const { name } = operation.data;
|
|
802
|
-
const index = graph.entities.findIndex(e => e.name === name);
|
|
803
|
-
if (index === -1) {
|
|
804
|
-
throw new KnowledgeGraphError(`Entity "${name}" not found`, 'ENTITY_NOT_FOUND');
|
|
805
|
-
}
|
|
806
|
-
graph.entities.splice(index, 1);
|
|
807
|
-
// Delete related relations
|
|
808
|
-
graph.relations = graph.relations.filter(r => r.from !== name && r.to !== name);
|
|
809
|
-
result.entitiesDeleted++;
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
case 'createRelation': {
|
|
813
|
-
const relation = {
|
|
814
|
-
...operation.data,
|
|
815
|
-
createdAt: timestamp,
|
|
816
|
-
lastModified: timestamp,
|
|
817
|
-
};
|
|
818
|
-
const exists = graph.relations.some(r => r.from === relation.from && r.to === relation.to && r.relationType === relation.relationType);
|
|
819
|
-
if (exists) {
|
|
820
|
-
throw new KnowledgeGraphError(`Relation "${relation.from}" -> "${relation.to}" (${relation.relationType}) already exists`, 'DUPLICATE_RELATION');
|
|
821
|
-
}
|
|
822
|
-
graph.relations.push(relation);
|
|
823
|
-
result.relationsCreated++;
|
|
824
|
-
break;
|
|
825
|
-
}
|
|
826
|
-
case 'deleteRelation': {
|
|
827
|
-
const { from, to, relationType } = operation.data;
|
|
828
|
-
const index = graph.relations.findIndex(r => r.from === from && r.to === to && r.relationType === relationType);
|
|
829
|
-
if (index === -1) {
|
|
830
|
-
throw new KnowledgeGraphError(`Relation "${from}" -> "${to}" (${relationType}) not found`, 'RELATION_NOT_FOUND');
|
|
831
|
-
}
|
|
832
|
-
graph.relations.splice(index, 1);
|
|
833
|
-
result.relationsDeleted++;
|
|
834
|
-
break;
|
|
835
|
-
}
|
|
836
|
-
case 'addObservations': {
|
|
837
|
-
const { name, observations } = operation.data;
|
|
838
|
-
const entity = graph.entities.find(e => e.name === name);
|
|
839
|
-
if (!entity) {
|
|
840
|
-
throw new KnowledgeGraphError(`Entity "${name}" not found`, 'ENTITY_NOT_FOUND');
|
|
841
|
-
}
|
|
842
|
-
// Add only new observations
|
|
843
|
-
const existingSet = new Set(entity.observations);
|
|
844
|
-
const newObs = observations.filter((o) => !existingSet.has(o));
|
|
845
|
-
entity.observations.push(...newObs);
|
|
846
|
-
entity.lastModified = timestamp;
|
|
847
|
-
result.entitiesUpdated++;
|
|
848
|
-
break;
|
|
849
|
-
}
|
|
850
|
-
case 'deleteObservations': {
|
|
851
|
-
const { name, observations } = operation.data;
|
|
852
|
-
const entity = graph.entities.find(e => e.name === name);
|
|
853
|
-
if (!entity) {
|
|
854
|
-
throw new KnowledgeGraphError(`Entity "${name}" not found`, 'ENTITY_NOT_FOUND');
|
|
855
|
-
}
|
|
856
|
-
const toDelete = new Set(observations);
|
|
857
|
-
entity.observations = entity.observations.filter((o) => !toDelete.has(o));
|
|
858
|
-
entity.lastModified = timestamp;
|
|
859
|
-
result.entitiesUpdated++;
|
|
860
|
-
break;
|
|
861
|
-
}
|
|
862
|
-
default: {
|
|
863
|
-
const _exhaustiveCheck = operation;
|
|
864
|
-
throw new KnowledgeGraphError(`Unknown batch operation type: ${_exhaustiveCheck.type}`, 'UNKNOWN_OPERATION');
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -11,7 +11,6 @@ export { HierarchyManager } from './HierarchyManager.js';
|
|
|
11
11
|
export { ManagerContext } from './ManagerContext.js';
|
|
12
12
|
export { GraphTraversal } from './GraphTraversal.js';
|
|
13
13
|
export { ManagerContext as KnowledgeGraphManager } from './ManagerContext.js';
|
|
14
|
-
export { TransactionManager, OperationType,
|
|
14
|
+
export { TransactionManager, OperationType, type TransactionOperation, type TransactionResult, } from './TransactionManager.js';
|
|
15
15
|
export { createStorage, createStorageFromPath } from './StorageFactory.js';
|
|
16
|
-
export { GraphEventEmitter } from './GraphEventEmitter.js';
|
|
17
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -13,7 +13,5 @@ export { ManagerContext } from './ManagerContext.js';
|
|
|
13
13
|
export { GraphTraversal } from './GraphTraversal.js';
|
|
14
14
|
// Backward compatibility alias
|
|
15
15
|
export { ManagerContext as KnowledgeGraphManager } from './ManagerContext.js';
|
|
16
|
-
export { TransactionManager, OperationType,
|
|
16
|
+
export { TransactionManager, OperationType, } from './TransactionManager.js';
|
|
17
17
|
export { createStorage, createStorageFromPath } from './StorageFactory.js';
|
|
18
|
-
// Phase 10 Sprint 2: Graph change events
|
|
19
|
-
export { GraphEventEmitter } from './GraphEventEmitter.js';
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module features/ArchiveManager
|
|
10
10
|
*/
|
|
11
|
-
import type { LongRunningOperationOptions } from '../types/index.js';
|
|
12
11
|
import type { GraphStorage } from '../core/GraphStorage.js';
|
|
13
12
|
/**
|
|
14
13
|
* Criteria for archiving entities.
|
|
@@ -23,9 +22,8 @@ export interface ArchiveCriteria {
|
|
|
23
22
|
}
|
|
24
23
|
/**
|
|
25
24
|
* Options for archive operations.
|
|
26
|
-
* Phase 9B: Extended with LongRunningOperationOptions.
|
|
27
25
|
*/
|
|
28
|
-
export interface ArchiveOptions
|
|
26
|
+
export interface ArchiveOptions {
|
|
29
27
|
/** Dry run mode - preview without making changes */
|
|
30
28
|
dryRun?: boolean;
|
|
31
29
|
/** Whether to save archived entities to a compressed file (default: true) */
|
|
@@ -71,12 +69,9 @@ export declare class ArchiveManager {
|
|
|
71
69
|
* being removed from the active graph. Use `saveToFile: false` to
|
|
72
70
|
* skip creating the archive file.
|
|
73
71
|
*
|
|
74
|
-
* Phase 9B: Supports progress tracking and cancellation via options.
|
|
75
|
-
*
|
|
76
72
|
* @param criteria - Archiving criteria
|
|
77
|
-
* @param options - Archive options (dryRun, saveToFile
|
|
73
|
+
* @param options - Archive options (dryRun, saveToFile)
|
|
78
74
|
* @returns Archive result with count, entity names, and compression stats
|
|
79
|
-
* @throws {OperationCancelledError} If operation is cancelled via signal (Phase 9B)
|
|
80
75
|
*
|
|
81
76
|
* @example
|
|
82
77
|
* ```typescript
|
|
@@ -90,13 +85,6 @@ export declare class ArchiveManager {
|
|
|
90
85
|
*
|
|
91
86
|
* // Preview without making changes
|
|
92
87
|
* const preview = await manager.archiveEntities(criteria, { dryRun: true });
|
|
93
|
-
*
|
|
94
|
-
* // With progress tracking and cancellation (Phase 9B)
|
|
95
|
-
* const controller = new AbortController();
|
|
96
|
-
* const result = await manager.archiveEntities(criteria, {
|
|
97
|
-
* signal: controller.signal,
|
|
98
|
-
* onProgress: (p) => console.log(`${p.percentage}% complete`),
|
|
99
|
-
* });
|
|
100
88
|
* ```
|
|
101
89
|
*/
|
|
102
90
|
archiveEntities(criteria: ArchiveCriteria, options?: ArchiveOptions | boolean): Promise<ArchiveResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArchiveManager.d.ts","sourceRoot":"","sources":["../../src/features/ArchiveManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"ArchiveManager.d.ts","sourceRoot":"","sources":["../../src/features/ArchiveManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IAGb,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEhB,OAAO,EAAE,YAAY;IAMzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACG,eAAe,CACnB,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,cAAc,GAAG,OAAY,GACrC,OAAO,CAAC,aAAa,CAAC;IA+FzB;;;;;;;;OAQG;YACW,aAAa;IAmD3B;;;;OAIG;IACG,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;QAClC,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,OAAO,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC,CAAC;IA6DH;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|