agentic-qe 1.8.4 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
  2. package/CHANGELOG.md +394 -0
  3. package/README.md +86 -18
  4. package/dist/App.d.ts +5 -0
  5. package/dist/App.d.ts.map +1 -0
  6. package/dist/App.js +15 -0
  7. package/dist/App.js.map +1 -0
  8. package/dist/cli/commands/constitution.d.ts +34 -0
  9. package/dist/cli/commands/constitution.d.ts.map +1 -0
  10. package/dist/cli/commands/constitution.js +679 -0
  11. package/dist/cli/commands/constitution.js.map +1 -0
  12. package/dist/cli/commands/init.d.ts +8 -75
  13. package/dist/cli/commands/init.d.ts.map +1 -1
  14. package/dist/cli/commands/init.js +22 -2292
  15. package/dist/cli/commands/init.js.map +1 -1
  16. package/dist/cli/commands/learn/index.d.ts.map +1 -1
  17. package/dist/cli/commands/learn/index.js +3 -4
  18. package/dist/cli/commands/learn/index.js.map +1 -1
  19. package/dist/cli/commands/telemetry.d.ts +36 -0
  20. package/dist/cli/commands/telemetry.d.ts.map +1 -0
  21. package/dist/cli/commands/telemetry.js +364 -0
  22. package/dist/cli/commands/telemetry.js.map +1 -0
  23. package/dist/cli/index.js +66 -0
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/init/agents.d.ts +22 -0
  26. package/dist/cli/init/agents.d.ts.map +1 -0
  27. package/dist/cli/init/agents.js +522 -0
  28. package/dist/cli/init/agents.js.map +1 -0
  29. package/dist/cli/init/bash-wrapper.d.ts +14 -0
  30. package/dist/cli/init/bash-wrapper.d.ts.map +1 -0
  31. package/dist/cli/init/bash-wrapper.js +47 -0
  32. package/dist/cli/init/bash-wrapper.js.map +1 -0
  33. package/dist/cli/init/claude-config.d.ts +24 -0
  34. package/dist/cli/init/claude-config.d.ts.map +1 -0
  35. package/dist/cli/init/claude-config.js +275 -0
  36. package/dist/cli/init/claude-config.js.map +1 -0
  37. package/dist/cli/init/claude-md.d.ts +19 -0
  38. package/dist/cli/init/claude-md.d.ts.map +1 -0
  39. package/dist/cli/init/claude-md.js +153 -0
  40. package/dist/cli/init/claude-md.js.map +1 -0
  41. package/dist/cli/init/commands.d.ts +6 -0
  42. package/dist/cli/init/commands.d.ts.map +1 -0
  43. package/dist/cli/init/commands.js +83 -0
  44. package/dist/cli/init/commands.js.map +1 -0
  45. package/dist/cli/init/database-init.d.ts +15 -0
  46. package/dist/cli/init/database-init.d.ts.map +1 -0
  47. package/dist/cli/init/database-init.js +203 -0
  48. package/dist/cli/init/database-init.js.map +1 -0
  49. package/dist/cli/init/directory-structure.d.ts +14 -0
  50. package/dist/cli/init/directory-structure.d.ts.map +1 -0
  51. package/dist/cli/init/directory-structure.js +91 -0
  52. package/dist/cli/init/directory-structure.js.map +1 -0
  53. package/dist/cli/init/documentation.d.ts +14 -0
  54. package/dist/cli/init/documentation.d.ts.map +1 -0
  55. package/dist/cli/init/documentation.js +195 -0
  56. package/dist/cli/init/documentation.js.map +1 -0
  57. package/dist/cli/init/fleet-config.d.ts +34 -0
  58. package/dist/cli/init/fleet-config.d.ts.map +1 -0
  59. package/dist/cli/init/fleet-config.js +269 -0
  60. package/dist/cli/init/fleet-config.js.map +1 -0
  61. package/dist/cli/init/helpers.d.ts +6 -0
  62. package/dist/cli/init/helpers.d.ts.map +1 -0
  63. package/dist/cli/init/helpers.js +94 -0
  64. package/dist/cli/init/helpers.js.map +1 -0
  65. package/dist/cli/init/index.d.ts +32 -0
  66. package/dist/cli/init/index.d.ts.map +1 -0
  67. package/dist/cli/init/index.js +294 -0
  68. package/dist/cli/init/index.js.map +1 -0
  69. package/dist/cli/init/skills.d.ts +6 -0
  70. package/dist/cli/init/skills.d.ts.map +1 -0
  71. package/dist/cli/init/skills.js +138 -0
  72. package/dist/cli/init/skills.js.map +1 -0
  73. package/dist/cli/init/utils/file-utils.d.ts +74 -0
  74. package/dist/cli/init/utils/file-utils.d.ts.map +1 -0
  75. package/dist/cli/init/utils/file-utils.js +187 -0
  76. package/dist/cli/init/utils/file-utils.js.map +1 -0
  77. package/dist/cli/init/utils/index.d.ts +18 -0
  78. package/dist/cli/init/utils/index.d.ts.map +1 -0
  79. package/dist/cli/init/utils/index.js +48 -0
  80. package/dist/cli/init/utils/index.js.map +1 -0
  81. package/dist/cli/init/utils/log-utils.d.ts +47 -0
  82. package/dist/cli/init/utils/log-utils.d.ts.map +1 -0
  83. package/dist/cli/init/utils/log-utils.js +68 -0
  84. package/dist/cli/init/utils/log-utils.js.map +1 -0
  85. package/dist/cli/init/utils/path-utils.d.ts +91 -0
  86. package/dist/cli/init/utils/path-utils.d.ts.map +1 -0
  87. package/dist/cli/init/utils/path-utils.js +208 -0
  88. package/dist/cli/init/utils/path-utils.js.map +1 -0
  89. package/dist/cli/init/utils/validation-utils.d.ts +44 -0
  90. package/dist/cli/init/utils/validation-utils.d.ts.map +1 -0
  91. package/dist/cli/init/utils/validation-utils.js +68 -0
  92. package/dist/cli/init/utils/validation-utils.js.map +1 -0
  93. package/dist/cli/init/utils.d.ts +183 -0
  94. package/dist/cli/init/utils.d.ts.map +1 -0
  95. package/dist/cli/init/utils.js +354 -0
  96. package/dist/cli/init/utils.js.map +1 -0
  97. package/dist/components/Dashboard/Dashboard.d.ts +4 -0
  98. package/dist/components/Dashboard/Dashboard.d.ts.map +1 -0
  99. package/dist/components/Dashboard/Dashboard.js +148 -0
  100. package/dist/components/Dashboard/Dashboard.js.map +1 -0
  101. package/dist/components/Dashboard/DashboardHeader.d.ts +4 -0
  102. package/dist/components/Dashboard/DashboardHeader.d.ts.map +1 -0
  103. package/dist/components/Dashboard/DashboardHeader.js +138 -0
  104. package/dist/components/Dashboard/DashboardHeader.js.map +1 -0
  105. package/dist/constitution/evaluators/ast-evaluator.d.ts +42 -0
  106. package/dist/constitution/evaluators/ast-evaluator.d.ts.map +1 -0
  107. package/dist/constitution/evaluators/ast-evaluator.js +303 -0
  108. package/dist/constitution/evaluators/ast-evaluator.js.map +1 -0
  109. package/dist/constitution/evaluators/base.d.ts +144 -0
  110. package/dist/constitution/evaluators/base.d.ts.map +1 -0
  111. package/dist/constitution/evaluators/base.js +144 -0
  112. package/dist/constitution/evaluators/base.js.map +1 -0
  113. package/dist/constitution/evaluators/index.d.ts +19 -0
  114. package/dist/constitution/evaluators/index.d.ts.map +1 -0
  115. package/dist/constitution/evaluators/index.js +56 -0
  116. package/dist/constitution/evaluators/index.js.map +1 -0
  117. package/dist/constitution/evaluators/metric-evaluator.d.ts +59 -0
  118. package/dist/constitution/evaluators/metric-evaluator.d.ts.map +1 -0
  119. package/dist/constitution/evaluators/metric-evaluator.js +195 -0
  120. package/dist/constitution/evaluators/metric-evaluator.js.map +1 -0
  121. package/dist/constitution/evaluators/pattern-evaluator.d.ts +66 -0
  122. package/dist/constitution/evaluators/pattern-evaluator.d.ts.map +1 -0
  123. package/dist/constitution/evaluators/pattern-evaluator.js +221 -0
  124. package/dist/constitution/evaluators/pattern-evaluator.js.map +1 -0
  125. package/dist/constitution/evaluators/semantic-evaluator.d.ts +68 -0
  126. package/dist/constitution/evaluators/semantic-evaluator.d.ts.map +1 -0
  127. package/dist/constitution/evaluators/semantic-evaluator.js +250 -0
  128. package/dist/constitution/evaluators/semantic-evaluator.js.map +1 -0
  129. package/dist/contexts/DashboardContext.d.ts +41 -0
  130. package/dist/contexts/DashboardContext.d.ts.map +1 -0
  131. package/dist/contexts/DashboardContext.js +187 -0
  132. package/dist/contexts/DashboardContext.js.map +1 -0
  133. package/dist/core/memory/SwarmMemoryManager.d.ts +40 -0
  134. package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
  135. package/dist/core/memory/SwarmMemoryManager.js +291 -120
  136. package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
  137. package/dist/hooks/useKeyboardShortcuts.d.ts +12 -0
  138. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  139. package/dist/hooks/useKeyboardShortcuts.js +69 -0
  140. package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
  141. package/dist/telemetry/instrumentation/agent.d.ts +158 -0
  142. package/dist/telemetry/instrumentation/agent.d.ts.map +1 -0
  143. package/dist/telemetry/instrumentation/agent.js +372 -0
  144. package/dist/telemetry/instrumentation/agent.js.map +1 -0
  145. package/dist/telemetry/instrumentation/index.d.ts +24 -0
  146. package/dist/telemetry/instrumentation/index.d.ts.map +1 -0
  147. package/dist/telemetry/instrumentation/index.js +54 -0
  148. package/dist/telemetry/instrumentation/index.js.map +1 -0
  149. package/dist/telemetry/instrumentation/memory.d.ts +313 -0
  150. package/dist/telemetry/instrumentation/memory.d.ts.map +1 -0
  151. package/dist/telemetry/instrumentation/memory.js +552 -0
  152. package/dist/telemetry/instrumentation/memory.js.map +1 -0
  153. package/dist/telemetry/instrumentation/task.d.ts +146 -0
  154. package/dist/telemetry/instrumentation/task.d.ts.map +1 -0
  155. package/dist/telemetry/instrumentation/task.js +305 -0
  156. package/dist/telemetry/instrumentation/task.js.map +1 -0
  157. package/dist/telemetry/metrics/collectors/cost.d.ts +246 -0
  158. package/dist/telemetry/metrics/collectors/cost.d.ts.map +1 -0
  159. package/dist/telemetry/metrics/collectors/cost.js +526 -0
  160. package/dist/telemetry/metrics/collectors/cost.js.map +1 -0
  161. package/dist/telemetry/metrics/collectors/pricing-config.d.ts +87 -0
  162. package/dist/telemetry/metrics/collectors/pricing-config.d.ts.map +1 -0
  163. package/dist/telemetry/metrics/collectors/pricing-config.js +207 -0
  164. package/dist/telemetry/metrics/collectors/pricing-config.js.map +1 -0
  165. package/dist/telemetry/metrics/index.d.ts +4 -1
  166. package/dist/telemetry/metrics/index.d.ts.map +1 -1
  167. package/dist/telemetry/metrics/index.js +18 -2
  168. package/dist/telemetry/metrics/index.js.map +1 -1
  169. package/dist/telemetry/types.d.ts +1 -1
  170. package/dist/telemetry/types.d.ts.map +1 -1
  171. package/dist/visualization/api/RestEndpoints.d.ts +136 -0
  172. package/dist/visualization/api/RestEndpoints.d.ts.map +1 -0
  173. package/dist/visualization/api/RestEndpoints.js +428 -0
  174. package/dist/visualization/api/RestEndpoints.js.map +1 -0
  175. package/dist/visualization/api/WebSocketServer.d.ts +165 -0
  176. package/dist/visualization/api/WebSocketServer.d.ts.map +1 -0
  177. package/dist/visualization/api/WebSocketServer.js +518 -0
  178. package/dist/visualization/api/WebSocketServer.js.map +1 -0
  179. package/dist/visualization/core/DataTransformer.d.ts +89 -0
  180. package/dist/visualization/core/DataTransformer.d.ts.map +1 -0
  181. package/dist/visualization/core/DataTransformer.js +478 -0
  182. package/dist/visualization/core/DataTransformer.js.map +1 -0
  183. package/dist/visualization/index.d.ts +92 -0
  184. package/dist/visualization/index.d.ts.map +1 -0
  185. package/dist/visualization/index.js +121 -0
  186. package/dist/visualization/index.js.map +1 -0
  187. package/dist/visualization/types.d.ts +148 -0
  188. package/dist/visualization/types.d.ts.map +1 -0
  189. package/dist/visualization/types.js +7 -0
  190. package/dist/visualization/types.js.map +1 -0
  191. package/dist/voting/consensus.d.ts +87 -0
  192. package/dist/voting/consensus.d.ts.map +1 -0
  193. package/dist/voting/consensus.js +568 -0
  194. package/dist/voting/consensus.js.map +1 -0
  195. package/dist/voting/index.d.ts +12 -0
  196. package/dist/voting/index.d.ts.map +1 -0
  197. package/dist/voting/index.js +36 -0
  198. package/dist/voting/index.js.map +1 -0
  199. package/dist/voting/orchestrator.d.ts +65 -0
  200. package/dist/voting/orchestrator.d.ts.map +1 -0
  201. package/dist/voting/orchestrator.js +306 -0
  202. package/dist/voting/orchestrator.js.map +1 -0
  203. package/dist/voting/panel-assembly.d.ts +54 -0
  204. package/dist/voting/panel-assembly.d.ts.map +1 -0
  205. package/dist/voting/panel-assembly.js +192 -0
  206. package/dist/voting/panel-assembly.js.map +1 -0
  207. package/dist/voting/protocol.d.ts +119 -0
  208. package/dist/voting/protocol.d.ts.map +1 -0
  209. package/dist/voting/protocol.js +18 -0
  210. package/dist/voting/protocol.js.map +1 -0
  211. package/dist/voting/types.d.ts +125 -0
  212. package/dist/voting/types.d.ts.map +1 -0
  213. package/dist/voting/types.js +7 -0
  214. package/dist/voting/types.js.map +1 -0
  215. package/package.json +27 -2
@@ -47,6 +47,8 @@ Object.defineProperty(exports, "Permission", { enumerable: true, get: function (
47
47
  Object.defineProperty(exports, "AccessControlError", { enumerable: true, get: function () { return AccessControl_1.AccessControlError; } });
48
48
  const AgentDBManager_1 = require("./AgentDBManager");
49
49
  const PatternCache_1 = require("./PatternCache");
50
+ const memory_1 = require("../../telemetry/instrumentation/memory");
51
+ const types_1 = require("../../types");
50
52
  /**
51
53
  * SwarmMemoryManager - Manages persistent memory for agent swarm coordination
52
54
  *
@@ -203,6 +205,18 @@ class SwarmMemoryManager {
203
205
  agent_id TEXT
204
206
  )
205
207
  `);
208
+ // Migration: Add agent_id column if it doesn't exist (for existing databases)
209
+ // SQLite doesn't support IF NOT EXISTS for columns, so check first
210
+ try {
211
+ const tableInfo = this.queryAll(`PRAGMA table_info(patterns)`);
212
+ const hasAgentId = tableInfo.some(col => col.name === 'agent_id');
213
+ if (!hasAgentId) {
214
+ await this.run(`ALTER TABLE patterns ADD COLUMN agent_id TEXT`);
215
+ }
216
+ }
217
+ catch (e) {
218
+ // Ignore errors - column might already exist
219
+ }
206
220
  // Create indexes for O(log n) pattern queries (Issue #57)
207
221
  await this.run(`
208
222
  CREATE INDEX IF NOT EXISTS idx_patterns_agent_confidence
@@ -401,6 +415,16 @@ class SwarmMemoryManager {
401
415
  await this.run(`CREATE INDEX IF NOT EXISTS idx_learning_metrics_agent ON learning_metrics(agent_id)`);
402
416
  this.initialized = true;
403
417
  }
418
+ /**
419
+ * Store a key-value pair in memory with OpenTelemetry instrumentation
420
+ *
421
+ * Automatically instruments the memory store operation with distributed tracing.
422
+ * Records namespace, key, value size, TTL, and operation performance metrics.
423
+ *
424
+ * @param key - Memory key
425
+ * @param value - Value to store (will be JSON serialized)
426
+ * @param options - Store options including partition, TTL, access control
427
+ */
404
428
  async store(key, value, options = {}) {
405
429
  // Auto-initialize if not initialized
406
430
  if (!this.initialized) {
@@ -412,44 +436,73 @@ class SwarmMemoryManager {
412
436
  const partition = options.partition || 'default';
413
437
  const owner = options.owner || 'system';
414
438
  const accessLevel = options.accessLevel || AccessControl_1.AccessLevel.PRIVATE;
415
- const createdAt = Date.now();
416
- const expiresAt = options.ttl ? createdAt + (options.ttl * 1000) : null;
417
- const metadata = options.metadata ? JSON.stringify(options.metadata) : null;
418
- // Check write permission if updating existing entry
419
- const existing = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
420
- if (existing && options.owner) {
421
- // Verify write permission
422
- const permCheck = this.accessControl.checkPermission({
423
- agentId: options.owner,
424
- resourceOwner: existing.owner,
425
- accessLevel: existing.access_level,
426
- permission: AccessControl_1.Permission.WRITE,
427
- teamId: options.teamId,
428
- resourceTeamId: existing.team_id,
429
- swarmId: options.swarmId,
430
- resourceSwarmId: existing.swarm_id
431
- });
432
- if (!permCheck.allowed) {
433
- throw new AccessControl_1.AccessControlError(`Write denied: ${permCheck.reason}`);
439
+ const valueJson = JSON.stringify(value);
440
+ const valueSize = valueJson.length;
441
+ // Create instrumentation span
442
+ const { span, context: spanContext } = memory_1.memorySpanManager.startStoreSpan({
443
+ agentId: { id: owner, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
444
+ namespace: partition,
445
+ key,
446
+ valueSize,
447
+ ttl: options.ttl,
448
+ });
449
+ const startTime = Date.now();
450
+ try {
451
+ const createdAt = Date.now();
452
+ const expiresAt = options.ttl ? createdAt + (options.ttl * 1000) : null;
453
+ const metadata = options.metadata ? JSON.stringify(options.metadata) : null;
454
+ // Check write permission if updating existing entry
455
+ const existing = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
456
+ if (existing && options.owner) {
457
+ // Verify write permission
458
+ const permCheck = this.accessControl.checkPermission({
459
+ agentId: options.owner,
460
+ resourceOwner: existing.owner,
461
+ accessLevel: existing.access_level,
462
+ permission: AccessControl_1.Permission.WRITE,
463
+ teamId: options.teamId,
464
+ resourceTeamId: existing.team_id,
465
+ swarmId: options.swarmId,
466
+ resourceSwarmId: existing.swarm_id
467
+ });
468
+ if (!permCheck.allowed) {
469
+ throw new AccessControl_1.AccessControlError(`Write denied: ${permCheck.reason}`);
470
+ }
434
471
  }
472
+ await this.run(`INSERT OR REPLACE INTO memory_entries
473
+ (key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id)
474
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
475
+ key,
476
+ partition,
477
+ valueJson,
478
+ metadata,
479
+ createdAt,
480
+ expiresAt,
481
+ owner,
482
+ accessLevel,
483
+ options.teamId || null,
484
+ options.swarmId || null
485
+ ]);
486
+ // Track modification for QUIC sync
487
+ const entryKey = `${partition}:${key}`;
488
+ this.lastModifiedTimestamps.set(entryKey, createdAt);
489
+ // Complete span successfully
490
+ const durationMs = Date.now() - startTime;
491
+ memory_1.memorySpanManager.completeStoreSpan(span, {
492
+ success: true,
493
+ durationMs,
494
+ });
495
+ }
496
+ catch (error) {
497
+ // Complete span with error
498
+ const durationMs = Date.now() - startTime;
499
+ memory_1.memorySpanManager.completeStoreSpan(span, {
500
+ success: false,
501
+ durationMs,
502
+ error: error,
503
+ });
504
+ throw error;
435
505
  }
436
- await this.run(`INSERT OR REPLACE INTO memory_entries
437
- (key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id)
438
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
439
- key,
440
- partition,
441
- JSON.stringify(value),
442
- metadata,
443
- createdAt,
444
- expiresAt,
445
- owner,
446
- accessLevel,
447
- options.teamId || null,
448
- options.swarmId || null
449
- ]);
450
- // Track modification for QUIC sync
451
- const entryKey = `${partition}:${key}`;
452
- this.lastModifiedTimestamps.set(entryKey, createdAt);
453
506
  }
454
507
  /**
455
508
  * Alias for store() method to maintain compatibility with MemoryStore interface
@@ -473,6 +526,16 @@ class SwarmMemoryManager {
473
526
  }
474
527
  return this.retrieve(key, options);
475
528
  }
529
+ /**
530
+ * Retrieve a value from memory with OpenTelemetry instrumentation
531
+ *
532
+ * Automatically instruments the memory retrieve operation with distributed tracing.
533
+ * Records namespace, key, whether the value was found, value size, and performance metrics.
534
+ *
535
+ * @param key - Memory key
536
+ * @param options - Retrieve options including partition, agentId for access control
537
+ * @returns Retrieved value or null if not found
538
+ */
476
539
  async retrieve(key, options = {}) {
477
540
  // Auto-initialize if not initialized
478
541
  if (!this.initialized) {
@@ -482,55 +545,35 @@ class SwarmMemoryManager {
482
545
  throw new Error('Memory manager not initialized. Call initialize() first.');
483
546
  }
484
547
  const partition = options.partition || 'default';
485
- const now = Date.now();
486
- let query = `SELECT value, owner, access_level, team_id, swarm_id
487
- FROM memory_entries WHERE key = ? AND partition = ?`;
488
- const params = [key, partition];
489
- if (!options.includeExpired) {
490
- query += ` AND (expires_at IS NULL OR expires_at > ?)`;
491
- params.push(now);
492
- }
493
- const row = await this.queryOne(query, params);
494
- if (!row) {
495
- return null;
496
- }
497
- // Check read permission if agentId provided
498
- if (options.agentId) {
499
- const permCheck = this.accessControl.checkPermission({
500
- agentId: options.agentId,
501
- resourceOwner: row.owner,
502
- accessLevel: row.access_level,
503
- permission: AccessControl_1.Permission.READ,
504
- teamId: options.teamId,
505
- resourceTeamId: row.team_id,
506
- swarmId: options.swarmId,
507
- resourceSwarmId: row.swarm_id,
508
- isSystemAgent: options.isSystemAgent
509
- });
510
- if (!permCheck.allowed) {
511
- throw new AccessControl_1.AccessControlError(`Read denied: ${permCheck.reason}`);
548
+ const agentId = options.agentId || 'system';
549
+ // Create instrumentation span
550
+ const { span, context: spanContext } = memory_1.memorySpanManager.startRetrieveSpan({
551
+ agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
552
+ namespace: partition,
553
+ key,
554
+ });
555
+ const startTime = Date.now();
556
+ try {
557
+ const now = Date.now();
558
+ let query = `SELECT value, owner, access_level, team_id, swarm_id
559
+ FROM memory_entries WHERE key = ? AND partition = ?`;
560
+ const params = [key, partition];
561
+ if (!options.includeExpired) {
562
+ query += ` AND (expires_at IS NULL OR expires_at > ?)`;
563
+ params.push(now);
512
564
  }
513
- }
514
- return JSON.parse(row.value);
515
- }
516
- async query(pattern, options = {}) {
517
- if (!this.db) {
518
- throw new Error('Memory manager not initialized');
519
- }
520
- const partition = options.partition || 'default';
521
- const now = Date.now();
522
- let query = `SELECT key, value, partition, created_at, expires_at, owner, access_level, team_id, swarm_id
523
- FROM memory_entries
524
- WHERE partition = ? AND key LIKE ?`;
525
- const params = [partition, pattern];
526
- if (!options.includeExpired) {
527
- query += ` AND (expires_at IS NULL OR expires_at > ?)`;
528
- params.push(now);
529
- }
530
- const rows = await this.queryAll(query, params);
531
- // Filter by access control if agentId provided
532
- const filteredRows = options.agentId
533
- ? rows.filter((row) => {
565
+ const row = await this.queryOne(query, params);
566
+ if (!row) {
567
+ // Complete span - not found
568
+ const durationMs = Date.now() - startTime;
569
+ memory_1.memorySpanManager.completeRetrieveSpan(span, {
570
+ found: false,
571
+ durationMs,
572
+ });
573
+ return null;
574
+ }
575
+ // Check read permission if agentId provided
576
+ if (options.agentId) {
534
577
  const permCheck = this.accessControl.checkPermission({
535
578
  agentId: options.agentId,
536
579
  resourceOwner: row.owner,
@@ -542,50 +585,178 @@ class SwarmMemoryManager {
542
585
  resourceSwarmId: row.swarm_id,
543
586
  isSystemAgent: options.isSystemAgent
544
587
  });
545
- return permCheck.allowed;
546
- })
547
- : rows;
548
- return filteredRows.map((row) => ({
549
- key: row.key,
550
- value: JSON.parse(row.value),
551
- partition: row.partition,
552
- createdAt: row.created_at,
553
- expiresAt: row.expires_at,
554
- owner: row.owner,
555
- accessLevel: row.access_level,
556
- teamId: row.team_id,
557
- swarmId: row.swarm_id
558
- }));
588
+ if (!permCheck.allowed) {
589
+ throw new AccessControl_1.AccessControlError(`Read denied: ${permCheck.reason}`);
590
+ }
591
+ }
592
+ const valueSize = row.value.length;
593
+ const parsedValue = JSON.parse(row.value);
594
+ // Complete span successfully
595
+ const durationMs = Date.now() - startTime;
596
+ memory_1.memorySpanManager.completeRetrieveSpan(span, {
597
+ found: true,
598
+ valueSize,
599
+ durationMs,
600
+ });
601
+ return parsedValue;
602
+ }
603
+ catch (error) {
604
+ // Complete span with error
605
+ const durationMs = Date.now() - startTime;
606
+ memory_1.memorySpanManager.completeRetrieveSpan(span, {
607
+ found: false,
608
+ durationMs,
609
+ error: error,
610
+ });
611
+ throw error;
612
+ }
613
+ }
614
+ /**
615
+ * Query/search memory entries by pattern with OpenTelemetry instrumentation
616
+ *
617
+ * Automatically instruments the memory search operation with distributed tracing.
618
+ * Records namespace, search pattern, result count, and performance metrics.
619
+ *
620
+ * @param pattern - SQL LIKE pattern for key matching
621
+ * @param options - Retrieve options including partition, agentId for access control
622
+ * @returns Array of matching memory entries
623
+ */
624
+ async query(pattern, options = {}) {
625
+ if (!this.db) {
626
+ throw new Error('Memory manager not initialized');
627
+ }
628
+ const partition = options.partition || 'default';
629
+ const agentId = options.agentId || 'system';
630
+ // Create instrumentation span
631
+ const { span, context: spanContext } = memory_1.memorySpanManager.startSearchSpan({
632
+ agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
633
+ namespace: partition,
634
+ pattern,
635
+ });
636
+ const startTime = Date.now();
637
+ try {
638
+ const now = Date.now();
639
+ let query = `SELECT key, value, partition, created_at, expires_at, owner, access_level, team_id, swarm_id
640
+ FROM memory_entries
641
+ WHERE partition = ? AND key LIKE ?`;
642
+ const params = [partition, pattern];
643
+ if (!options.includeExpired) {
644
+ query += ` AND (expires_at IS NULL OR expires_at > ?)`;
645
+ params.push(now);
646
+ }
647
+ const rows = await this.queryAll(query, params);
648
+ // Filter by access control if agentId provided
649
+ const filteredRows = options.agentId
650
+ ? rows.filter((row) => {
651
+ const permCheck = this.accessControl.checkPermission({
652
+ agentId: options.agentId,
653
+ resourceOwner: row.owner,
654
+ accessLevel: row.access_level,
655
+ permission: AccessControl_1.Permission.READ,
656
+ teamId: options.teamId,
657
+ resourceTeamId: row.team_id,
658
+ swarmId: options.swarmId,
659
+ resourceSwarmId: row.swarm_id,
660
+ isSystemAgent: options.isSystemAgent
661
+ });
662
+ return permCheck.allowed;
663
+ })
664
+ : rows;
665
+ const results = filteredRows.map((row) => ({
666
+ key: row.key,
667
+ value: JSON.parse(row.value),
668
+ partition: row.partition,
669
+ createdAt: row.created_at,
670
+ expiresAt: row.expires_at,
671
+ owner: row.owner,
672
+ accessLevel: row.access_level,
673
+ teamId: row.team_id,
674
+ swarmId: row.swarm_id
675
+ }));
676
+ // Complete span successfully
677
+ const durationMs = Date.now() - startTime;
678
+ memory_1.memorySpanManager.completeSearchSpan(span, {
679
+ resultCount: results.length,
680
+ durationMs,
681
+ });
682
+ return results;
683
+ }
684
+ catch (error) {
685
+ // Complete span with error
686
+ const durationMs = Date.now() - startTime;
687
+ memory_1.memorySpanManager.completeSearchSpan(span, {
688
+ resultCount: 0,
689
+ durationMs,
690
+ error: error,
691
+ });
692
+ throw error;
693
+ }
559
694
  }
695
+ /**
696
+ * Delete a key from memory with OpenTelemetry instrumentation
697
+ *
698
+ * Automatically instruments the memory delete operation with distributed tracing.
699
+ * Records namespace, key, and operation performance metrics.
700
+ *
701
+ * @param key - Memory key to delete
702
+ * @param partition - Memory partition (namespace)
703
+ * @param options - Delete options including agentId for access control
704
+ */
560
705
  async delete(key, partition = 'default', options = {}) {
561
706
  if (!this.db) {
562
707
  throw new Error('Memory manager not initialized');
563
708
  }
564
- // Check delete permission if agentId provided
565
- if (options.agentId) {
566
- const row = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
567
- if (row) {
568
- const permCheck = this.accessControl.checkPermission({
569
- agentId: options.agentId,
570
- resourceOwner: row.owner,
571
- accessLevel: row.access_level,
572
- permission: AccessControl_1.Permission.DELETE,
573
- teamId: options.teamId,
574
- resourceTeamId: row.team_id,
575
- swarmId: options.swarmId,
576
- resourceSwarmId: row.swarm_id,
577
- isSystemAgent: options.isSystemAgent
578
- });
579
- if (!permCheck.allowed) {
580
- throw new AccessControl_1.AccessControlError(`Delete denied: ${permCheck.reason}`);
709
+ const agentId = options.agentId || 'system';
710
+ // Create instrumentation span
711
+ const { span, context: spanContext } = memory_1.memorySpanManager.startDeleteSpan({
712
+ agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
713
+ namespace: partition,
714
+ key,
715
+ });
716
+ const startTime = Date.now();
717
+ try {
718
+ // Check delete permission if agentId provided
719
+ if (options.agentId) {
720
+ const row = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
721
+ if (row) {
722
+ const permCheck = this.accessControl.checkPermission({
723
+ agentId: options.agentId,
724
+ resourceOwner: row.owner,
725
+ accessLevel: row.access_level,
726
+ permission: AccessControl_1.Permission.DELETE,
727
+ teamId: options.teamId,
728
+ resourceTeamId: row.team_id,
729
+ swarmId: options.swarmId,
730
+ resourceSwarmId: row.swarm_id,
731
+ isSystemAgent: options.isSystemAgent
732
+ });
733
+ if (!permCheck.allowed) {
734
+ throw new AccessControl_1.AccessControlError(`Delete denied: ${permCheck.reason}`);
735
+ }
581
736
  }
582
737
  }
738
+ await this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
739
+ // Clean up ACL if exists
740
+ const resourceId = `${partition}:${key}`;
741
+ await this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]);
742
+ this.aclCache.delete(resourceId);
743
+ // Complete span successfully
744
+ const durationMs = Date.now() - startTime;
745
+ memory_1.memorySpanManager.completeDeleteSpan(span, {
746
+ success: true,
747
+ durationMs,
748
+ });
749
+ }
750
+ catch (error) {
751
+ // Complete span with error
752
+ const durationMs = Date.now() - startTime;
753
+ memory_1.memorySpanManager.completeDeleteSpan(span, {
754
+ success: false,
755
+ durationMs,
756
+ error: error,
757
+ });
758
+ throw error;
583
759
  }
584
- await this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
585
- // Clean up ACL if exists
586
- const resourceId = `${partition}:${key}`;
587
- await this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]);
588
- this.aclCache.delete(resourceId);
589
760
  }
590
761
  async clear(partition = 'default') {
591
762
  if (!this.db) {