agentic-qe 2.5.5 → 2.5.6
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/CHANGELOG.md +70 -0
- package/README.md +1 -1
- package/dist/adapters/MemoryStoreAdapter.d.ts +75 -123
- package/dist/adapters/MemoryStoreAdapter.d.ts.map +1 -1
- package/dist/adapters/MemoryStoreAdapter.js +204 -219
- package/dist/adapters/MemoryStoreAdapter.js.map +1 -1
- package/dist/agents/AccessibilityAllyAgent.d.ts.map +1 -1
- package/dist/agents/AccessibilityAllyAgent.js +17 -1
- package/dist/agents/AccessibilityAllyAgent.js.map +1 -1
- package/dist/agents/BaseAgent.d.ts +18 -250
- package/dist/agents/BaseAgent.d.ts.map +1 -1
- package/dist/agents/BaseAgent.js +122 -520
- package/dist/agents/BaseAgent.js.map +1 -1
- package/dist/agents/utils/generators.d.ts +30 -0
- package/dist/agents/utils/generators.d.ts.map +1 -0
- package/dist/agents/utils/generators.js +44 -0
- package/dist/agents/utils/generators.js.map +1 -0
- package/dist/agents/utils/index.d.ts +10 -0
- package/dist/agents/utils/index.d.ts.map +1 -0
- package/dist/agents/utils/index.js +19 -0
- package/dist/agents/utils/index.js.map +1 -0
- package/dist/agents/utils/validation.d.ts +72 -0
- package/dist/agents/utils/validation.d.ts.map +1 -0
- package/dist/agents/utils/validation.js +75 -0
- package/dist/agents/utils/validation.js.map +1 -0
- package/dist/core/memory/HNSWVectorMemory.js +1 -1
- package/dist/core/memory/SwarmMemoryManager.d.ts +114 -90
- package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
- package/dist/core/memory/SwarmMemoryManager.js +277 -235
- package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
- package/dist/learning/baselines/StandardTaskSuite.d.ts.map +1 -1
- package/dist/learning/baselines/StandardTaskSuite.js +38 -0
- package/dist/learning/baselines/StandardTaskSuite.js.map +1 -1
- package/dist/mcp/server-instructions.d.ts +1 -1
- package/dist/mcp/server-instructions.js +1 -1
- package/dist/types/memory-interfaces.d.ts +76 -68
- package/dist/types/memory-interfaces.d.ts.map +1 -1
- package/dist/types/memory-interfaces.js +3 -0
- package/dist/types/memory-interfaces.js.map +1 -1
- package/package.json +1 -1
|
@@ -52,8 +52,15 @@ const types_1 = require("../../types");
|
|
|
52
52
|
/**
|
|
53
53
|
* SwarmMemoryManager - Manages persistent memory for agent swarm coordination
|
|
54
54
|
*
|
|
55
|
+
* IMPORTANT: This class uses better-sqlite3 which is intentionally synchronous.
|
|
56
|
+
* All database operations are synchronous for maximum performance.
|
|
57
|
+
* Only initialize() is async due to filesystem operations.
|
|
58
|
+
*
|
|
59
|
+
* Issue #65: Converted from misleading async/await pattern to honest synchronous API.
|
|
60
|
+
* See: https://github.com/proffesor-for-testing/agentic-qe/issues/65
|
|
61
|
+
*
|
|
55
62
|
* Features:
|
|
56
|
-
* - SQLite-based persistent storage with 12-table schema
|
|
63
|
+
* - SQLite-based persistent storage with 12-table schema (SYNCHRONOUS)
|
|
57
64
|
* - Partitioned key-value store
|
|
58
65
|
* - TTL-based expiration with different policies per table
|
|
59
66
|
* - Hint/blackboard pattern support
|
|
@@ -136,7 +143,8 @@ class SwarmMemoryManager {
|
|
|
136
143
|
throw new Error(`Failed to create database connection: ${error}`);
|
|
137
144
|
}
|
|
138
145
|
// Create memory entries table with access control fields
|
|
139
|
-
|
|
146
|
+
// Note: All this.run() calls are synchronous (better-sqlite3)
|
|
147
|
+
this.run(`
|
|
140
148
|
CREATE TABLE IF NOT EXISTS memory_entries (
|
|
141
149
|
key TEXT NOT NULL,
|
|
142
150
|
partition TEXT NOT NULL DEFAULT 'default',
|
|
@@ -152,7 +160,7 @@ class SwarmMemoryManager {
|
|
|
152
160
|
)
|
|
153
161
|
`);
|
|
154
162
|
// Create ACL table for advanced permissions
|
|
155
|
-
|
|
163
|
+
this.run(`
|
|
156
164
|
CREATE TABLE IF NOT EXISTS memory_acl (
|
|
157
165
|
resource_id TEXT PRIMARY KEY,
|
|
158
166
|
owner TEXT NOT NULL,
|
|
@@ -166,7 +174,7 @@ class SwarmMemoryManager {
|
|
|
166
174
|
)
|
|
167
175
|
`);
|
|
168
176
|
// Create hints table for blackboard pattern
|
|
169
|
-
|
|
177
|
+
this.run(`
|
|
170
178
|
CREATE TABLE IF NOT EXISTS hints (
|
|
171
179
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
172
180
|
key TEXT NOT NULL,
|
|
@@ -176,7 +184,7 @@ class SwarmMemoryManager {
|
|
|
176
184
|
)
|
|
177
185
|
`);
|
|
178
186
|
// Table 3: Events (TTL: 30 days)
|
|
179
|
-
|
|
187
|
+
this.run(`
|
|
180
188
|
CREATE TABLE IF NOT EXISTS events (
|
|
181
189
|
id TEXT PRIMARY KEY,
|
|
182
190
|
type TEXT NOT NULL,
|
|
@@ -188,7 +196,7 @@ class SwarmMemoryManager {
|
|
|
188
196
|
)
|
|
189
197
|
`);
|
|
190
198
|
// Table 4: Workflow State (TTL: never expires)
|
|
191
|
-
|
|
199
|
+
this.run(`
|
|
192
200
|
CREATE TABLE IF NOT EXISTS workflow_state (
|
|
193
201
|
id TEXT PRIMARY KEY,
|
|
194
202
|
step TEXT NOT NULL,
|
|
@@ -202,7 +210,7 @@ class SwarmMemoryManager {
|
|
|
202
210
|
`);
|
|
203
211
|
// Table 5: Patterns (TTL: 7 days)
|
|
204
212
|
// Issue #79: Added domain and success_rate columns for learning persistence
|
|
205
|
-
|
|
213
|
+
this.run(`
|
|
206
214
|
CREATE TABLE IF NOT EXISTS patterns (
|
|
207
215
|
id TEXT PRIMARY KEY,
|
|
208
216
|
pattern TEXT NOT NULL UNIQUE,
|
|
@@ -223,31 +231,31 @@ class SwarmMemoryManager {
|
|
|
223
231
|
const tableInfo = this.queryAll(`PRAGMA table_info(patterns)`);
|
|
224
232
|
const columnNames = tableInfo.map(col => col.name);
|
|
225
233
|
if (!columnNames.includes('agent_id')) {
|
|
226
|
-
|
|
234
|
+
this.run(`ALTER TABLE patterns ADD COLUMN agent_id TEXT`);
|
|
227
235
|
}
|
|
228
236
|
// Issue #79: Add domain column for learning persistence
|
|
229
237
|
if (!columnNames.includes('domain')) {
|
|
230
|
-
|
|
238
|
+
this.run(`ALTER TABLE patterns ADD COLUMN domain TEXT DEFAULT 'general'`);
|
|
231
239
|
}
|
|
232
240
|
// Issue #79: Add success_rate column for learning persistence
|
|
233
241
|
if (!columnNames.includes('success_rate')) {
|
|
234
|
-
|
|
242
|
+
this.run(`ALTER TABLE patterns ADD COLUMN success_rate REAL DEFAULT 1.0`);
|
|
235
243
|
}
|
|
236
244
|
}
|
|
237
245
|
catch (e) {
|
|
238
246
|
// Ignore errors - columns might already exist
|
|
239
247
|
}
|
|
240
248
|
// Create indexes for O(log n) pattern queries (Issue #57)
|
|
241
|
-
|
|
249
|
+
this.run(`
|
|
242
250
|
CREATE INDEX IF NOT EXISTS idx_patterns_agent_confidence
|
|
243
251
|
ON patterns(agent_id, confidence DESC)
|
|
244
252
|
`);
|
|
245
|
-
|
|
253
|
+
this.run(`
|
|
246
254
|
CREATE INDEX IF NOT EXISTS idx_patterns_agent
|
|
247
255
|
ON patterns(agent_id)
|
|
248
256
|
`);
|
|
249
257
|
// Table 6: Consensus State (TTL: 7 days)
|
|
250
|
-
|
|
258
|
+
this.run(`
|
|
251
259
|
CREATE TABLE IF NOT EXISTS consensus_state (
|
|
252
260
|
id TEXT PRIMARY KEY,
|
|
253
261
|
decision TEXT NOT NULL,
|
|
@@ -262,7 +270,7 @@ class SwarmMemoryManager {
|
|
|
262
270
|
)
|
|
263
271
|
`);
|
|
264
272
|
// Table 7: Performance Metrics
|
|
265
|
-
|
|
273
|
+
this.run(`
|
|
266
274
|
CREATE TABLE IF NOT EXISTS performance_metrics (
|
|
267
275
|
id TEXT PRIMARY KEY,
|
|
268
276
|
metric TEXT NOT NULL,
|
|
@@ -273,7 +281,7 @@ class SwarmMemoryManager {
|
|
|
273
281
|
)
|
|
274
282
|
`);
|
|
275
283
|
// Table 8: Artifacts (TTL: never expires)
|
|
276
|
-
|
|
284
|
+
this.run(`
|
|
277
285
|
CREATE TABLE IF NOT EXISTS artifacts (
|
|
278
286
|
id TEXT PRIMARY KEY,
|
|
279
287
|
kind TEXT NOT NULL,
|
|
@@ -286,7 +294,7 @@ class SwarmMemoryManager {
|
|
|
286
294
|
)
|
|
287
295
|
`);
|
|
288
296
|
// Table 9: Sessions (for resumability)
|
|
289
|
-
|
|
297
|
+
this.run(`
|
|
290
298
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
291
299
|
id TEXT PRIMARY KEY,
|
|
292
300
|
mode TEXT NOT NULL,
|
|
@@ -297,7 +305,7 @@ class SwarmMemoryManager {
|
|
|
297
305
|
)
|
|
298
306
|
`);
|
|
299
307
|
// Table 10: Agent Registry
|
|
300
|
-
|
|
308
|
+
this.run(`
|
|
301
309
|
CREATE TABLE IF NOT EXISTS agent_registry (
|
|
302
310
|
id TEXT PRIMARY KEY,
|
|
303
311
|
type TEXT NOT NULL,
|
|
@@ -309,7 +317,7 @@ class SwarmMemoryManager {
|
|
|
309
317
|
)
|
|
310
318
|
`);
|
|
311
319
|
// Table 11: GOAP State
|
|
312
|
-
|
|
320
|
+
this.run(`
|
|
313
321
|
CREATE TABLE IF NOT EXISTS goap_goals (
|
|
314
322
|
id TEXT PRIMARY KEY,
|
|
315
323
|
conditions TEXT NOT NULL,
|
|
@@ -318,7 +326,7 @@ class SwarmMemoryManager {
|
|
|
318
326
|
created_at INTEGER NOT NULL
|
|
319
327
|
)
|
|
320
328
|
`);
|
|
321
|
-
|
|
329
|
+
this.run(`
|
|
322
330
|
CREATE TABLE IF NOT EXISTS goap_actions (
|
|
323
331
|
id TEXT PRIMARY KEY,
|
|
324
332
|
preconditions TEXT NOT NULL,
|
|
@@ -328,7 +336,7 @@ class SwarmMemoryManager {
|
|
|
328
336
|
created_at INTEGER NOT NULL
|
|
329
337
|
)
|
|
330
338
|
`);
|
|
331
|
-
|
|
339
|
+
this.run(`
|
|
332
340
|
CREATE TABLE IF NOT EXISTS goap_plans (
|
|
333
341
|
id TEXT PRIMARY KEY,
|
|
334
342
|
goal_id TEXT NOT NULL,
|
|
@@ -338,7 +346,7 @@ class SwarmMemoryManager {
|
|
|
338
346
|
)
|
|
339
347
|
`);
|
|
340
348
|
// Table 12: OODA Cycles
|
|
341
|
-
|
|
349
|
+
this.run(`
|
|
342
350
|
CREATE TABLE IF NOT EXISTS ooda_cycles (
|
|
343
351
|
id TEXT PRIMARY KEY,
|
|
344
352
|
phase TEXT NOT NULL,
|
|
@@ -352,29 +360,29 @@ class SwarmMemoryManager {
|
|
|
352
360
|
)
|
|
353
361
|
`);
|
|
354
362
|
// Create indexes for performance
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
363
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_memory_partition ON memory_entries(partition)`);
|
|
364
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_memory_expires ON memory_entries(expires_at)`);
|
|
365
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_memory_owner ON memory_entries(owner)`);
|
|
366
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_memory_access ON memory_entries(access_level)`);
|
|
367
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_hints_key ON hints(key)`);
|
|
368
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_hints_expires ON hints(expires_at)`);
|
|
369
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_acl_owner ON memory_acl(owner)`);
|
|
370
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_events_type ON events(type)`);
|
|
371
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_events_source ON events(source)`);
|
|
372
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_events_expires ON events(expires_at)`);
|
|
373
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_workflow_status ON workflow_state(status)`);
|
|
374
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_patterns_confidence ON patterns(confidence)`);
|
|
375
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_patterns_expires ON patterns(expires_at)`);
|
|
376
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_consensus_status ON consensus_state(status)`);
|
|
377
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_consensus_expires ON consensus_state(expires_at)`);
|
|
378
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_metrics_metric ON performance_metrics(metric)`);
|
|
379
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_metrics_agent ON performance_metrics(agent_id)`);
|
|
380
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_artifacts_kind ON artifacts(kind)`);
|
|
381
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_agent_status ON agent_registry(status)`);
|
|
382
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_ooda_phase ON ooda_cycles(phase)`);
|
|
375
383
|
// Table 13: Q-values (Q-learning)
|
|
376
384
|
// Issue #79: Added metadata column for learning persistence
|
|
377
|
-
|
|
385
|
+
this.run(`
|
|
378
386
|
CREATE TABLE IF NOT EXISTS q_values (
|
|
379
387
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
380
388
|
agent_id TEXT NOT NULL,
|
|
@@ -392,7 +400,7 @@ class SwarmMemoryManager {
|
|
|
392
400
|
try {
|
|
393
401
|
const qvTableInfo = this.queryAll(`PRAGMA table_info(q_values)`);
|
|
394
402
|
if (!qvTableInfo.some(col => col.name === 'metadata')) {
|
|
395
|
-
|
|
403
|
+
this.run(`ALTER TABLE q_values ADD COLUMN metadata TEXT`);
|
|
396
404
|
}
|
|
397
405
|
}
|
|
398
406
|
catch (e) {
|
|
@@ -400,7 +408,7 @@ class SwarmMemoryManager {
|
|
|
400
408
|
}
|
|
401
409
|
// Table 14: Learning Experiences
|
|
402
410
|
// Issue #79: Added metadata and created_at columns for learning persistence
|
|
403
|
-
|
|
411
|
+
this.run(`
|
|
404
412
|
CREATE TABLE IF NOT EXISTS learning_experiences (
|
|
405
413
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
406
414
|
agent_id TEXT NOT NULL,
|
|
@@ -421,17 +429,17 @@ class SwarmMemoryManager {
|
|
|
421
429
|
const leTableInfo = this.queryAll(`PRAGMA table_info(learning_experiences)`);
|
|
422
430
|
const leColumnNames = leTableInfo.map(col => col.name);
|
|
423
431
|
if (!leColumnNames.includes('metadata')) {
|
|
424
|
-
|
|
432
|
+
this.run(`ALTER TABLE learning_experiences ADD COLUMN metadata TEXT`);
|
|
425
433
|
}
|
|
426
434
|
if (!leColumnNames.includes('created_at')) {
|
|
427
|
-
|
|
435
|
+
this.run(`ALTER TABLE learning_experiences ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP`);
|
|
428
436
|
}
|
|
429
437
|
}
|
|
430
438
|
catch (e) {
|
|
431
439
|
// Ignore errors - columns might already exist
|
|
432
440
|
}
|
|
433
441
|
// Table 15: Learning History (snapshots and metrics)
|
|
434
|
-
|
|
442
|
+
this.run(`
|
|
435
443
|
CREATE TABLE IF NOT EXISTS learning_history (
|
|
436
444
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
437
445
|
agent_id TEXT NOT NULL,
|
|
@@ -446,7 +454,7 @@ class SwarmMemoryManager {
|
|
|
446
454
|
)
|
|
447
455
|
`);
|
|
448
456
|
// Table 16: Learning Metrics (aggregated performance data)
|
|
449
|
-
|
|
457
|
+
this.run(`
|
|
450
458
|
CREATE TABLE IF NOT EXISTS learning_metrics (
|
|
451
459
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
452
460
|
agent_id TEXT NOT NULL,
|
|
@@ -458,27 +466,36 @@ class SwarmMemoryManager {
|
|
|
458
466
|
)
|
|
459
467
|
`);
|
|
460
468
|
// Learning indexes for performance
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
469
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_q_values_agent ON q_values(agent_id)`);
|
|
470
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_learning_exp_agent ON learning_experiences(agent_id)`);
|
|
471
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_learning_hist_agent ON learning_history(agent_id)`);
|
|
472
|
+
this.run(`CREATE INDEX IF NOT EXISTS idx_learning_metrics_agent ON learning_metrics(agent_id)`);
|
|
465
473
|
this.initialized = true;
|
|
466
474
|
}
|
|
467
475
|
/**
|
|
468
476
|
* Store a key-value pair in memory with OpenTelemetry instrumentation
|
|
469
477
|
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
478
|
+
* NOTE: This method is async only for auto-initialization. The actual DB
|
|
479
|
+
* operations are synchronous (better-sqlite3). For maximum performance,
|
|
480
|
+
* call initialize() first and use storeSync() instead.
|
|
472
481
|
*
|
|
473
482
|
* @param key - Memory key
|
|
474
483
|
* @param value - Value to store (will be JSON serialized)
|
|
475
484
|
* @param options - Store options including partition, TTL, access control
|
|
476
485
|
*/
|
|
477
486
|
async store(key, value, options = {}) {
|
|
478
|
-
// Auto-initialize if not initialized
|
|
487
|
+
// Auto-initialize if not initialized (only async part)
|
|
479
488
|
if (!this.initialized) {
|
|
480
489
|
await this.initialize();
|
|
481
490
|
}
|
|
491
|
+
// Delegate to sync implementation
|
|
492
|
+
this.storeSync(key, value, options);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Synchronous store operation - use when already initialized
|
|
496
|
+
* Issue #65: Honest synchronous API for better-sqlite3
|
|
497
|
+
*/
|
|
498
|
+
storeSync(key, value, options = {}) {
|
|
482
499
|
if (!this.db) {
|
|
483
500
|
throw new Error('Memory manager not initialized. Call initialize() first.');
|
|
484
501
|
}
|
|
@@ -501,7 +518,7 @@ class SwarmMemoryManager {
|
|
|
501
518
|
const expiresAt = options.ttl ? createdAt + (options.ttl * 1000) : null;
|
|
502
519
|
const metadata = options.metadata ? JSON.stringify(options.metadata) : null;
|
|
503
520
|
// Check write permission if updating existing entry
|
|
504
|
-
const existing =
|
|
521
|
+
const existing = this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
505
522
|
if (existing && options.owner) {
|
|
506
523
|
// Verify write permission
|
|
507
524
|
const permCheck = this.accessControl.checkPermission({
|
|
@@ -518,7 +535,7 @@ class SwarmMemoryManager {
|
|
|
518
535
|
throw new AccessControl_1.AccessControlError(`Write denied: ${permCheck.reason}`);
|
|
519
536
|
}
|
|
520
537
|
}
|
|
521
|
-
|
|
538
|
+
this.run(`INSERT OR REPLACE INTO memory_entries
|
|
522
539
|
(key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id)
|
|
523
540
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
524
541
|
key,
|
|
@@ -564,6 +581,17 @@ class SwarmMemoryManager {
|
|
|
564
581
|
}
|
|
565
582
|
return this.store(key, value, options);
|
|
566
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Synchronous set - use when already initialized
|
|
586
|
+
*/
|
|
587
|
+
setSync(key, value, options = {}) {
|
|
588
|
+
if (typeof options === 'string') {
|
|
589
|
+
this.storeSync(key, value, { partition: options });
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
this.storeSync(key, value, options);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
567
595
|
/**
|
|
568
596
|
* Alias for retrieve() method to maintain compatibility
|
|
569
597
|
* Supports both options object and partition string
|
|
@@ -575,21 +603,37 @@ class SwarmMemoryManager {
|
|
|
575
603
|
}
|
|
576
604
|
return this.retrieve(key, options);
|
|
577
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Synchronous get - use when already initialized
|
|
608
|
+
*/
|
|
609
|
+
getSync(key, options = {}) {
|
|
610
|
+
if (typeof options === 'string') {
|
|
611
|
+
return this.retrieveSync(key, { partition: options });
|
|
612
|
+
}
|
|
613
|
+
return this.retrieveSync(key, options);
|
|
614
|
+
}
|
|
578
615
|
/**
|
|
579
616
|
* Retrieve a value from memory with OpenTelemetry instrumentation
|
|
580
617
|
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
618
|
+
* NOTE: This method is async only for auto-initialization. For maximum
|
|
619
|
+
* performance, call initialize() first and use retrieveSync() instead.
|
|
583
620
|
*
|
|
584
621
|
* @param key - Memory key
|
|
585
622
|
* @param options - Retrieve options including partition, agentId for access control
|
|
586
623
|
* @returns Retrieved value or null if not found
|
|
587
624
|
*/
|
|
588
625
|
async retrieve(key, options = {}) {
|
|
589
|
-
// Auto-initialize if not initialized
|
|
626
|
+
// Auto-initialize if not initialized (only async part)
|
|
590
627
|
if (!this.initialized) {
|
|
591
628
|
await this.initialize();
|
|
592
629
|
}
|
|
630
|
+
return this.retrieveSync(key, options);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Synchronous retrieve operation - use when already initialized
|
|
634
|
+
* Issue #65: Honest synchronous API for better-sqlite3
|
|
635
|
+
*/
|
|
636
|
+
retrieveSync(key, options = {}) {
|
|
593
637
|
if (!this.db) {
|
|
594
638
|
throw new Error('Memory manager not initialized. Call initialize() first.');
|
|
595
639
|
}
|
|
@@ -611,7 +655,7 @@ class SwarmMemoryManager {
|
|
|
611
655
|
query += ` AND (expires_at IS NULL OR expires_at > ?)`;
|
|
612
656
|
params.push(now);
|
|
613
657
|
}
|
|
614
|
-
const row =
|
|
658
|
+
const row = this.queryOne(query, params);
|
|
615
659
|
if (!row) {
|
|
616
660
|
// Complete span - not found
|
|
617
661
|
const durationMs = Date.now() - startTime;
|
|
@@ -662,15 +706,13 @@ class SwarmMemoryManager {
|
|
|
662
706
|
}
|
|
663
707
|
/**
|
|
664
708
|
* Query/search memory entries by pattern with OpenTelemetry instrumentation
|
|
665
|
-
*
|
|
666
|
-
* Automatically instruments the memory search operation with distributed tracing.
|
|
667
|
-
* Records namespace, search pattern, result count, and performance metrics.
|
|
709
|
+
* Issue #65: Converted to synchronous API
|
|
668
710
|
*
|
|
669
711
|
* @param pattern - SQL LIKE pattern for key matching
|
|
670
712
|
* @param options - Retrieve options including partition, agentId for access control
|
|
671
713
|
* @returns Array of matching memory entries
|
|
672
714
|
*/
|
|
673
|
-
|
|
715
|
+
query(pattern, options = {}) {
|
|
674
716
|
if (!this.db) {
|
|
675
717
|
throw new Error('Memory manager not initialized');
|
|
676
718
|
}
|
|
@@ -685,15 +727,15 @@ class SwarmMemoryManager {
|
|
|
685
727
|
const startTime = Date.now();
|
|
686
728
|
try {
|
|
687
729
|
const now = Date.now();
|
|
688
|
-
let
|
|
730
|
+
let queryStr = `SELECT key, value, partition, created_at, expires_at, owner, access_level, team_id, swarm_id
|
|
689
731
|
FROM memory_entries
|
|
690
732
|
WHERE partition = ? AND key LIKE ?`;
|
|
691
733
|
const params = [partition, pattern];
|
|
692
734
|
if (!options.includeExpired) {
|
|
693
|
-
|
|
735
|
+
queryStr += ` AND (expires_at IS NULL OR expires_at > ?)`;
|
|
694
736
|
params.push(now);
|
|
695
737
|
}
|
|
696
|
-
const rows =
|
|
738
|
+
const rows = this.queryAll(queryStr, params);
|
|
697
739
|
// Filter by access control if agentId provided
|
|
698
740
|
const filteredRows = options.agentId
|
|
699
741
|
? rows.filter((row) => {
|
|
@@ -751,7 +793,7 @@ class SwarmMemoryManager {
|
|
|
751
793
|
* @param partition - Memory partition (namespace)
|
|
752
794
|
* @param options - Delete options including agentId for access control
|
|
753
795
|
*/
|
|
754
|
-
|
|
796
|
+
delete(key, partition = 'default', options = {}) {
|
|
755
797
|
if (!this.db) {
|
|
756
798
|
throw new Error('Memory manager not initialized');
|
|
757
799
|
}
|
|
@@ -766,7 +808,7 @@ class SwarmMemoryManager {
|
|
|
766
808
|
try {
|
|
767
809
|
// Check delete permission if agentId provided
|
|
768
810
|
if (options.agentId) {
|
|
769
|
-
const row =
|
|
811
|
+
const row = this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
770
812
|
if (row) {
|
|
771
813
|
const permCheck = this.accessControl.checkPermission({
|
|
772
814
|
agentId: options.agentId,
|
|
@@ -784,10 +826,10 @@ class SwarmMemoryManager {
|
|
|
784
826
|
}
|
|
785
827
|
}
|
|
786
828
|
}
|
|
787
|
-
|
|
829
|
+
this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
788
830
|
// Clean up ACL if exists
|
|
789
831
|
const resourceId = `${partition}:${key}`;
|
|
790
|
-
|
|
832
|
+
this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]);
|
|
791
833
|
this.aclCache.delete(resourceId);
|
|
792
834
|
// Complete span successfully
|
|
793
835
|
const durationMs = Date.now() - startTime;
|
|
@@ -807,26 +849,26 @@ class SwarmMemoryManager {
|
|
|
807
849
|
throw error;
|
|
808
850
|
}
|
|
809
851
|
}
|
|
810
|
-
|
|
852
|
+
clear(partition = 'default') {
|
|
811
853
|
if (!this.db) {
|
|
812
854
|
throw new Error('Memory manager not initialized');
|
|
813
855
|
}
|
|
814
|
-
|
|
856
|
+
this.run(`DELETE FROM memory_entries WHERE partition = ?`, [partition]);
|
|
815
857
|
}
|
|
816
|
-
|
|
858
|
+
postHint(hint) {
|
|
817
859
|
if (!this.db) {
|
|
818
860
|
throw new Error('Memory manager not initialized');
|
|
819
861
|
}
|
|
820
862
|
const createdAt = Date.now();
|
|
821
863
|
const expiresAt = hint.ttl ? createdAt + (hint.ttl * 1000) : null;
|
|
822
|
-
|
|
864
|
+
this.run(`INSERT INTO hints (key, value, created_at, expires_at) VALUES (?, ?, ?, ?)`, [hint.key, JSON.stringify(hint.value), createdAt, expiresAt]);
|
|
823
865
|
}
|
|
824
|
-
|
|
866
|
+
readHints(pattern) {
|
|
825
867
|
if (!this.db) {
|
|
826
868
|
throw new Error('Memory manager not initialized');
|
|
827
869
|
}
|
|
828
870
|
const now = Date.now();
|
|
829
|
-
const rows =
|
|
871
|
+
const rows = this.queryAll(`SELECT key, value, created_at, expires_at
|
|
830
872
|
FROM hints
|
|
831
873
|
WHERE key LIKE ? AND (expires_at IS NULL OR expires_at > ?)
|
|
832
874
|
ORDER BY created_at DESC`, [pattern, now]);
|
|
@@ -837,50 +879,50 @@ class SwarmMemoryManager {
|
|
|
837
879
|
expiresAt: row.expires_at
|
|
838
880
|
}));
|
|
839
881
|
}
|
|
840
|
-
|
|
882
|
+
cleanExpired() {
|
|
841
883
|
if (!this.db) {
|
|
842
884
|
throw new Error('Memory manager not initialized');
|
|
843
885
|
}
|
|
844
886
|
const now = Date.now();
|
|
845
887
|
// Clean memory entries
|
|
846
|
-
|
|
888
|
+
this.run(`DELETE FROM memory_entries WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]);
|
|
847
889
|
// Clean hints
|
|
848
|
-
|
|
890
|
+
this.run(`DELETE FROM hints WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]);
|
|
849
891
|
// Clean events
|
|
850
|
-
|
|
892
|
+
this.run(`DELETE FROM events WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]);
|
|
851
893
|
// Clean patterns
|
|
852
|
-
|
|
894
|
+
this.run(`DELETE FROM patterns WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]);
|
|
853
895
|
// Clean consensus
|
|
854
|
-
|
|
896
|
+
this.run(`DELETE FROM consensus_state WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]);
|
|
855
897
|
return 0;
|
|
856
898
|
}
|
|
857
|
-
|
|
899
|
+
close() {
|
|
858
900
|
if (this.db) {
|
|
859
901
|
this.db.close();
|
|
860
902
|
this.db = null;
|
|
861
903
|
this.initialized = false;
|
|
862
904
|
}
|
|
863
905
|
}
|
|
864
|
-
|
|
906
|
+
stats() {
|
|
865
907
|
if (!this.db) {
|
|
866
908
|
throw new Error('Memory manager not initialized');
|
|
867
909
|
}
|
|
868
|
-
const entriesCount =
|
|
869
|
-
const hintsCount =
|
|
870
|
-
const eventsCount =
|
|
871
|
-
const workflowsCount =
|
|
872
|
-
const patternsCount =
|
|
873
|
-
const consensusCount =
|
|
874
|
-
const metricsCount =
|
|
875
|
-
const artifactsCount =
|
|
876
|
-
const sessionsCount =
|
|
877
|
-
const agentsCount =
|
|
878
|
-
const goapGoalsCount =
|
|
879
|
-
const goapActionsCount =
|
|
880
|
-
const goapPlansCount =
|
|
881
|
-
const oodaCyclesCount =
|
|
882
|
-
const partitionsResult =
|
|
883
|
-
const accessLevelsResult =
|
|
910
|
+
const entriesCount = this.queryOne(`SELECT COUNT(*) as count FROM memory_entries`);
|
|
911
|
+
const hintsCount = this.queryOne(`SELECT COUNT(*) as count FROM hints`);
|
|
912
|
+
const eventsCount = this.queryOne(`SELECT COUNT(*) as count FROM events`);
|
|
913
|
+
const workflowsCount = this.queryOne(`SELECT COUNT(*) as count FROM workflow_state`);
|
|
914
|
+
const patternsCount = this.queryOne(`SELECT COUNT(*) as count FROM patterns`);
|
|
915
|
+
const consensusCount = this.queryOne(`SELECT COUNT(*) as count FROM consensus_state`);
|
|
916
|
+
const metricsCount = this.queryOne(`SELECT COUNT(*) as count FROM performance_metrics`);
|
|
917
|
+
const artifactsCount = this.queryOne(`SELECT COUNT(*) as count FROM artifacts`);
|
|
918
|
+
const sessionsCount = this.queryOne(`SELECT COUNT(*) as count FROM sessions`);
|
|
919
|
+
const agentsCount = this.queryOne(`SELECT COUNT(*) as count FROM agent_registry`);
|
|
920
|
+
const goapGoalsCount = this.queryOne(`SELECT COUNT(*) as count FROM goap_goals`);
|
|
921
|
+
const goapActionsCount = this.queryOne(`SELECT COUNT(*) as count FROM goap_actions`);
|
|
922
|
+
const goapPlansCount = this.queryOne(`SELECT COUNT(*) as count FROM goap_plans`);
|
|
923
|
+
const oodaCyclesCount = this.queryOne(`SELECT COUNT(*) as count FROM ooda_cycles`);
|
|
924
|
+
const partitionsResult = this.queryAll(`SELECT DISTINCT partition FROM memory_entries`);
|
|
925
|
+
const accessLevelsResult = this.queryAll(`SELECT access_level, COUNT(*) as count FROM memory_entries GROUP BY access_level`);
|
|
884
926
|
const accessLevels = {};
|
|
885
927
|
accessLevelsResult.forEach(row => {
|
|
886
928
|
accessLevels[row.access_level] = row.count;
|
|
@@ -907,7 +949,7 @@ class SwarmMemoryManager {
|
|
|
907
949
|
// ============================================================================
|
|
908
950
|
// Table 3: Events (TTL: 30 days)
|
|
909
951
|
// ============================================================================
|
|
910
|
-
|
|
952
|
+
storeEvent(event) {
|
|
911
953
|
if (!this.db) {
|
|
912
954
|
throw new Error('Memory manager not initialized');
|
|
913
955
|
}
|
|
@@ -915,16 +957,16 @@ class SwarmMemoryManager {
|
|
|
915
957
|
const timestamp = event.timestamp || Date.now();
|
|
916
958
|
const ttl = event.ttl !== undefined ? event.ttl : this.TTL_POLICY.events;
|
|
917
959
|
const expiresAt = ttl > 0 ? timestamp + (ttl * 1000) : null;
|
|
918
|
-
|
|
960
|
+
this.run(`INSERT INTO events (id, type, payload, timestamp, source, ttl, expires_at)
|
|
919
961
|
VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, event.type, JSON.stringify(event.payload), timestamp, event.source, ttl, expiresAt]);
|
|
920
962
|
return id;
|
|
921
963
|
}
|
|
922
|
-
|
|
964
|
+
queryEvents(type) {
|
|
923
965
|
if (!this.db) {
|
|
924
966
|
throw new Error('Memory manager not initialized');
|
|
925
967
|
}
|
|
926
968
|
const now = Date.now();
|
|
927
|
-
const rows =
|
|
969
|
+
const rows = this.queryAll(`SELECT id, type, payload, timestamp, source, ttl
|
|
928
970
|
FROM events
|
|
929
971
|
WHERE type = ? AND (expires_at IS NULL OR expires_at > ?)
|
|
930
972
|
ORDER BY timestamp DESC`, [type, now]);
|
|
@@ -937,12 +979,12 @@ class SwarmMemoryManager {
|
|
|
937
979
|
ttl: row.ttl
|
|
938
980
|
}));
|
|
939
981
|
}
|
|
940
|
-
|
|
982
|
+
getEventsBySource(source) {
|
|
941
983
|
if (!this.db) {
|
|
942
984
|
throw new Error('Memory manager not initialized');
|
|
943
985
|
}
|
|
944
986
|
const now = Date.now();
|
|
945
|
-
const rows =
|
|
987
|
+
const rows = this.queryAll(`SELECT id, type, payload, timestamp, source, ttl
|
|
946
988
|
FROM events
|
|
947
989
|
WHERE source = ? AND (expires_at IS NULL OR expires_at > ?)
|
|
948
990
|
ORDER BY timestamp DESC`, [source, now]);
|
|
@@ -958,20 +1000,20 @@ class SwarmMemoryManager {
|
|
|
958
1000
|
// ============================================================================
|
|
959
1001
|
// Table 4: Workflow State (TTL: never expires)
|
|
960
1002
|
// ============================================================================
|
|
961
|
-
|
|
1003
|
+
storeWorkflowState(workflow) {
|
|
962
1004
|
if (!this.db) {
|
|
963
1005
|
throw new Error('Memory manager not initialized');
|
|
964
1006
|
}
|
|
965
1007
|
const now = Date.now();
|
|
966
1008
|
const ttl = workflow.ttl !== undefined ? workflow.ttl : this.TTL_POLICY.workflow_state;
|
|
967
|
-
|
|
1009
|
+
this.run(`INSERT OR REPLACE INTO workflow_state (id, step, status, checkpoint, sha, ttl, created_at, updated_at)
|
|
968
1010
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [workflow.id, workflow.step, workflow.status, JSON.stringify(workflow.checkpoint), workflow.sha, ttl, now, now]);
|
|
969
1011
|
}
|
|
970
|
-
|
|
1012
|
+
getWorkflowState(id) {
|
|
971
1013
|
if (!this.db) {
|
|
972
1014
|
throw new Error('Memory manager not initialized');
|
|
973
1015
|
}
|
|
974
|
-
const row =
|
|
1016
|
+
const row = this.queryOne(`SELECT id, step, status, checkpoint, sha, ttl, created_at, updated_at
|
|
975
1017
|
FROM workflow_state
|
|
976
1018
|
WHERE id = ?`, [id]);
|
|
977
1019
|
if (!row) {
|
|
@@ -988,13 +1030,13 @@ class SwarmMemoryManager {
|
|
|
988
1030
|
updatedAt: row.updated_at
|
|
989
1031
|
};
|
|
990
1032
|
}
|
|
991
|
-
|
|
1033
|
+
updateWorkflowState(id, updates) {
|
|
992
1034
|
if (!this.db) {
|
|
993
1035
|
throw new Error('Memory manager not initialized');
|
|
994
1036
|
}
|
|
995
|
-
const current =
|
|
1037
|
+
const current = this.getWorkflowState(id);
|
|
996
1038
|
const now = Date.now();
|
|
997
|
-
|
|
1039
|
+
this.run(`UPDATE workflow_state
|
|
998
1040
|
SET step = ?, status = ?, checkpoint = ?, sha = ?, updated_at = ?
|
|
999
1041
|
WHERE id = ?`, [
|
|
1000
1042
|
updates.step || current.step,
|
|
@@ -1005,11 +1047,11 @@ class SwarmMemoryManager {
|
|
|
1005
1047
|
id
|
|
1006
1048
|
]);
|
|
1007
1049
|
}
|
|
1008
|
-
|
|
1050
|
+
queryWorkflowsByStatus(status) {
|
|
1009
1051
|
if (!this.db) {
|
|
1010
1052
|
throw new Error('Memory manager not initialized');
|
|
1011
1053
|
}
|
|
1012
|
-
const rows =
|
|
1054
|
+
const rows = this.queryAll(`SELECT id, step, status, checkpoint, sha, ttl, created_at, updated_at
|
|
1013
1055
|
FROM workflow_state
|
|
1014
1056
|
WHERE status = ?`, [status]);
|
|
1015
1057
|
return rows.map((row) => ({
|
|
@@ -1026,7 +1068,7 @@ class SwarmMemoryManager {
|
|
|
1026
1068
|
// ============================================================================
|
|
1027
1069
|
// Table 5: Patterns (TTL: 7 days)
|
|
1028
1070
|
// ============================================================================
|
|
1029
|
-
|
|
1071
|
+
storePattern(pattern) {
|
|
1030
1072
|
if (!this.db) {
|
|
1031
1073
|
throw new Error('Memory manager not initialized');
|
|
1032
1074
|
}
|
|
@@ -1036,7 +1078,7 @@ class SwarmMemoryManager {
|
|
|
1036
1078
|
const expiresAt = ttl > 0 ? now + (ttl * 1000) : null;
|
|
1037
1079
|
// Extract agent_id from metadata for indexed lookups (O(log n) vs O(n))
|
|
1038
1080
|
const agentId = pattern.metadata?.agent_id || pattern.metadata?.agentId || null;
|
|
1039
|
-
|
|
1081
|
+
this.run(`INSERT OR REPLACE INTO patterns (id, pattern, confidence, usage_count, metadata, ttl, expires_at, created_at, agent_id)
|
|
1040
1082
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
1041
1083
|
id,
|
|
1042
1084
|
pattern.pattern,
|
|
@@ -1052,12 +1094,12 @@ class SwarmMemoryManager {
|
|
|
1052
1094
|
this.invalidatePatternCacheForAgent(agentId);
|
|
1053
1095
|
return id;
|
|
1054
1096
|
}
|
|
1055
|
-
|
|
1097
|
+
getPattern(patternName) {
|
|
1056
1098
|
if (!this.db) {
|
|
1057
1099
|
throw new Error('Memory manager not initialized');
|
|
1058
1100
|
}
|
|
1059
1101
|
const now = Date.now();
|
|
1060
|
-
const row =
|
|
1102
|
+
const row = this.queryOne(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at
|
|
1061
1103
|
FROM patterns
|
|
1062
1104
|
WHERE pattern = ? AND (expires_at IS NULL OR expires_at > ?)`, [patternName, now]);
|
|
1063
1105
|
if (!row) {
|
|
@@ -1073,7 +1115,7 @@ class SwarmMemoryManager {
|
|
|
1073
1115
|
createdAt: row.created_at
|
|
1074
1116
|
};
|
|
1075
1117
|
}
|
|
1076
|
-
|
|
1118
|
+
incrementPatternUsage(patternName) {
|
|
1077
1119
|
if (!this.db) {
|
|
1078
1120
|
throw new Error('Memory manager not initialized');
|
|
1079
1121
|
}
|
|
@@ -1103,12 +1145,12 @@ class SwarmMemoryManager {
|
|
|
1103
1145
|
this.patternCache.clear();
|
|
1104
1146
|
}
|
|
1105
1147
|
}
|
|
1106
|
-
|
|
1148
|
+
queryPatternsByConfidence(threshold) {
|
|
1107
1149
|
if (!this.db) {
|
|
1108
1150
|
throw new Error('Memory manager not initialized');
|
|
1109
1151
|
}
|
|
1110
1152
|
const now = Date.now();
|
|
1111
|
-
const rows =
|
|
1153
|
+
const rows = this.queryAll(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at
|
|
1112
1154
|
FROM patterns
|
|
1113
1155
|
WHERE confidence >= ? AND (expires_at IS NULL OR expires_at > ?)
|
|
1114
1156
|
ORDER BY confidence DESC`, [threshold, now]);
|
|
@@ -1135,7 +1177,7 @@ class SwarmMemoryManager {
|
|
|
1135
1177
|
escapeLikePattern(value) {
|
|
1136
1178
|
return value.replace(/[%_\\]/g, '\\$&');
|
|
1137
1179
|
}
|
|
1138
|
-
|
|
1180
|
+
queryPatternsByAgent(agentId, minConfidence = 0) {
|
|
1139
1181
|
if (!this.db) {
|
|
1140
1182
|
throw new Error('Memory manager not initialized');
|
|
1141
1183
|
}
|
|
@@ -1199,14 +1241,14 @@ class SwarmMemoryManager {
|
|
|
1199
1241
|
// ============================================================================
|
|
1200
1242
|
// Table 6: Consensus State (TTL: 7 days)
|
|
1201
1243
|
// ============================================================================
|
|
1202
|
-
|
|
1244
|
+
createConsensusProposal(proposal) {
|
|
1203
1245
|
if (!this.db) {
|
|
1204
1246
|
throw new Error('Memory manager not initialized');
|
|
1205
1247
|
}
|
|
1206
1248
|
const now = Date.now();
|
|
1207
1249
|
const ttl = proposal.ttl !== undefined ? proposal.ttl : this.TTL_POLICY.consensus;
|
|
1208
1250
|
const expiresAt = ttl > 0 ? now + (ttl * 1000) : null;
|
|
1209
|
-
|
|
1251
|
+
this.run(`INSERT INTO consensus_state (id, decision, proposer, votes, quorum, status, version, ttl, expires_at, created_at)
|
|
1210
1252
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
1211
1253
|
proposal.id,
|
|
1212
1254
|
proposal.decision,
|
|
@@ -1220,12 +1262,12 @@ class SwarmMemoryManager {
|
|
|
1220
1262
|
now
|
|
1221
1263
|
]);
|
|
1222
1264
|
}
|
|
1223
|
-
|
|
1265
|
+
getConsensusProposal(id) {
|
|
1224
1266
|
if (!this.db) {
|
|
1225
1267
|
throw new Error('Memory manager not initialized');
|
|
1226
1268
|
}
|
|
1227
1269
|
const now = Date.now();
|
|
1228
|
-
const row =
|
|
1270
|
+
const row = this.queryOne(`SELECT id, decision, proposer, votes, quorum, status, version, ttl, created_at
|
|
1229
1271
|
FROM consensus_state
|
|
1230
1272
|
WHERE id = ? AND (expires_at IS NULL OR expires_at > ?)`, [id, now]);
|
|
1231
1273
|
if (!row) {
|
|
@@ -1243,11 +1285,11 @@ class SwarmMemoryManager {
|
|
|
1243
1285
|
createdAt: row.created_at
|
|
1244
1286
|
};
|
|
1245
1287
|
}
|
|
1246
|
-
|
|
1288
|
+
voteOnConsensus(proposalId, agentId) {
|
|
1247
1289
|
if (!this.db) {
|
|
1248
1290
|
throw new Error('Memory manager not initialized');
|
|
1249
1291
|
}
|
|
1250
|
-
const proposal =
|
|
1292
|
+
const proposal = this.getConsensusProposal(proposalId);
|
|
1251
1293
|
if (!proposal.votes.includes(agentId)) {
|
|
1252
1294
|
proposal.votes.push(agentId);
|
|
1253
1295
|
}
|
|
@@ -1255,17 +1297,17 @@ class SwarmMemoryManager {
|
|
|
1255
1297
|
if (approved) {
|
|
1256
1298
|
proposal.status = 'approved';
|
|
1257
1299
|
}
|
|
1258
|
-
|
|
1300
|
+
this.run(`UPDATE consensus_state
|
|
1259
1301
|
SET votes = ?, status = ?
|
|
1260
1302
|
WHERE id = ?`, [JSON.stringify(proposal.votes), proposal.status, proposalId]);
|
|
1261
1303
|
return approved;
|
|
1262
1304
|
}
|
|
1263
|
-
|
|
1305
|
+
queryConsensusProposals(status) {
|
|
1264
1306
|
if (!this.db) {
|
|
1265
1307
|
throw new Error('Memory manager not initialized');
|
|
1266
1308
|
}
|
|
1267
1309
|
const now = Date.now();
|
|
1268
|
-
const rows =
|
|
1310
|
+
const rows = this.queryAll(`SELECT id, decision, proposer, votes, quorum, status, version, ttl, created_at
|
|
1269
1311
|
FROM consensus_state
|
|
1270
1312
|
WHERE status = ? AND (expires_at IS NULL OR expires_at > ?)`, [status, now]);
|
|
1271
1313
|
return rows.map((row) => ({
|
|
@@ -1283,21 +1325,21 @@ class SwarmMemoryManager {
|
|
|
1283
1325
|
// ============================================================================
|
|
1284
1326
|
// Table 7: Performance Metrics
|
|
1285
1327
|
// ============================================================================
|
|
1286
|
-
|
|
1328
|
+
storePerformanceMetric(metric) {
|
|
1287
1329
|
if (!this.db) {
|
|
1288
1330
|
throw new Error('Memory manager not initialized');
|
|
1289
1331
|
}
|
|
1290
1332
|
const id = metric.id || `metric-${Date.now()}-${SecureRandom_js_1.SecureRandom.generateId(5)}`;
|
|
1291
1333
|
const timestamp = metric.timestamp || Date.now();
|
|
1292
|
-
|
|
1334
|
+
this.run(`INSERT INTO performance_metrics (id, metric, value, unit, timestamp, agent_id)
|
|
1293
1335
|
VALUES (?, ?, ?, ?, ?, ?)`, [id, metric.metric, metric.value, metric.unit, timestamp, metric.agentId || null]);
|
|
1294
1336
|
return id;
|
|
1295
1337
|
}
|
|
1296
|
-
|
|
1338
|
+
queryPerformanceMetrics(metricName) {
|
|
1297
1339
|
if (!this.db) {
|
|
1298
1340
|
throw new Error('Memory manager not initialized');
|
|
1299
1341
|
}
|
|
1300
|
-
const rows =
|
|
1342
|
+
const rows = this.queryAll(`SELECT id, metric, value, unit, timestamp, agent_id
|
|
1301
1343
|
FROM performance_metrics
|
|
1302
1344
|
WHERE metric = ?
|
|
1303
1345
|
ORDER BY timestamp DESC`, [metricName]);
|
|
@@ -1310,11 +1352,11 @@ class SwarmMemoryManager {
|
|
|
1310
1352
|
agentId: row.agent_id
|
|
1311
1353
|
}));
|
|
1312
1354
|
}
|
|
1313
|
-
|
|
1355
|
+
getMetricsByAgent(agentId) {
|
|
1314
1356
|
if (!this.db) {
|
|
1315
1357
|
throw new Error('Memory manager not initialized');
|
|
1316
1358
|
}
|
|
1317
|
-
const rows =
|
|
1359
|
+
const rows = this.queryAll(`SELECT id, metric, value, unit, timestamp, agent_id
|
|
1318
1360
|
FROM performance_metrics
|
|
1319
1361
|
WHERE agent_id = ?
|
|
1320
1362
|
ORDER BY timestamp DESC`, [agentId]);
|
|
@@ -1327,23 +1369,23 @@ class SwarmMemoryManager {
|
|
|
1327
1369
|
agentId: row.agent_id
|
|
1328
1370
|
}));
|
|
1329
1371
|
}
|
|
1330
|
-
|
|
1372
|
+
getAverageMetric(metricName) {
|
|
1331
1373
|
if (!this.db) {
|
|
1332
1374
|
throw new Error('Memory manager not initialized');
|
|
1333
1375
|
}
|
|
1334
|
-
const row =
|
|
1376
|
+
const row = this.queryOne(`SELECT AVG(value) as avg FROM performance_metrics WHERE metric = ?`, [metricName]);
|
|
1335
1377
|
return row?.avg || 0;
|
|
1336
1378
|
}
|
|
1337
1379
|
// ============================================================================
|
|
1338
1380
|
// Table 8: Artifacts (TTL: never expires)
|
|
1339
1381
|
// ============================================================================
|
|
1340
|
-
|
|
1382
|
+
createArtifact(artifact) {
|
|
1341
1383
|
if (!this.db) {
|
|
1342
1384
|
throw new Error('Memory manager not initialized');
|
|
1343
1385
|
}
|
|
1344
1386
|
const now = Date.now();
|
|
1345
1387
|
const ttl = artifact.ttl !== undefined ? artifact.ttl : this.TTL_POLICY.artifacts;
|
|
1346
|
-
|
|
1388
|
+
this.run(`INSERT INTO artifacts (id, kind, path, sha256, tags, metadata, ttl, created_at)
|
|
1347
1389
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
1348
1390
|
artifact.id,
|
|
1349
1391
|
artifact.kind,
|
|
@@ -1355,11 +1397,11 @@ class SwarmMemoryManager {
|
|
|
1355
1397
|
now
|
|
1356
1398
|
]);
|
|
1357
1399
|
}
|
|
1358
|
-
|
|
1400
|
+
getArtifact(id) {
|
|
1359
1401
|
if (!this.db) {
|
|
1360
1402
|
throw new Error('Memory manager not initialized');
|
|
1361
1403
|
}
|
|
1362
|
-
const row =
|
|
1404
|
+
const row = this.queryOne(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at
|
|
1363
1405
|
FROM artifacts
|
|
1364
1406
|
WHERE id = ?`, [id]);
|
|
1365
1407
|
if (!row) {
|
|
@@ -1376,11 +1418,11 @@ class SwarmMemoryManager {
|
|
|
1376
1418
|
createdAt: row.created_at
|
|
1377
1419
|
};
|
|
1378
1420
|
}
|
|
1379
|
-
|
|
1421
|
+
queryArtifactsByKind(kind) {
|
|
1380
1422
|
if (!this.db) {
|
|
1381
1423
|
throw new Error('Memory manager not initialized');
|
|
1382
1424
|
}
|
|
1383
|
-
const rows =
|
|
1425
|
+
const rows = this.queryAll(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at
|
|
1384
1426
|
FROM artifacts
|
|
1385
1427
|
WHERE kind = ?`, [kind]);
|
|
1386
1428
|
return rows.map((row) => ({
|
|
@@ -1394,11 +1436,11 @@ class SwarmMemoryManager {
|
|
|
1394
1436
|
createdAt: row.created_at
|
|
1395
1437
|
}));
|
|
1396
1438
|
}
|
|
1397
|
-
|
|
1439
|
+
queryArtifactsByTag(tag) {
|
|
1398
1440
|
if (!this.db) {
|
|
1399
1441
|
throw new Error('Memory manager not initialized');
|
|
1400
1442
|
}
|
|
1401
|
-
const rows =
|
|
1443
|
+
const rows = this.queryAll(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at
|
|
1402
1444
|
FROM artifacts
|
|
1403
1445
|
WHERE tags LIKE ?`, [`%"${tag}"%`]);
|
|
1404
1446
|
return rows.map((row) => ({
|
|
@@ -1415,12 +1457,12 @@ class SwarmMemoryManager {
|
|
|
1415
1457
|
// ============================================================================
|
|
1416
1458
|
// Table 9: Sessions (resumability)
|
|
1417
1459
|
// ============================================================================
|
|
1418
|
-
|
|
1460
|
+
createSession(session) {
|
|
1419
1461
|
if (!this.db) {
|
|
1420
1462
|
throw new Error('Memory manager not initialized');
|
|
1421
1463
|
}
|
|
1422
1464
|
const now = Date.now();
|
|
1423
|
-
|
|
1465
|
+
this.run(`INSERT INTO sessions (id, mode, state, checkpoints, created_at, last_resumed)
|
|
1424
1466
|
VALUES (?, ?, ?, ?, ?, ?)`, [
|
|
1425
1467
|
session.id,
|
|
1426
1468
|
session.mode,
|
|
@@ -1430,11 +1472,11 @@ class SwarmMemoryManager {
|
|
|
1430
1472
|
null
|
|
1431
1473
|
]);
|
|
1432
1474
|
}
|
|
1433
|
-
|
|
1475
|
+
getSession(id) {
|
|
1434
1476
|
if (!this.db) {
|
|
1435
1477
|
throw new Error('Memory manager not initialized');
|
|
1436
1478
|
}
|
|
1437
|
-
const row =
|
|
1479
|
+
const row = this.queryOne(`SELECT id, mode, state, checkpoints, created_at, last_resumed
|
|
1438
1480
|
FROM sessions
|
|
1439
1481
|
WHERE id = ?`, [id]);
|
|
1440
1482
|
if (!row) {
|
|
@@ -1449,40 +1491,40 @@ class SwarmMemoryManager {
|
|
|
1449
1491
|
lastResumed: row.last_resumed
|
|
1450
1492
|
};
|
|
1451
1493
|
}
|
|
1452
|
-
|
|
1494
|
+
addSessionCheckpoint(sessionId, checkpoint) {
|
|
1453
1495
|
if (!this.db) {
|
|
1454
1496
|
throw new Error('Memory manager not initialized');
|
|
1455
1497
|
}
|
|
1456
|
-
const session =
|
|
1498
|
+
const session = this.getSession(sessionId);
|
|
1457
1499
|
session.checkpoints.push(checkpoint);
|
|
1458
|
-
|
|
1500
|
+
this.run(`UPDATE sessions
|
|
1459
1501
|
SET checkpoints = ?
|
|
1460
1502
|
WHERE id = ?`, [JSON.stringify(session.checkpoints), sessionId]);
|
|
1461
1503
|
}
|
|
1462
|
-
|
|
1463
|
-
const session =
|
|
1504
|
+
getLatestCheckpoint(sessionId) {
|
|
1505
|
+
const session = this.getSession(sessionId);
|
|
1464
1506
|
return session.checkpoints.length > 0
|
|
1465
1507
|
? session.checkpoints[session.checkpoints.length - 1]
|
|
1466
1508
|
: undefined;
|
|
1467
1509
|
}
|
|
1468
|
-
|
|
1510
|
+
markSessionResumed(sessionId) {
|
|
1469
1511
|
if (!this.db) {
|
|
1470
1512
|
throw new Error('Memory manager not initialized');
|
|
1471
1513
|
}
|
|
1472
1514
|
const now = Date.now();
|
|
1473
|
-
|
|
1515
|
+
this.run(`UPDATE sessions
|
|
1474
1516
|
SET last_resumed = ?
|
|
1475
1517
|
WHERE id = ?`, [now, sessionId]);
|
|
1476
1518
|
}
|
|
1477
1519
|
// ============================================================================
|
|
1478
1520
|
// Table 10: Agent Registry
|
|
1479
1521
|
// ============================================================================
|
|
1480
|
-
|
|
1522
|
+
registerAgent(agent) {
|
|
1481
1523
|
if (!this.db) {
|
|
1482
1524
|
throw new Error('Memory manager not initialized');
|
|
1483
1525
|
}
|
|
1484
1526
|
const now = Date.now();
|
|
1485
|
-
|
|
1527
|
+
this.run(`INSERT INTO agent_registry (id, type, capabilities, status, performance, created_at, updated_at)
|
|
1486
1528
|
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
|
1487
1529
|
agent.id,
|
|
1488
1530
|
agent.type,
|
|
@@ -1493,11 +1535,11 @@ class SwarmMemoryManager {
|
|
|
1493
1535
|
now
|
|
1494
1536
|
]);
|
|
1495
1537
|
}
|
|
1496
|
-
|
|
1538
|
+
getAgent(id) {
|
|
1497
1539
|
if (!this.db) {
|
|
1498
1540
|
throw new Error('Memory manager not initialized');
|
|
1499
1541
|
}
|
|
1500
|
-
const row =
|
|
1542
|
+
const row = this.queryOne(`SELECT id, type, capabilities, status, performance, created_at, updated_at
|
|
1501
1543
|
FROM agent_registry
|
|
1502
1544
|
WHERE id = ?`, [id]);
|
|
1503
1545
|
if (!row) {
|
|
@@ -1513,20 +1555,20 @@ class SwarmMemoryManager {
|
|
|
1513
1555
|
updatedAt: row.updated_at
|
|
1514
1556
|
};
|
|
1515
1557
|
}
|
|
1516
|
-
|
|
1558
|
+
updateAgentStatus(agentId, status) {
|
|
1517
1559
|
if (!this.db) {
|
|
1518
1560
|
throw new Error('Memory manager not initialized');
|
|
1519
1561
|
}
|
|
1520
1562
|
const now = Date.now();
|
|
1521
|
-
|
|
1563
|
+
this.run(`UPDATE agent_registry
|
|
1522
1564
|
SET status = ?, updated_at = ?
|
|
1523
1565
|
WHERE id = ?`, [status, now, agentId]);
|
|
1524
1566
|
}
|
|
1525
|
-
|
|
1567
|
+
queryAgentsByStatus(status) {
|
|
1526
1568
|
if (!this.db) {
|
|
1527
1569
|
throw new Error('Memory manager not initialized');
|
|
1528
1570
|
}
|
|
1529
|
-
const rows =
|
|
1571
|
+
const rows = this.queryAll(`SELECT id, type, capabilities, status, performance, created_at, updated_at
|
|
1530
1572
|
FROM agent_registry
|
|
1531
1573
|
WHERE status = ?`, [status]);
|
|
1532
1574
|
return rows.map((row) => ({
|
|
@@ -1539,31 +1581,31 @@ class SwarmMemoryManager {
|
|
|
1539
1581
|
updatedAt: row.updated_at
|
|
1540
1582
|
}));
|
|
1541
1583
|
}
|
|
1542
|
-
|
|
1584
|
+
updateAgentPerformance(agentId, performance) {
|
|
1543
1585
|
if (!this.db) {
|
|
1544
1586
|
throw new Error('Memory manager not initialized');
|
|
1545
1587
|
}
|
|
1546
1588
|
const now = Date.now();
|
|
1547
|
-
|
|
1589
|
+
this.run(`UPDATE agent_registry
|
|
1548
1590
|
SET performance = ?, updated_at = ?
|
|
1549
1591
|
WHERE id = ?`, [JSON.stringify(performance), now, agentId]);
|
|
1550
1592
|
}
|
|
1551
1593
|
// ============================================================================
|
|
1552
1594
|
// Table 11: GOAP State
|
|
1553
1595
|
// ============================================================================
|
|
1554
|
-
|
|
1596
|
+
storeGOAPGoal(goal) {
|
|
1555
1597
|
if (!this.db) {
|
|
1556
1598
|
throw new Error('Memory manager not initialized');
|
|
1557
1599
|
}
|
|
1558
1600
|
const now = Date.now();
|
|
1559
|
-
|
|
1601
|
+
this.run(`INSERT INTO goap_goals (id, conditions, cost, priority, created_at)
|
|
1560
1602
|
VALUES (?, ?, ?, ?, ?)`, [goal.id, JSON.stringify(goal.conditions), goal.cost, goal.priority || null, now]);
|
|
1561
1603
|
}
|
|
1562
|
-
|
|
1604
|
+
getGOAPGoal(id) {
|
|
1563
1605
|
if (!this.db) {
|
|
1564
1606
|
throw new Error('Memory manager not initialized');
|
|
1565
1607
|
}
|
|
1566
|
-
const row =
|
|
1608
|
+
const row = this.queryOne(`SELECT id, conditions, cost, priority, created_at
|
|
1567
1609
|
FROM goap_goals
|
|
1568
1610
|
WHERE id = ?`, [id]);
|
|
1569
1611
|
if (!row) {
|
|
@@ -1577,12 +1619,12 @@ class SwarmMemoryManager {
|
|
|
1577
1619
|
createdAt: row.created_at
|
|
1578
1620
|
};
|
|
1579
1621
|
}
|
|
1580
|
-
|
|
1622
|
+
storeGOAPAction(action) {
|
|
1581
1623
|
if (!this.db) {
|
|
1582
1624
|
throw new Error('Memory manager not initialized');
|
|
1583
1625
|
}
|
|
1584
1626
|
const now = Date.now();
|
|
1585
|
-
|
|
1627
|
+
this.run(`INSERT INTO goap_actions (id, preconditions, effects, cost, agent_type, created_at)
|
|
1586
1628
|
VALUES (?, ?, ?, ?, ?, ?)`, [
|
|
1587
1629
|
action.id,
|
|
1588
1630
|
JSON.stringify(action.preconditions),
|
|
@@ -1592,11 +1634,11 @@ class SwarmMemoryManager {
|
|
|
1592
1634
|
now
|
|
1593
1635
|
]);
|
|
1594
1636
|
}
|
|
1595
|
-
|
|
1637
|
+
getGOAPAction(id) {
|
|
1596
1638
|
if (!this.db) {
|
|
1597
1639
|
throw new Error('Memory manager not initialized');
|
|
1598
1640
|
}
|
|
1599
|
-
const row =
|
|
1641
|
+
const row = this.queryOne(`SELECT id, preconditions, effects, cost, agent_type, created_at
|
|
1600
1642
|
FROM goap_actions
|
|
1601
1643
|
WHERE id = ?`, [id]);
|
|
1602
1644
|
if (!row) {
|
|
@@ -1611,19 +1653,19 @@ class SwarmMemoryManager {
|
|
|
1611
1653
|
createdAt: row.created_at
|
|
1612
1654
|
};
|
|
1613
1655
|
}
|
|
1614
|
-
|
|
1656
|
+
storeGOAPPlan(plan) {
|
|
1615
1657
|
if (!this.db) {
|
|
1616
1658
|
throw new Error('Memory manager not initialized');
|
|
1617
1659
|
}
|
|
1618
1660
|
const now = Date.now();
|
|
1619
|
-
|
|
1661
|
+
this.run(`INSERT INTO goap_plans (id, goal_id, sequence, total_cost, created_at)
|
|
1620
1662
|
VALUES (?, ?, ?, ?, ?)`, [plan.id, plan.goalId, JSON.stringify(plan.sequence), plan.totalCost, now]);
|
|
1621
1663
|
}
|
|
1622
|
-
|
|
1664
|
+
getGOAPPlan(id) {
|
|
1623
1665
|
if (!this.db) {
|
|
1624
1666
|
throw new Error('Memory manager not initialized');
|
|
1625
1667
|
}
|
|
1626
|
-
const row =
|
|
1668
|
+
const row = this.queryOne(`SELECT id, goal_id, sequence, total_cost, created_at
|
|
1627
1669
|
FROM goap_plans
|
|
1628
1670
|
WHERE id = ?`, [id]);
|
|
1629
1671
|
if (!row) {
|
|
@@ -1640,11 +1682,11 @@ class SwarmMemoryManager {
|
|
|
1640
1682
|
// ============================================================================
|
|
1641
1683
|
// Table 12: OODA Cycles
|
|
1642
1684
|
// ============================================================================
|
|
1643
|
-
|
|
1685
|
+
storeOODACycle(cycle) {
|
|
1644
1686
|
if (!this.db) {
|
|
1645
1687
|
throw new Error('Memory manager not initialized');
|
|
1646
1688
|
}
|
|
1647
|
-
|
|
1689
|
+
this.run(`INSERT INTO ooda_cycles (id, phase, observations, orientation, decision, action, timestamp, completed, result)
|
|
1648
1690
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
1649
1691
|
cycle.id,
|
|
1650
1692
|
cycle.phase,
|
|
@@ -1657,11 +1699,11 @@ class SwarmMemoryManager {
|
|
|
1657
1699
|
cycle.result ? JSON.stringify(cycle.result) : null
|
|
1658
1700
|
]);
|
|
1659
1701
|
}
|
|
1660
|
-
|
|
1702
|
+
getOODACycle(id) {
|
|
1661
1703
|
if (!this.db) {
|
|
1662
1704
|
throw new Error('Memory manager not initialized');
|
|
1663
1705
|
}
|
|
1664
|
-
const row =
|
|
1706
|
+
const row = this.queryOne(`SELECT id, phase, observations, orientation, decision, action, timestamp, completed, result
|
|
1665
1707
|
FROM ooda_cycles
|
|
1666
1708
|
WHERE id = ?`, [id]);
|
|
1667
1709
|
if (!row) {
|
|
@@ -1679,7 +1721,7 @@ class SwarmMemoryManager {
|
|
|
1679
1721
|
result: row.result ? JSON.parse(row.result) : undefined
|
|
1680
1722
|
};
|
|
1681
1723
|
}
|
|
1682
|
-
|
|
1724
|
+
updateOODAPhase(cycleId, phase, data) {
|
|
1683
1725
|
if (!this.db) {
|
|
1684
1726
|
throw new Error('Memory manager not initialized');
|
|
1685
1727
|
}
|
|
@@ -1690,23 +1732,23 @@ class SwarmMemoryManager {
|
|
|
1690
1732
|
act: 'action'
|
|
1691
1733
|
};
|
|
1692
1734
|
const field = fieldMap[phase];
|
|
1693
|
-
|
|
1735
|
+
this.run(`UPDATE ooda_cycles
|
|
1694
1736
|
SET phase = ?, ${field} = ?
|
|
1695
1737
|
WHERE id = ?`, [phase, JSON.stringify(data), cycleId]);
|
|
1696
1738
|
}
|
|
1697
|
-
|
|
1739
|
+
completeOODACycle(cycleId, result) {
|
|
1698
1740
|
if (!this.db) {
|
|
1699
1741
|
throw new Error('Memory manager not initialized');
|
|
1700
1742
|
}
|
|
1701
|
-
|
|
1743
|
+
this.run(`UPDATE ooda_cycles
|
|
1702
1744
|
SET completed = 1, result = ?
|
|
1703
1745
|
WHERE id = ?`, [JSON.stringify(result), cycleId]);
|
|
1704
1746
|
}
|
|
1705
|
-
|
|
1747
|
+
queryOODACyclesByPhase(phase) {
|
|
1706
1748
|
if (!this.db) {
|
|
1707
1749
|
throw new Error('Memory manager not initialized');
|
|
1708
1750
|
}
|
|
1709
|
-
const rows =
|
|
1751
|
+
const rows = this.queryAll(`SELECT id, phase, observations, orientation, decision, action, timestamp, completed, result
|
|
1710
1752
|
FROM ooda_cycles
|
|
1711
1753
|
WHERE phase = ?`, [phase]);
|
|
1712
1754
|
return rows.map((row) => ({
|
|
@@ -1725,13 +1767,13 @@ class SwarmMemoryManager {
|
|
|
1725
1767
|
/**
|
|
1726
1768
|
* Store ACL for a memory entry
|
|
1727
1769
|
*/
|
|
1728
|
-
|
|
1770
|
+
storeACL(acl) {
|
|
1729
1771
|
if (!this.db) {
|
|
1730
1772
|
throw new Error('Memory manager not initialized');
|
|
1731
1773
|
}
|
|
1732
1774
|
const grantedPerms = acl.grantedPermissions ? JSON.stringify(acl.grantedPermissions) : null;
|
|
1733
1775
|
const blockedAgents = acl.blockedAgents ? JSON.stringify(acl.blockedAgents) : null;
|
|
1734
|
-
|
|
1776
|
+
this.run(`INSERT OR REPLACE INTO memory_acl
|
|
1735
1777
|
(resource_id, owner, access_level, team_id, swarm_id, granted_permissions, blocked_agents, created_at, updated_at)
|
|
1736
1778
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
1737
1779
|
acl.resourceId,
|
|
@@ -1749,7 +1791,7 @@ class SwarmMemoryManager {
|
|
|
1749
1791
|
/**
|
|
1750
1792
|
* Retrieve ACL for a memory entry
|
|
1751
1793
|
*/
|
|
1752
|
-
|
|
1794
|
+
getACL(resourceId) {
|
|
1753
1795
|
if (!this.db) {
|
|
1754
1796
|
throw new Error('Memory manager not initialized');
|
|
1755
1797
|
}
|
|
@@ -1757,7 +1799,7 @@ class SwarmMemoryManager {
|
|
|
1757
1799
|
if (this.aclCache.has(resourceId)) {
|
|
1758
1800
|
return this.aclCache.get(resourceId);
|
|
1759
1801
|
}
|
|
1760
|
-
const row =
|
|
1802
|
+
const row = this.queryOne(`SELECT * FROM memory_acl WHERE resource_id = ?`, [resourceId]);
|
|
1761
1803
|
if (!row) {
|
|
1762
1804
|
return null;
|
|
1763
1805
|
}
|
|
@@ -1778,57 +1820,57 @@ class SwarmMemoryManager {
|
|
|
1778
1820
|
/**
|
|
1779
1821
|
* Update ACL for a memory entry
|
|
1780
1822
|
*/
|
|
1781
|
-
|
|
1782
|
-
const existing =
|
|
1823
|
+
updateACL(resourceId, updates) {
|
|
1824
|
+
const existing = this.getACL(resourceId);
|
|
1783
1825
|
if (!existing) {
|
|
1784
1826
|
throw new Error(`ACL not found for resource: ${resourceId}`);
|
|
1785
1827
|
}
|
|
1786
1828
|
const updated = this.accessControl.updateACL(existing, updates);
|
|
1787
|
-
|
|
1829
|
+
this.storeACL(updated);
|
|
1788
1830
|
}
|
|
1789
1831
|
/**
|
|
1790
1832
|
* Grant permission to an agent
|
|
1791
1833
|
*/
|
|
1792
|
-
|
|
1793
|
-
const existing =
|
|
1834
|
+
grantPermission(resourceId, agentId, permissions) {
|
|
1835
|
+
const existing = this.getACL(resourceId);
|
|
1794
1836
|
if (!existing) {
|
|
1795
1837
|
throw new Error(`ACL not found for resource: ${resourceId}`);
|
|
1796
1838
|
}
|
|
1797
1839
|
const updated = this.accessControl.grantPermission(existing, agentId, permissions);
|
|
1798
|
-
|
|
1840
|
+
this.storeACL(updated);
|
|
1799
1841
|
}
|
|
1800
1842
|
/**
|
|
1801
1843
|
* Revoke permission from an agent
|
|
1802
1844
|
*/
|
|
1803
|
-
|
|
1804
|
-
const existing =
|
|
1845
|
+
revokePermission(resourceId, agentId, permissions) {
|
|
1846
|
+
const existing = this.getACL(resourceId);
|
|
1805
1847
|
if (!existing) {
|
|
1806
1848
|
throw new Error(`ACL not found for resource: ${resourceId}`);
|
|
1807
1849
|
}
|
|
1808
1850
|
const updated = this.accessControl.revokePermission(existing, agentId, permissions);
|
|
1809
|
-
|
|
1851
|
+
this.storeACL(updated);
|
|
1810
1852
|
}
|
|
1811
1853
|
/**
|
|
1812
1854
|
* Block an agent from accessing a resource
|
|
1813
1855
|
*/
|
|
1814
|
-
|
|
1815
|
-
const existing =
|
|
1856
|
+
blockAgent(resourceId, agentId) {
|
|
1857
|
+
const existing = this.getACL(resourceId);
|
|
1816
1858
|
if (!existing) {
|
|
1817
1859
|
throw new Error(`ACL not found for resource: ${resourceId}`);
|
|
1818
1860
|
}
|
|
1819
1861
|
const updated = this.accessControl.blockAgent(existing, agentId);
|
|
1820
|
-
|
|
1862
|
+
this.storeACL(updated);
|
|
1821
1863
|
}
|
|
1822
1864
|
/**
|
|
1823
1865
|
* Unblock an agent
|
|
1824
1866
|
*/
|
|
1825
|
-
|
|
1826
|
-
const existing =
|
|
1867
|
+
unblockAgent(resourceId, agentId) {
|
|
1868
|
+
const existing = this.getACL(resourceId);
|
|
1827
1869
|
if (!existing) {
|
|
1828
1870
|
throw new Error(`ACL not found for resource: ${resourceId}`);
|
|
1829
1871
|
}
|
|
1830
1872
|
const updated = this.accessControl.unblockAgent(existing, agentId);
|
|
1831
|
-
|
|
1873
|
+
this.storeACL(updated);
|
|
1832
1874
|
}
|
|
1833
1875
|
/**
|
|
1834
1876
|
* Get access control instance for direct usage
|
|
@@ -1881,7 +1923,7 @@ class SwarmMemoryManager {
|
|
|
1881
1923
|
* @param port - Peer port number
|
|
1882
1924
|
* @returns Peer ID
|
|
1883
1925
|
*/
|
|
1884
|
-
|
|
1926
|
+
addQUICPeer(address, port) {
|
|
1885
1927
|
if (!this.agentDBManager) {
|
|
1886
1928
|
throw new Error('AgentDB not enabled. Call enableAgentDB() first.');
|
|
1887
1929
|
}
|
|
@@ -1894,7 +1936,7 @@ class SwarmMemoryManager {
|
|
|
1894
1936
|
*
|
|
1895
1937
|
* @param peerId - Peer ID to remove
|
|
1896
1938
|
*/
|
|
1897
|
-
|
|
1939
|
+
removeQUICPeer(peerId) {
|
|
1898
1940
|
if (!this.agentDBManager) {
|
|
1899
1941
|
throw new Error('AgentDB not enabled');
|
|
1900
1942
|
}
|
|
@@ -1939,7 +1981,7 @@ class SwarmMemoryManager {
|
|
|
1939
1981
|
* @param partition - Optional partition filter
|
|
1940
1982
|
* @returns Array of modified entries with metadata
|
|
1941
1983
|
*/
|
|
1942
|
-
|
|
1984
|
+
getModifiedEntries(since, partition) {
|
|
1943
1985
|
if (!this.db) {
|
|
1944
1986
|
throw new Error('Memory manager not initialized');
|
|
1945
1987
|
}
|
|
@@ -1954,7 +1996,7 @@ class SwarmMemoryManager {
|
|
|
1954
1996
|
params.push(partition);
|
|
1955
1997
|
}
|
|
1956
1998
|
query += ` ORDER BY created_at ASC`;
|
|
1957
|
-
const rows =
|
|
1999
|
+
const rows = this.queryAll(query, params);
|
|
1958
2000
|
return rows.map((row) => ({
|
|
1959
2001
|
key: row.key,
|
|
1960
2002
|
value: JSON.parse(row.value),
|
|
@@ -1993,7 +2035,7 @@ class SwarmMemoryManager {
|
|
|
1993
2035
|
* Store a learning experience for Q-learning
|
|
1994
2036
|
* Delegates to the underlying Database instance
|
|
1995
2037
|
*/
|
|
1996
|
-
|
|
2038
|
+
storeLearningExperience(experience) {
|
|
1997
2039
|
if (!this.db) {
|
|
1998
2040
|
throw new Error('Memory manager not initialized');
|
|
1999
2041
|
}
|
|
@@ -2017,7 +2059,7 @@ class SwarmMemoryManager {
|
|
|
2017
2059
|
* Upsert a Q-value for a state-action pair
|
|
2018
2060
|
* Delegates to the underlying Database instance
|
|
2019
2061
|
*/
|
|
2020
|
-
|
|
2062
|
+
upsertQValue(agentId, stateKey, actionKey, qValue) {
|
|
2021
2063
|
if (!this.db) {
|
|
2022
2064
|
throw new Error('Memory manager not initialized');
|
|
2023
2065
|
}
|
|
@@ -2034,7 +2076,7 @@ class SwarmMemoryManager {
|
|
|
2034
2076
|
/**
|
|
2035
2077
|
* Get all Q-values for an agent
|
|
2036
2078
|
*/
|
|
2037
|
-
|
|
2079
|
+
getAllQValues(agentId) {
|
|
2038
2080
|
if (!this.db) {
|
|
2039
2081
|
throw new Error('Memory manager not initialized');
|
|
2040
2082
|
}
|
|
@@ -2044,12 +2086,12 @@ class SwarmMemoryManager {
|
|
|
2044
2086
|
WHERE agent_id = ?
|
|
2045
2087
|
ORDER BY last_updated DESC
|
|
2046
2088
|
`;
|
|
2047
|
-
return
|
|
2089
|
+
return this.queryAll(sql, [agentId]);
|
|
2048
2090
|
}
|
|
2049
2091
|
/**
|
|
2050
2092
|
* Get Q-value for a specific state-action pair
|
|
2051
2093
|
*/
|
|
2052
|
-
|
|
2094
|
+
getQValue(agentId, stateKey, actionKey) {
|
|
2053
2095
|
if (!this.db) {
|
|
2054
2096
|
throw new Error('Memory manager not initialized');
|
|
2055
2097
|
}
|
|
@@ -2057,14 +2099,14 @@ class SwarmMemoryManager {
|
|
|
2057
2099
|
SELECT q_value FROM q_values
|
|
2058
2100
|
WHERE agent_id = ? AND state_key = ? AND action_key = ?
|
|
2059
2101
|
`;
|
|
2060
|
-
const row =
|
|
2102
|
+
const row = this.queryOne(sql, [agentId, stateKey, actionKey]);
|
|
2061
2103
|
return row ? row.q_value : null;
|
|
2062
2104
|
}
|
|
2063
2105
|
/**
|
|
2064
2106
|
* Get the best action for a given state based on Q-values
|
|
2065
2107
|
* Returns the action with the highest Q-value for the specified state
|
|
2066
2108
|
*/
|
|
2067
|
-
|
|
2109
|
+
getBestAction(agentId, stateKey) {
|
|
2068
2110
|
if (!this.db) {
|
|
2069
2111
|
throw new Error('Memory manager not initialized');
|
|
2070
2112
|
}
|
|
@@ -2075,14 +2117,14 @@ class SwarmMemoryManager {
|
|
|
2075
2117
|
ORDER BY q_value DESC
|
|
2076
2118
|
LIMIT 1
|
|
2077
2119
|
`;
|
|
2078
|
-
const result =
|
|
2120
|
+
const result = this.queryOne(sql, [agentId, stateKey]);
|
|
2079
2121
|
return result || null;
|
|
2080
2122
|
}
|
|
2081
2123
|
/**
|
|
2082
2124
|
* Get recent learning experiences for an agent
|
|
2083
2125
|
* Returns experiences ordered by most recent first
|
|
2084
2126
|
*/
|
|
2085
|
-
|
|
2127
|
+
getRecentLearningExperiences(agentId, limit = 10) {
|
|
2086
2128
|
if (!this.db) {
|
|
2087
2129
|
throw new Error('Memory manager not initialized');
|
|
2088
2130
|
}
|
|
@@ -2093,12 +2135,12 @@ class SwarmMemoryManager {
|
|
|
2093
2135
|
ORDER BY created_at DESC
|
|
2094
2136
|
LIMIT ?
|
|
2095
2137
|
`;
|
|
2096
|
-
return
|
|
2138
|
+
return this.queryAll(sql, [agentId, limit]);
|
|
2097
2139
|
}
|
|
2098
2140
|
/**
|
|
2099
2141
|
* Get learning experiences by task type
|
|
2100
2142
|
*/
|
|
2101
|
-
|
|
2143
|
+
getLearningExperiencesByTaskType(agentId, taskType, limit = 50) {
|
|
2102
2144
|
if (!this.db) {
|
|
2103
2145
|
throw new Error('Memory manager not initialized');
|
|
2104
2146
|
}
|
|
@@ -2109,13 +2151,13 @@ class SwarmMemoryManager {
|
|
|
2109
2151
|
ORDER BY created_at DESC
|
|
2110
2152
|
LIMIT ?
|
|
2111
2153
|
`;
|
|
2112
|
-
return
|
|
2154
|
+
return this.queryAll(sql, [agentId, taskType, limit]);
|
|
2113
2155
|
}
|
|
2114
2156
|
/**
|
|
2115
2157
|
* Get high-reward learning experiences for pattern extraction
|
|
2116
2158
|
* Useful for identifying successful strategies to replicate
|
|
2117
2159
|
*/
|
|
2118
|
-
|
|
2160
|
+
getHighRewardExperiences(agentId, minReward = 0.8, limit = 20) {
|
|
2119
2161
|
if (!this.db) {
|
|
2120
2162
|
throw new Error('Memory manager not initialized');
|
|
2121
2163
|
}
|
|
@@ -2126,13 +2168,13 @@ class SwarmMemoryManager {
|
|
|
2126
2168
|
ORDER BY reward DESC, created_at DESC
|
|
2127
2169
|
LIMIT ?
|
|
2128
2170
|
`;
|
|
2129
|
-
return
|
|
2171
|
+
return this.queryAll(sql, [agentId, minReward, limit]);
|
|
2130
2172
|
}
|
|
2131
2173
|
/**
|
|
2132
2174
|
* Get learning statistics for an agent
|
|
2133
2175
|
* Useful for tracking learning progress over time
|
|
2134
2176
|
*/
|
|
2135
|
-
|
|
2177
|
+
getLearningStats(agentId) {
|
|
2136
2178
|
if (!this.db) {
|
|
2137
2179
|
throw new Error('Memory manager not initialized');
|
|
2138
2180
|
}
|
|
@@ -2147,7 +2189,7 @@ class SwarmMemoryManager {
|
|
|
2147
2189
|
FROM learning_experiences
|
|
2148
2190
|
WHERE agent_id = ?
|
|
2149
2191
|
`;
|
|
2150
|
-
const row =
|
|
2192
|
+
const row = this.queryOne(sql, [agentId]);
|
|
2151
2193
|
return {
|
|
2152
2194
|
totalExperiences: row?.total_experiences || 0,
|
|
2153
2195
|
averageReward: row?.avg_reward || 0,
|
|
@@ -2160,7 +2202,7 @@ class SwarmMemoryManager {
|
|
|
2160
2202
|
/**
|
|
2161
2203
|
* Store a learning performance snapshot
|
|
2162
2204
|
*/
|
|
2163
|
-
|
|
2205
|
+
storeLearningSnapshot(snapshot) {
|
|
2164
2206
|
if (!this.db) {
|
|
2165
2207
|
throw new Error('Memory manager not initialized');
|
|
2166
2208
|
}
|
|
@@ -2184,7 +2226,7 @@ class SwarmMemoryManager {
|
|
|
2184
2226
|
/**
|
|
2185
2227
|
* Get learning history for an agent
|
|
2186
2228
|
*/
|
|
2187
|
-
|
|
2229
|
+
getLearningHistory(agentId, limit = 100) {
|
|
2188
2230
|
if (!this.db) {
|
|
2189
2231
|
throw new Error('Memory manager not initialized');
|
|
2190
2232
|
}
|
|
@@ -2196,7 +2238,7 @@ class SwarmMemoryManager {
|
|
|
2196
2238
|
ORDER BY timestamp DESC
|
|
2197
2239
|
LIMIT ?
|
|
2198
2240
|
`;
|
|
2199
|
-
return
|
|
2241
|
+
return this.queryAll(sql, [agentId, limit]);
|
|
2200
2242
|
}
|
|
2201
2243
|
}
|
|
2202
2244
|
exports.SwarmMemoryManager = SwarmMemoryManager;
|