agentic-qe 1.9.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/.claude/agents/qe-api-contract-validator.md +95 -1336
  2. package/.claude/agents/qe-chaos-engineer.md +152 -1211
  3. package/.claude/agents/qe-code-complexity.md +144 -707
  4. package/.claude/agents/qe-coverage-analyzer.md +147 -743
  5. package/.claude/agents/qe-deployment-readiness.md +143 -1496
  6. package/.claude/agents/qe-flaky-test-hunter.md +132 -1529
  7. package/.claude/agents/qe-fleet-commander.md +12 -12
  8. package/.claude/agents/qe-performance-tester.md +150 -886
  9. package/.claude/agents/qe-production-intelligence.md +155 -1396
  10. package/.claude/agents/qe-quality-analyzer.md +6 -6
  11. package/.claude/agents/qe-quality-gate.md +151 -648
  12. package/.claude/agents/qe-regression-risk-analyzer.md +132 -1150
  13. package/.claude/agents/qe-requirements-validator.md +149 -932
  14. package/.claude/agents/qe-security-scanner.md +157 -797
  15. package/.claude/agents/qe-test-data-architect.md +96 -1365
  16. package/.claude/agents/qe-test-executor.md +8 -8
  17. package/.claude/agents/qe-test-generator.md +145 -1540
  18. package/.claude/agents/qe-visual-tester.md +153 -1257
  19. package/.claude/agents/qx-partner.md +235 -0
  20. package/.claude/agents/subagents/qe-code-reviewer.md +40 -136
  21. package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +40 -480
  22. package/.claude/agents/subagents/qe-data-generator.md +41 -125
  23. package/.claude/agents/subagents/qe-flaky-investigator.md +55 -411
  24. package/.claude/agents/subagents/qe-integration-tester.md +53 -141
  25. package/.claude/agents/subagents/qe-performance-validator.md +54 -130
  26. package/.claude/agents/subagents/qe-security-auditor.md +56 -114
  27. package/.claude/agents/subagents/qe-test-data-architect-sub.md +57 -548
  28. package/.claude/agents/subagents/qe-test-implementer.md +58 -551
  29. package/.claude/agents/subagents/qe-test-refactorer.md +65 -722
  30. package/.claude/agents/subagents/qe-test-writer.md +63 -726
  31. package/.claude/skills/skills-manifest.json +632 -0
  32. package/.claude/skills/testability-scoring/README.md +71 -0
  33. package/.claude/skills/testability-scoring/SKILL.md +611 -0
  34. package/.claude/skills/testability-scoring/resources/templates/config.template.js +84 -0
  35. package/.claude/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
  36. package/.claude/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
  37. package/.claude/skills/testability-scoring/scripts/run-assessment.sh +70 -0
  38. package/CHANGELOG.md +116 -0
  39. package/README.md +59 -7
  40. package/config/.env.otel.example +25 -0
  41. package/config/OTEL-QUICK-REFERENCE.md +137 -0
  42. package/config/README-OTEL.md +222 -0
  43. package/config/alerting-rules.yml +518 -0
  44. package/config/docker-compose.otel.yml +187 -0
  45. package/config/grafana/dashboards/agentic-qe-overview.json +286 -0
  46. package/config/grafana/provisioning/dashboards/dashboards.yml +19 -0
  47. package/config/grafana/provisioning/datasources/datasources.yml +53 -0
  48. package/config/otel-collector-config.yaml.example +145 -0
  49. package/config/prometheus.yml.example +106 -0
  50. package/dist/agents/QXPartnerAgent.d.ts +139 -0
  51. package/dist/agents/QXPartnerAgent.d.ts.map +1 -0
  52. package/dist/agents/QXPartnerAgent.js +769 -0
  53. package/dist/agents/QXPartnerAgent.js.map +1 -0
  54. package/dist/agents/index.d.ts +1 -0
  55. package/dist/agents/index.d.ts.map +1 -1
  56. package/dist/agents/index.js +82 -2
  57. package/dist/agents/index.js.map +1 -1
  58. package/dist/alerting/AlertManager.d.ts +120 -0
  59. package/dist/alerting/AlertManager.d.ts.map +1 -0
  60. package/dist/alerting/AlertManager.js +345 -0
  61. package/dist/alerting/AlertManager.js.map +1 -0
  62. package/dist/alerting/FeedbackRouter.d.ts +98 -0
  63. package/dist/alerting/FeedbackRouter.d.ts.map +1 -0
  64. package/dist/alerting/FeedbackRouter.js +331 -0
  65. package/dist/alerting/FeedbackRouter.js.map +1 -0
  66. package/dist/alerting/StrategyApplicator.d.ts +120 -0
  67. package/dist/alerting/StrategyApplicator.d.ts.map +1 -0
  68. package/dist/alerting/StrategyApplicator.js +299 -0
  69. package/dist/alerting/StrategyApplicator.js.map +1 -0
  70. package/dist/alerting/index.d.ts +68 -0
  71. package/dist/alerting/index.d.ts.map +1 -0
  72. package/dist/alerting/index.js +112 -0
  73. package/dist/alerting/index.js.map +1 -0
  74. package/dist/alerting/types.d.ts +118 -0
  75. package/dist/alerting/types.d.ts.map +1 -0
  76. package/dist/alerting/types.js +11 -0
  77. package/dist/alerting/types.js.map +1 -0
  78. package/dist/cli/commands/debug/agent.d.ts.map +1 -1
  79. package/dist/cli/commands/debug/agent.js +19 -6
  80. package/dist/cli/commands/debug/agent.js.map +1 -1
  81. package/dist/cli/commands/debug/health-check.js +20 -7
  82. package/dist/cli/commands/debug/health-check.js.map +1 -1
  83. package/dist/cli/commands/init-claude-md-template.d.ts +1 -0
  84. package/dist/cli/commands/init-claude-md-template.d.ts.map +1 -1
  85. package/dist/cli/commands/init-claude-md-template.js +4 -3
  86. package/dist/cli/commands/init-claude-md-template.js.map +1 -1
  87. package/dist/cli/commands/workflow/cancel.d.ts.map +1 -1
  88. package/dist/cli/commands/workflow/cancel.js +4 -3
  89. package/dist/cli/commands/workflow/cancel.js.map +1 -1
  90. package/dist/cli/commands/workflow/list.d.ts.map +1 -1
  91. package/dist/cli/commands/workflow/list.js +4 -3
  92. package/dist/cli/commands/workflow/list.js.map +1 -1
  93. package/dist/cli/commands/workflow/pause.d.ts.map +1 -1
  94. package/dist/cli/commands/workflow/pause.js +4 -3
  95. package/dist/cli/commands/workflow/pause.js.map +1 -1
  96. package/dist/cli/init/claude-config.d.ts.map +1 -1
  97. package/dist/cli/init/claude-config.js +13 -13
  98. package/dist/cli/init/claude-config.js.map +1 -1
  99. package/dist/cli/init/claude-md.d.ts.map +1 -1
  100. package/dist/cli/init/claude-md.js +44 -2
  101. package/dist/cli/init/claude-md.js.map +1 -1
  102. package/dist/cli/init/database-init.js +1 -1
  103. package/dist/cli/init/index.d.ts.map +1 -1
  104. package/dist/cli/init/index.js +13 -6
  105. package/dist/cli/init/index.js.map +1 -1
  106. package/dist/cli/init/skills.d.ts.map +1 -1
  107. package/dist/cli/init/skills.js +2 -1
  108. package/dist/cli/init/skills.js.map +1 -1
  109. package/dist/core/memory/AgentDBIntegration.d.ts +24 -6
  110. package/dist/core/memory/AgentDBIntegration.d.ts.map +1 -1
  111. package/dist/core/memory/AgentDBIntegration.js +66 -10
  112. package/dist/core/memory/AgentDBIntegration.js.map +1 -1
  113. package/dist/core/memory/IPatternStore.d.ts +209 -0
  114. package/dist/core/memory/IPatternStore.d.ts.map +1 -0
  115. package/dist/core/memory/IPatternStore.js +15 -0
  116. package/dist/core/memory/IPatternStore.js.map +1 -0
  117. package/dist/core/memory/MigrationTools.d.ts +192 -0
  118. package/dist/core/memory/MigrationTools.d.ts.map +1 -0
  119. package/dist/core/memory/MigrationTools.js +615 -0
  120. package/dist/core/memory/MigrationTools.js.map +1 -0
  121. package/dist/core/memory/NeuralEnhancement.d.ts +154 -0
  122. package/dist/core/memory/NeuralEnhancement.d.ts.map +1 -0
  123. package/dist/core/memory/NeuralEnhancement.js +598 -0
  124. package/dist/core/memory/NeuralEnhancement.js.map +1 -0
  125. package/dist/core/memory/PatternStoreFactory.d.ts +143 -0
  126. package/dist/core/memory/PatternStoreFactory.d.ts.map +1 -0
  127. package/dist/core/memory/PatternStoreFactory.js +370 -0
  128. package/dist/core/memory/PatternStoreFactory.js.map +1 -0
  129. package/dist/core/memory/RealAgentDBAdapter.d.ts +1 -0
  130. package/dist/core/memory/RealAgentDBAdapter.d.ts.map +1 -1
  131. package/dist/core/memory/RealAgentDBAdapter.js +28 -20
  132. package/dist/core/memory/RealAgentDBAdapter.js.map +1 -1
  133. package/dist/core/memory/RuVectorPatternStore.d.ts +198 -0
  134. package/dist/core/memory/RuVectorPatternStore.d.ts.map +1 -0
  135. package/dist/core/memory/RuVectorPatternStore.js +605 -0
  136. package/dist/core/memory/RuVectorPatternStore.js.map +1 -0
  137. package/dist/core/memory/SelfHealingMonitor.d.ts +186 -0
  138. package/dist/core/memory/SelfHealingMonitor.d.ts.map +1 -0
  139. package/dist/core/memory/SelfHealingMonitor.js +451 -0
  140. package/dist/core/memory/SelfHealingMonitor.js.map +1 -0
  141. package/dist/core/memory/SwarmMemoryManager.d.ts +62 -0
  142. package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
  143. package/dist/core/memory/SwarmMemoryManager.js +97 -0
  144. package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
  145. package/dist/core/memory/UnifiedMemoryCoordinator.d.ts +341 -0
  146. package/dist/core/memory/UnifiedMemoryCoordinator.d.ts.map +1 -0
  147. package/dist/core/memory/UnifiedMemoryCoordinator.js +986 -0
  148. package/dist/core/memory/UnifiedMemoryCoordinator.js.map +1 -0
  149. package/dist/core/memory/index.d.ts +16 -0
  150. package/dist/core/memory/index.d.ts.map +1 -1
  151. package/dist/core/memory/index.js +58 -1
  152. package/dist/core/memory/index.js.map +1 -1
  153. package/dist/core/optimization/SwarmOptimizer.d.ts +185 -0
  154. package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -0
  155. package/dist/core/optimization/SwarmOptimizer.js +631 -0
  156. package/dist/core/optimization/SwarmOptimizer.js.map +1 -0
  157. package/dist/core/optimization/index.d.ts +9 -0
  158. package/dist/core/optimization/index.d.ts.map +1 -0
  159. package/dist/core/optimization/index.js +25 -0
  160. package/dist/core/optimization/index.js.map +1 -0
  161. package/dist/core/optimization/types.d.ts +53 -0
  162. package/dist/core/optimization/types.d.ts.map +1 -0
  163. package/dist/core/optimization/types.js +6 -0
  164. package/dist/core/optimization/types.js.map +1 -0
  165. package/dist/core/orchestration/PriorityQueue.d.ts +54 -0
  166. package/dist/core/orchestration/PriorityQueue.d.ts.map +1 -0
  167. package/dist/core/orchestration/PriorityQueue.js +122 -0
  168. package/dist/core/orchestration/PriorityQueue.js.map +1 -0
  169. package/dist/core/orchestration/WorkflowOrchestrator.d.ts +176 -0
  170. package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -0
  171. package/dist/core/orchestration/WorkflowOrchestrator.js +813 -0
  172. package/dist/core/orchestration/WorkflowOrchestrator.js.map +1 -0
  173. package/dist/core/orchestration/index.d.ts +7 -0
  174. package/dist/core/orchestration/index.d.ts.map +1 -0
  175. package/dist/core/orchestration/index.js +11 -0
  176. package/dist/core/orchestration/index.js.map +1 -0
  177. package/dist/core/orchestration/types.d.ts +96 -0
  178. package/dist/core/orchestration/types.d.ts.map +1 -0
  179. package/dist/core/orchestration/types.js +6 -0
  180. package/dist/core/orchestration/types.js.map +1 -0
  181. package/dist/core/skills/DynamicSkillLoader.d.ts +96 -0
  182. package/dist/core/skills/DynamicSkillLoader.d.ts.map +1 -0
  183. package/dist/core/skills/DynamicSkillLoader.js +353 -0
  184. package/dist/core/skills/DynamicSkillLoader.js.map +1 -0
  185. package/dist/core/skills/types.d.ts +118 -0
  186. package/dist/core/skills/types.d.ts.map +1 -0
  187. package/dist/core/skills/types.js +7 -0
  188. package/dist/core/skills/types.js.map +1 -0
  189. package/dist/core/transport/QUICTransport.d.ts +320 -0
  190. package/dist/core/transport/QUICTransport.d.ts.map +1 -0
  191. package/dist/core/transport/QUICTransport.js +711 -0
  192. package/dist/core/transport/QUICTransport.js.map +1 -0
  193. package/dist/core/transport/index.d.ts +40 -0
  194. package/dist/core/transport/index.d.ts.map +1 -0
  195. package/dist/core/transport/index.js +46 -0
  196. package/dist/core/transport/index.js.map +1 -0
  197. package/dist/core/transport/quic-loader.d.ts +123 -0
  198. package/dist/core/transport/quic-loader.d.ts.map +1 -0
  199. package/dist/core/transport/quic-loader.js +293 -0
  200. package/dist/core/transport/quic-loader.js.map +1 -0
  201. package/dist/core/transport/quic.d.ts +154 -0
  202. package/dist/core/transport/quic.d.ts.map +1 -0
  203. package/dist/core/transport/quic.js +214 -0
  204. package/dist/core/transport/quic.js.map +1 -0
  205. package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
  206. package/dist/mcp/services/AgentRegistry.js +4 -1
  207. package/dist/mcp/services/AgentRegistry.js.map +1 -1
  208. package/dist/reasoning/RuVectorReasoningAdapter.d.ts +232 -0
  209. package/dist/reasoning/RuVectorReasoningAdapter.d.ts.map +1 -0
  210. package/dist/reasoning/RuVectorReasoningAdapter.js +585 -0
  211. package/dist/reasoning/RuVectorReasoningAdapter.js.map +1 -0
  212. package/dist/reasoning/index.d.ts +2 -0
  213. package/dist/reasoning/index.d.ts.map +1 -1
  214. package/dist/reasoning/index.js +6 -1
  215. package/dist/reasoning/index.js.map +1 -1
  216. package/dist/reporting/ResultAggregator.d.ts +107 -0
  217. package/dist/reporting/ResultAggregator.d.ts.map +1 -0
  218. package/dist/reporting/ResultAggregator.js +435 -0
  219. package/dist/reporting/ResultAggregator.js.map +1 -0
  220. package/dist/reporting/index.d.ts +48 -0
  221. package/dist/reporting/index.d.ts.map +1 -0
  222. package/dist/reporting/index.js +154 -0
  223. package/dist/reporting/index.js.map +1 -0
  224. package/dist/reporting/reporters/ControlLoopReporter.d.ts +128 -0
  225. package/dist/reporting/reporters/ControlLoopReporter.d.ts.map +1 -0
  226. package/dist/reporting/reporters/ControlLoopReporter.js +417 -0
  227. package/dist/reporting/reporters/ControlLoopReporter.js.map +1 -0
  228. package/dist/reporting/reporters/HumanReadableReporter.d.ts +140 -0
  229. package/dist/reporting/reporters/HumanReadableReporter.d.ts.map +1 -0
  230. package/dist/reporting/reporters/HumanReadableReporter.js +524 -0
  231. package/dist/reporting/reporters/HumanReadableReporter.js.map +1 -0
  232. package/dist/reporting/reporters/JSONReporter.d.ts +193 -0
  233. package/dist/reporting/reporters/JSONReporter.d.ts.map +1 -0
  234. package/dist/reporting/reporters/JSONReporter.js +324 -0
  235. package/dist/reporting/reporters/JSONReporter.js.map +1 -0
  236. package/dist/reporting/reporters/index.d.ts +14 -0
  237. package/dist/reporting/reporters/index.d.ts.map +1 -0
  238. package/dist/reporting/reporters/index.js +19 -0
  239. package/dist/reporting/reporters/index.js.map +1 -0
  240. package/dist/reporting/types.d.ts +427 -0
  241. package/dist/reporting/types.d.ts.map +1 -0
  242. package/dist/reporting/types.js +12 -0
  243. package/dist/reporting/types.js.map +1 -0
  244. package/dist/types/index.d.ts +2 -1
  245. package/dist/types/index.d.ts.map +1 -1
  246. package/dist/types/index.js +2 -0
  247. package/dist/types/index.js.map +1 -1
  248. package/dist/types/qx.d.ts +397 -0
  249. package/dist/types/qx.d.ts.map +1 -0
  250. package/dist/types/qx.js +71 -0
  251. package/dist/types/qx.js.map +1 -0
  252. package/dist/visualization/api/RestEndpoints.js +1 -1
  253. package/dist/visualization/api/RestEndpoints.js.map +1 -1
  254. package/dist/visualization/api/WebSocketServer.d.ts +44 -0
  255. package/dist/visualization/api/WebSocketServer.d.ts.map +1 -1
  256. package/dist/visualization/api/WebSocketServer.js +144 -23
  257. package/dist/visualization/api/WebSocketServer.js.map +1 -1
  258. package/dist/visualization/core/DataTransformer.d.ts +10 -0
  259. package/dist/visualization/core/DataTransformer.d.ts.map +1 -1
  260. package/dist/visualization/core/DataTransformer.js +60 -5
  261. package/dist/visualization/core/DataTransformer.js.map +1 -1
  262. package/dist/visualization/emit-event.d.ts +75 -0
  263. package/dist/visualization/emit-event.d.ts.map +1 -0
  264. package/dist/visualization/emit-event.js +213 -0
  265. package/dist/visualization/emit-event.js.map +1 -0
  266. package/dist/visualization/index.d.ts +1 -0
  267. package/dist/visualization/index.d.ts.map +1 -1
  268. package/dist/visualization/index.js +7 -1
  269. package/dist/visualization/index.js.map +1 -1
  270. package/docs/reference/skills.md +63 -1
  271. package/package.json +12 -4
@@ -0,0 +1,986 @@
1
+ "use strict";
2
+ /**
3
+ * UnifiedMemoryCoordinator - Single interface for all memory systems
4
+ *
5
+ * Integrates:
6
+ * - SwarmMemoryManager (cross-agent coordination with SQLite)
7
+ * - AgentDBService (vector database operations)
8
+ * - RuVectorPatternStore (high-performance pattern storage)
9
+ *
10
+ * Features:
11
+ * - Automatic SQLite ↔ JSON fallback
12
+ * - Memory health monitoring
13
+ * - Unified namespace management
14
+ * - Cross-system synchronization
15
+ * - Transparent backend switching
16
+ * - Metrics collection
17
+ *
18
+ * @module core/memory/UnifiedMemoryCoordinator
19
+ * @version 1.0.0
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.NamespacedCoordinator = exports.UnifiedMemoryCoordinator = void 0;
56
+ exports.createUnifiedMemoryCoordinator = createUnifiedMemoryCoordinator;
57
+ const Logger_1 = require("../../utils/Logger");
58
+ const SwarmMemoryManager_1 = require("./SwarmMemoryManager");
59
+ const AgentDBService_1 = require("./AgentDBService");
60
+ const RuVectorPatternStore_1 = require("./RuVectorPatternStore");
61
+ const RuVectorPatternStore_2 = require("./RuVectorPatternStore");
62
+ const path = __importStar(require("path"));
63
+ const fs = __importStar(require("fs-extra"));
64
+ /**
65
+ * UnifiedMemoryCoordinator - Unified interface for all memory systems
66
+ */
67
+ class UnifiedMemoryCoordinator {
68
+ constructor(config = {}) {
69
+ this.logger = Logger_1.Logger.getInstance();
70
+ this.config = {
71
+ preferredBackend: config.preferredBackend ?? 'auto',
72
+ enableFallback: config.enableFallback ?? true,
73
+ syncInterval: config.syncInterval ?? 60000, // 1 minute
74
+ healthCheckInterval: config.healthCheckInterval ?? 30000, // 30 seconds
75
+ maxRetries: config.maxRetries ?? 3,
76
+ namespace: config.namespace ?? 'default',
77
+ dbPaths: config.dbPaths ?? {},
78
+ enableVectorOps: config.enableVectorOps ?? true,
79
+ vectorDimension: config.vectorDimension ?? 384,
80
+ };
81
+ this.jsonStore = new Map();
82
+ this.healthStatus = new Map();
83
+ this.syncInProgress = false;
84
+ this.activeBackend = 'json'; // Start with fallback
85
+ this.fallbackChain = [];
86
+ this.metrics = {
87
+ totalOperations: 0,
88
+ operationsByBackend: new Map(),
89
+ averageLatency: 0,
90
+ failoverCount: 0,
91
+ cacheHitRate: 0,
92
+ syncCount: 0,
93
+ errorCount: 0,
94
+ };
95
+ }
96
+ /**
97
+ * Initialize the memory coordinator
98
+ */
99
+ async initialize() {
100
+ this.logger.info('Initializing UnifiedMemoryCoordinator...');
101
+ try {
102
+ // Detect available backends
103
+ const availableBackends = await this.detectAvailableBackends();
104
+ this.logger.info('Available backends:', availableBackends);
105
+ // Initialize SwarmMemoryManager (always available)
106
+ await this.initializeSwarmMemory();
107
+ // Initialize AgentDB if available
108
+ if (availableBackends.includes('agentdb')) {
109
+ await this.initializeAgentDB();
110
+ }
111
+ // Initialize RuVector if available
112
+ if (availableBackends.includes('vector') && this.config.enableVectorOps) {
113
+ await this.initializeVectorStore();
114
+ }
115
+ // Select optimal backend
116
+ this.activeBackend = await this.selectOptimalBackend();
117
+ this.logger.info(`Active backend: ${this.activeBackend}`);
118
+ // Build fallback chain
119
+ this.fallbackChain = this.buildFallbackChain(this.activeBackend);
120
+ this.logger.info('Fallback chain:', this.fallbackChain);
121
+ // Start health monitoring
122
+ this.startHealthMonitoring();
123
+ // Start periodic sync
124
+ if (this.config.syncInterval > 0) {
125
+ this.startPeriodicSync();
126
+ }
127
+ this.logger.info('UnifiedMemoryCoordinator initialized successfully');
128
+ }
129
+ catch (error) {
130
+ this.logger.error('Failed to initialize UnifiedMemoryCoordinator:', error);
131
+ throw error;
132
+ }
133
+ }
134
+ /**
135
+ * Detect available backends
136
+ */
137
+ async detectAvailableBackends() {
138
+ const backends = [];
139
+ // SQLite is always available via SwarmMemoryManager
140
+ backends.push('sqlite');
141
+ // Check AgentDB
142
+ try {
143
+ require('agentdb');
144
+ backends.push('agentdb');
145
+ }
146
+ catch {
147
+ this.logger.debug('AgentDB not available');
148
+ }
149
+ // Check RuVector
150
+ if ((0, RuVectorPatternStore_2.isRuVectorAvailable)()) {
151
+ backends.push('vector');
152
+ }
153
+ else {
154
+ this.logger.debug('RuVector not available');
155
+ }
156
+ // JSON is always available as fallback
157
+ backends.push('json');
158
+ return backends;
159
+ }
160
+ /**
161
+ * Initialize SwarmMemoryManager
162
+ */
163
+ async initializeSwarmMemory() {
164
+ try {
165
+ const dbPath = this.config.dbPaths?.swarm ??
166
+ path.join(process.cwd(), '.agentic-qe', 'memory.db');
167
+ await fs.ensureDir(path.dirname(dbPath));
168
+ this.swarmMemory = new SwarmMemoryManager_1.SwarmMemoryManager(dbPath);
169
+ await this.swarmMemory.initialize();
170
+ this.updateHealthStatus('sqlite', {
171
+ backend: 'sqlite',
172
+ status: 'healthy',
173
+ latency: 0,
174
+ lastCheck: new Date(),
175
+ errorCount: 0,
176
+ details: { dbPath },
177
+ });
178
+ this.logger.debug('SwarmMemoryManager initialized');
179
+ }
180
+ catch (error) {
181
+ this.logger.error('Failed to initialize SwarmMemoryManager:', error);
182
+ this.updateHealthStatus('sqlite', {
183
+ backend: 'sqlite',
184
+ status: 'failed',
185
+ latency: 0,
186
+ lastCheck: new Date(),
187
+ errorCount: 1,
188
+ details: { error: String(error) },
189
+ });
190
+ throw error;
191
+ }
192
+ }
193
+ /**
194
+ * Initialize AgentDB
195
+ */
196
+ async initializeAgentDB() {
197
+ try {
198
+ const dbPath = this.config.dbPaths?.agentdb ??
199
+ path.join(process.cwd(), '.agentic-qe', 'agentdb.db');
200
+ this.agentDB = new AgentDBService_1.AgentDBService({
201
+ dbPath,
202
+ embeddingDim: this.config.vectorDimension,
203
+ enableHNSW: true,
204
+ enableCache: true,
205
+ });
206
+ await this.agentDB.initialize();
207
+ this.updateHealthStatus('agentdb', {
208
+ backend: 'agentdb',
209
+ status: 'healthy',
210
+ latency: 0,
211
+ lastCheck: new Date(),
212
+ errorCount: 0,
213
+ details: { dbPath },
214
+ });
215
+ this.logger.debug('AgentDB initialized');
216
+ }
217
+ catch (error) {
218
+ this.logger.error('Failed to initialize AgentDB:', error);
219
+ this.updateHealthStatus('agentdb', {
220
+ backend: 'agentdb',
221
+ status: 'failed',
222
+ latency: 0,
223
+ lastCheck: new Date(),
224
+ errorCount: 1,
225
+ details: { error: String(error) },
226
+ });
227
+ }
228
+ }
229
+ /**
230
+ * Initialize RuVector store
231
+ */
232
+ async initializeVectorStore() {
233
+ try {
234
+ const dbPath = this.config.dbPaths?.ruvector ??
235
+ path.join(process.cwd(), '.agentic-qe', 'vectors.db');
236
+ this.vectorStore = new RuVectorPatternStore_1.RuVectorPatternStore({
237
+ dimension: this.config.vectorDimension,
238
+ metric: 'cosine',
239
+ storagePath: dbPath,
240
+ autoPersist: true,
241
+ enableMetrics: true,
242
+ });
243
+ await this.vectorStore.initialize();
244
+ this.updateHealthStatus('vector', {
245
+ backend: 'vector',
246
+ status: 'healthy',
247
+ latency: 0,
248
+ lastCheck: new Date(),
249
+ errorCount: 0,
250
+ details: { dbPath },
251
+ });
252
+ this.logger.debug('RuVector store initialized');
253
+ }
254
+ catch (error) {
255
+ this.logger.error('Failed to initialize RuVector store:', error);
256
+ this.updateHealthStatus('vector', {
257
+ backend: 'vector',
258
+ status: 'failed',
259
+ latency: 0,
260
+ lastCheck: new Date(),
261
+ errorCount: 1,
262
+ details: { error: String(error) },
263
+ });
264
+ }
265
+ }
266
+ /**
267
+ * Select optimal backend
268
+ */
269
+ async selectOptimalBackend() {
270
+ if (this.config.preferredBackend !== 'auto') {
271
+ const health = this.healthStatus.get(this.config.preferredBackend);
272
+ if (health && health.status === 'healthy') {
273
+ return this.config.preferredBackend;
274
+ }
275
+ }
276
+ // Auto-select based on health and capabilities
277
+ const priorities = ['sqlite', 'agentdb', 'vector', 'json'];
278
+ for (const backend of priorities) {
279
+ const health = this.healthStatus.get(backend);
280
+ if (health && health.status === 'healthy') {
281
+ return backend;
282
+ }
283
+ }
284
+ // Fallback to JSON
285
+ return 'json';
286
+ }
287
+ /**
288
+ * Build fallback chain
289
+ */
290
+ buildFallbackChain(primary) {
291
+ const chain = [primary];
292
+ const alternatives = ['sqlite', 'agentdb', 'vector', 'json'];
293
+ for (const backend of alternatives) {
294
+ if (backend !== primary) {
295
+ const health = this.healthStatus.get(backend);
296
+ if (health && health.status !== 'failed') {
297
+ chain.push(backend);
298
+ }
299
+ }
300
+ }
301
+ // Always have JSON as final fallback
302
+ if (!chain.includes('json')) {
303
+ chain.push('json');
304
+ }
305
+ return chain;
306
+ }
307
+ /**
308
+ * Store a key-value pair
309
+ */
310
+ async store(key, value, ttl) {
311
+ const startTime = Date.now();
312
+ const fullKey = this.prefixKey(key);
313
+ try {
314
+ await this.executeWithFallback(async (backend) => {
315
+ await this.storeInBackend(backend, fullKey, value, ttl);
316
+ });
317
+ this.updateMetrics('store', startTime, this.activeBackend);
318
+ }
319
+ catch (error) {
320
+ this.logger.error(`Failed to store key ${fullKey}:`, error);
321
+ this.metrics.errorCount++;
322
+ throw error;
323
+ }
324
+ }
325
+ /**
326
+ * Store in specific backend
327
+ */
328
+ async storeInBackend(backend, key, value, ttl) {
329
+ switch (backend) {
330
+ case 'sqlite':
331
+ await this.swarmMemory.store(key, value, { ttl, partition: this.config.namespace });
332
+ break;
333
+ case 'agentdb':
334
+ // AgentDB stores patterns, not key-value pairs
335
+ // Fall through to JSON for key-value storage
336
+ throw new Error('AgentDB not suitable for key-value storage');
337
+ case 'json':
338
+ this.jsonStore.set(key, {
339
+ value,
340
+ ttl,
341
+ createdAt: Date.now(),
342
+ });
343
+ break;
344
+ default:
345
+ throw new Error(`Unknown backend: ${backend}`);
346
+ }
347
+ }
348
+ /**
349
+ * Retrieve a value by key
350
+ */
351
+ async retrieve(key) {
352
+ const startTime = Date.now();
353
+ const fullKey = this.prefixKey(key);
354
+ try {
355
+ const result = await this.executeWithFallback(async (backend) => {
356
+ return await this.retrieveFromBackend(backend, fullKey);
357
+ });
358
+ this.updateMetrics('retrieve', startTime, this.activeBackend);
359
+ return result;
360
+ }
361
+ catch (error) {
362
+ this.logger.error(`Failed to retrieve key ${fullKey}:`, error);
363
+ this.metrics.errorCount++;
364
+ return null;
365
+ }
366
+ }
367
+ /**
368
+ * Retrieve from specific backend
369
+ */
370
+ async retrieveFromBackend(backend, key) {
371
+ switch (backend) {
372
+ case 'sqlite':
373
+ return await this.swarmMemory.retrieve(key, { partition: this.config.namespace });
374
+ case 'json': {
375
+ const entry = this.jsonStore.get(key);
376
+ if (!entry)
377
+ return null;
378
+ // Check TTL
379
+ if (entry.ttl && Date.now() - entry.createdAt > entry.ttl * 1000) {
380
+ this.jsonStore.delete(key);
381
+ return null;
382
+ }
383
+ return entry.value;
384
+ }
385
+ default:
386
+ throw new Error(`Backend ${backend} not suitable for key-value retrieval`);
387
+ }
388
+ }
389
+ /**
390
+ * Delete a key
391
+ */
392
+ async delete(key) {
393
+ const startTime = Date.now();
394
+ const fullKey = this.prefixKey(key);
395
+ try {
396
+ const result = await this.executeWithFallback(async (backend) => {
397
+ return await this.deleteFromBackend(backend, fullKey);
398
+ });
399
+ this.updateMetrics('delete', startTime, this.activeBackend);
400
+ return result;
401
+ }
402
+ catch (error) {
403
+ this.logger.error(`Failed to delete key ${fullKey}:`, error);
404
+ this.metrics.errorCount++;
405
+ return false;
406
+ }
407
+ }
408
+ /**
409
+ * Delete from specific backend
410
+ */
411
+ async deleteFromBackend(backend, key) {
412
+ switch (backend) {
413
+ case 'sqlite':
414
+ await this.swarmMemory.delete(key, this.config.namespace);
415
+ return true;
416
+ case 'json':
417
+ return this.jsonStore.delete(key);
418
+ default:
419
+ return false;
420
+ }
421
+ }
422
+ /**
423
+ * Check if key exists
424
+ */
425
+ async exists(key) {
426
+ const value = await this.retrieve(key);
427
+ return value !== null;
428
+ }
429
+ /**
430
+ * List keys matching pattern
431
+ */
432
+ async list(pattern) {
433
+ const startTime = Date.now();
434
+ try {
435
+ const result = await this.executeWithFallback(async (backend) => {
436
+ return await this.listFromBackend(backend, pattern);
437
+ });
438
+ this.updateMetrics('list', startTime, this.activeBackend);
439
+ return result;
440
+ }
441
+ catch (error) {
442
+ this.logger.error('Failed to list keys:', error);
443
+ this.metrics.errorCount++;
444
+ return [];
445
+ }
446
+ }
447
+ /**
448
+ * List from specific backend
449
+ */
450
+ async listFromBackend(backend, pattern) {
451
+ switch (backend) {
452
+ case 'sqlite': {
453
+ const sqlPattern = pattern ? pattern.replace(/\*/g, '%') : '%';
454
+ const entries = await this.swarmMemory.query(sqlPattern, { partition: this.config.namespace });
455
+ return entries.map(e => e.key);
456
+ }
457
+ case 'json': {
458
+ const keys = Array.from(this.jsonStore.keys());
459
+ if (!pattern)
460
+ return keys;
461
+ const regex = new RegExp(pattern.replace(/\*/g, '.*'));
462
+ return keys.filter(k => regex.test(k));
463
+ }
464
+ default:
465
+ return [];
466
+ }
467
+ }
468
+ /**
469
+ * Search for entries
470
+ */
471
+ async search(query, options = {}) {
472
+ const startTime = Date.now();
473
+ try {
474
+ const results = await this.executeWithFallback(async (backend) => {
475
+ return await this.searchInBackend(backend, query, options);
476
+ });
477
+ this.updateMetrics('search', startTime, this.activeBackend);
478
+ return results;
479
+ }
480
+ catch (error) {
481
+ this.logger.error('Failed to search:', error);
482
+ this.metrics.errorCount++;
483
+ return [];
484
+ }
485
+ }
486
+ /**
487
+ * Search in specific backend
488
+ */
489
+ async searchInBackend(backend, query, options) {
490
+ switch (backend) {
491
+ case 'sqlite': {
492
+ const sqlPattern = `%${query}%`;
493
+ const entries = await this.swarmMemory.query(sqlPattern, { partition: this.config.namespace });
494
+ const keys = entries.map(e => e.key);
495
+ const results = [];
496
+ for (const key of keys.slice(options.offset ?? 0, (options.offset ?? 0) + (options.limit ?? 10))) {
497
+ const value = await this.swarmMemory.retrieve(key, { partition: this.config.namespace });
498
+ if (value) {
499
+ results.push({ key, value, backend: 'sqlite' });
500
+ }
501
+ }
502
+ return results;
503
+ }
504
+ case 'json': {
505
+ const results = [];
506
+ const limit = options.limit ?? 10;
507
+ const offset = options.offset ?? 0;
508
+ let count = 0;
509
+ for (const [key, entry] of this.jsonStore.entries()) {
510
+ if (key.includes(query)) {
511
+ if (count >= offset && count < offset + limit) {
512
+ results.push({ key, value: entry.value, backend: 'json' });
513
+ }
514
+ count++;
515
+ }
516
+ }
517
+ return results;
518
+ }
519
+ default:
520
+ return [];
521
+ }
522
+ }
523
+ /**
524
+ * Store multiple entries in batch
525
+ */
526
+ async storeBatch(entries) {
527
+ const startTime = Date.now();
528
+ try {
529
+ await this.executeWithFallback(async (backend) => {
530
+ for (const entry of entries) {
531
+ const fullKey = this.prefixKey(entry.key);
532
+ await this.storeInBackend(backend, fullKey, entry.value, entry.ttl);
533
+ }
534
+ });
535
+ this.updateMetrics('storeBatch', startTime, this.activeBackend);
536
+ }
537
+ catch (error) {
538
+ this.logger.error('Failed to store batch:', error);
539
+ this.metrics.errorCount++;
540
+ throw error;
541
+ }
542
+ }
543
+ /**
544
+ * Retrieve multiple entries in batch
545
+ */
546
+ async retrieveBatch(keys) {
547
+ const startTime = Date.now();
548
+ const results = new Map();
549
+ try {
550
+ await this.executeWithFallback(async (backend) => {
551
+ for (const key of keys) {
552
+ const fullKey = this.prefixKey(key);
553
+ const value = await this.retrieveFromBackend(backend, fullKey);
554
+ results.set(key, value);
555
+ }
556
+ });
557
+ this.updateMetrics('retrieveBatch', startTime, this.activeBackend);
558
+ return results;
559
+ }
560
+ catch (error) {
561
+ this.logger.error('Failed to retrieve batch:', error);
562
+ this.metrics.errorCount++;
563
+ return results;
564
+ }
565
+ }
566
+ /**
567
+ * Store a vector
568
+ */
569
+ async storeVector(key, vector, metadata) {
570
+ if (!this.vectorStore) {
571
+ throw new Error('Vector operations not enabled');
572
+ }
573
+ const pattern = {
574
+ id: this.prefixKey(key),
575
+ type: 'vector',
576
+ domain: this.config.namespace,
577
+ content: '',
578
+ embedding: vector,
579
+ metadata,
580
+ };
581
+ await this.vectorStore.storePattern(pattern);
582
+ }
583
+ /**
584
+ * Search for similar vectors
585
+ */
586
+ async searchSimilar(vector, limit = 10) {
587
+ if (!this.vectorStore) {
588
+ throw new Error('Vector operations not enabled');
589
+ }
590
+ const results = await this.vectorStore.searchSimilar(vector, { k: limit });
591
+ return results.map(r => ({
592
+ key: r.pattern.id,
593
+ similarity: r.score,
594
+ metadata: r.pattern.metadata,
595
+ vector: r.pattern.embedding,
596
+ }));
597
+ }
598
+ /**
599
+ * Store a pattern
600
+ */
601
+ async storePattern(pattern) {
602
+ if (this.vectorStore && pattern.embedding) {
603
+ const testPattern = {
604
+ id: pattern.id,
605
+ type: pattern.type,
606
+ domain: this.config.namespace,
607
+ content: pattern.content,
608
+ embedding: pattern.embedding,
609
+ metadata: pattern.metadata,
610
+ };
611
+ await this.vectorStore.storePattern(testPattern);
612
+ }
613
+ else {
614
+ // Store as key-value
615
+ await this.store(`pattern:${pattern.id}`, pattern);
616
+ }
617
+ }
618
+ /**
619
+ * Query patterns
620
+ */
621
+ async queryPatterns(filter) {
622
+ const results = [];
623
+ if (this.vectorStore) {
624
+ // Use vector store
625
+ const keys = await this.list('pattern:*');
626
+ for (const key of keys.slice(0, filter.limit ?? 100)) {
627
+ const patternId = key.replace('pattern:', '');
628
+ const pattern = await this.vectorStore.getPattern(patternId);
629
+ if (pattern) {
630
+ if (filter.type && pattern.type !== filter.type)
631
+ continue;
632
+ if (filter.domain && pattern.domain !== filter.domain)
633
+ continue;
634
+ results.push({
635
+ id: pattern.id,
636
+ type: pattern.type,
637
+ content: pattern.content,
638
+ confidence: 1.0,
639
+ metadata: pattern.metadata ?? {},
640
+ embedding: pattern.embedding,
641
+ });
642
+ }
643
+ }
644
+ }
645
+ else {
646
+ // Fall back to key-value search
647
+ const keys = await this.list('pattern:*');
648
+ for (const key of keys.slice(0, filter.limit ?? 100)) {
649
+ const pattern = await this.retrieve(key);
650
+ if (pattern) {
651
+ if (filter.type && pattern.type !== filter.type)
652
+ continue;
653
+ if (filter.minConfidence && pattern.confidence < filter.minConfidence)
654
+ continue;
655
+ results.push(pattern);
656
+ }
657
+ }
658
+ }
659
+ return results;
660
+ }
661
+ /**
662
+ * Get backend-specific instance
663
+ */
664
+ getSwarmMemory() {
665
+ return this.swarmMemory;
666
+ }
667
+ getAgentDB() {
668
+ return this.agentDB;
669
+ }
670
+ getVectorStore() {
671
+ return this.vectorStore;
672
+ }
673
+ /**
674
+ * Check health of all backends
675
+ */
676
+ async checkHealth() {
677
+ const backends = ['sqlite', 'agentdb', 'json', 'vector'];
678
+ for (const backend of backends) {
679
+ const startTime = Date.now();
680
+ try {
681
+ await this.healthCheckBackend(backend);
682
+ const latency = Date.now() - startTime;
683
+ this.updateHealthStatus(backend, {
684
+ backend,
685
+ status: 'healthy',
686
+ latency,
687
+ lastCheck: new Date(),
688
+ errorCount: 0,
689
+ details: {},
690
+ });
691
+ }
692
+ catch (error) {
693
+ const health = this.healthStatus.get(backend);
694
+ const errorCount = (health?.errorCount ?? 0) + 1;
695
+ this.updateHealthStatus(backend, {
696
+ backend,
697
+ status: errorCount > 3 ? 'failed' : 'degraded',
698
+ latency: 0,
699
+ lastCheck: new Date(),
700
+ errorCount,
701
+ details: { error: String(error) },
702
+ });
703
+ }
704
+ }
705
+ return this.healthStatus;
706
+ }
707
+ /**
708
+ * Health check for specific backend
709
+ */
710
+ async healthCheckBackend(backend) {
711
+ switch (backend) {
712
+ case 'sqlite':
713
+ if (!this.swarmMemory)
714
+ throw new Error('SwarmMemory not initialized');
715
+ // Try a simple operation - query with wildcard to verify connectivity
716
+ await this.swarmMemory.query('%', { partition: this.config.namespace });
717
+ break;
718
+ case 'agentdb':
719
+ if (!this.agentDB)
720
+ throw new Error('AgentDB not initialized');
721
+ // AgentDB health check would go here
722
+ break;
723
+ case 'vector':
724
+ if (!this.vectorStore)
725
+ throw new Error('VectorStore not initialized');
726
+ await this.vectorStore.getStats();
727
+ break;
728
+ case 'json':
729
+ // JSON store is always healthy
730
+ break;
731
+ }
732
+ }
733
+ /**
734
+ * Get health status
735
+ */
736
+ getHealthStatus() {
737
+ return new Map(this.healthStatus);
738
+ }
739
+ /**
740
+ * Check if coordinator is healthy
741
+ */
742
+ isHealthy() {
743
+ const primaryHealth = this.healthStatus.get(this.activeBackend);
744
+ return primaryHealth?.status === 'healthy';
745
+ }
746
+ /**
747
+ * Execute with fallback
748
+ */
749
+ async executeWithFallback(operation, backends) {
750
+ const chain = backends ?? this.fallbackChain;
751
+ let lastError = null;
752
+ for (const backend of chain) {
753
+ try {
754
+ const result = await operation(backend);
755
+ // If we're not using the primary backend, consider switching
756
+ if (backend !== this.activeBackend) {
757
+ this.metrics.failoverCount++;
758
+ this.logger.warn(`Using fallback backend: ${backend}`);
759
+ }
760
+ return result;
761
+ }
762
+ catch (error) {
763
+ lastError = error;
764
+ this.logger.debug(`Backend ${backend} failed:`, error);
765
+ // Update health status
766
+ const health = this.healthStatus.get(backend);
767
+ if (health) {
768
+ health.errorCount++;
769
+ health.status = 'degraded';
770
+ }
771
+ }
772
+ }
773
+ throw new Error(`All backends failed: ${lastError?.message}`);
774
+ }
775
+ /**
776
+ * Switch backend
777
+ */
778
+ async switchBackend(from, to) {
779
+ this.logger.info(`Switching backend from ${from} to ${to}`);
780
+ this.activeBackend = to;
781
+ this.fallbackChain = this.buildFallbackChain(to);
782
+ // Optionally sync data
783
+ if (this.config.enableFallback) {
784
+ await this.syncBackends();
785
+ }
786
+ }
787
+ /**
788
+ * Sync data between backends
789
+ */
790
+ async syncBackends() {
791
+ if (this.syncInProgress) {
792
+ return {
793
+ success: false,
794
+ recordsSynced: 0,
795
+ conflicts: 0,
796
+ duration: 0,
797
+ errors: ['Sync already in progress'],
798
+ };
799
+ }
800
+ this.syncInProgress = true;
801
+ const startTime = Date.now();
802
+ let recordsSynced = 0;
803
+ const errors = [];
804
+ try {
805
+ this.logger.debug('Starting backend synchronization...');
806
+ // Sync SQLite to JSON
807
+ if (this.swarmMemory) {
808
+ try {
809
+ const entries = await this.swarmMemory.query('%', { partition: this.config.namespace });
810
+ const keys = entries.map(e => e.key);
811
+ for (const key of keys) {
812
+ try {
813
+ const value = await this.swarmMemory.retrieve(key, { partition: this.config.namespace });
814
+ if (value) {
815
+ this.jsonStore.set(key, {
816
+ value,
817
+ createdAt: Date.now(),
818
+ });
819
+ recordsSynced++;
820
+ }
821
+ }
822
+ catch (error) {
823
+ errors.push(`Failed to sync key ${key}: ${error}`);
824
+ }
825
+ }
826
+ }
827
+ catch (error) {
828
+ errors.push(`Failed to sync from SQLite: ${error}`);
829
+ }
830
+ }
831
+ const duration = Date.now() - startTime;
832
+ this.metrics.syncCount++;
833
+ this.metrics.lastSync = new Date();
834
+ this.logger.info(`Sync completed: ${recordsSynced} records in ${duration}ms`);
835
+ return {
836
+ success: errors.length === 0,
837
+ recordsSynced,
838
+ conflicts: 0,
839
+ duration,
840
+ errors: errors.length > 0 ? errors : undefined,
841
+ };
842
+ }
843
+ finally {
844
+ this.syncInProgress = false;
845
+ }
846
+ }
847
+ /**
848
+ * Create namespaced coordinator
849
+ */
850
+ createNamespace(name) {
851
+ return new NamespacedCoordinator(this, name);
852
+ }
853
+ /**
854
+ * Get metrics
855
+ */
856
+ getMetrics() {
857
+ return {
858
+ ...this.metrics,
859
+ operationsByBackend: new Map(this.metrics.operationsByBackend),
860
+ };
861
+ }
862
+ /**
863
+ * Start health monitoring
864
+ */
865
+ startHealthMonitoring() {
866
+ if (this.healthCheckTimer) {
867
+ clearInterval(this.healthCheckTimer);
868
+ }
869
+ this.healthCheckTimer = setInterval(async () => {
870
+ try {
871
+ await this.checkHealth();
872
+ }
873
+ catch (error) {
874
+ this.logger.error('Health check failed:', error);
875
+ }
876
+ }, this.config.healthCheckInterval);
877
+ }
878
+ /**
879
+ * Start periodic sync
880
+ */
881
+ startPeriodicSync() {
882
+ if (this.syncTimer) {
883
+ clearInterval(this.syncTimer);
884
+ }
885
+ this.syncTimer = setInterval(async () => {
886
+ try {
887
+ await this.syncBackends();
888
+ }
889
+ catch (error) {
890
+ this.logger.error('Periodic sync failed:', error);
891
+ }
892
+ }, this.config.syncInterval);
893
+ }
894
+ /**
895
+ * Update health status
896
+ */
897
+ updateHealthStatus(backend, health) {
898
+ this.healthStatus.set(backend, health);
899
+ }
900
+ /**
901
+ * Update metrics
902
+ */
903
+ updateMetrics(operation, startTime, backend) {
904
+ const duration = Date.now() - startTime;
905
+ this.metrics.totalOperations++;
906
+ const backendOps = this.metrics.operationsByBackend.get(backend) ?? 0;
907
+ this.metrics.operationsByBackend.set(backend, backendOps + 1);
908
+ // Update average latency
909
+ const totalLatency = this.metrics.averageLatency * (this.metrics.totalOperations - 1) + duration;
910
+ this.metrics.averageLatency = totalLatency / this.metrics.totalOperations;
911
+ }
912
+ /**
913
+ * Prefix key with namespace
914
+ */
915
+ prefixKey(key) {
916
+ return `${this.config.namespace}:${key}`;
917
+ }
918
+ /**
919
+ * Shutdown coordinator
920
+ */
921
+ async shutdown() {
922
+ this.logger.info('Shutting down UnifiedMemoryCoordinator...');
923
+ // Stop timers
924
+ if (this.healthCheckTimer) {
925
+ clearInterval(this.healthCheckTimer);
926
+ }
927
+ if (this.syncTimer) {
928
+ clearInterval(this.syncTimer);
929
+ }
930
+ // Final sync
931
+ if (this.config.enableFallback) {
932
+ await this.syncBackends();
933
+ }
934
+ // Shutdown backends
935
+ if (this.vectorStore) {
936
+ await this.vectorStore.shutdown();
937
+ }
938
+ if (this.agentDB) {
939
+ await this.agentDB.close();
940
+ }
941
+ if (this.swarmMemory) {
942
+ await this.swarmMemory.close();
943
+ }
944
+ this.logger.info('UnifiedMemoryCoordinator shut down');
945
+ }
946
+ }
947
+ exports.UnifiedMemoryCoordinator = UnifiedMemoryCoordinator;
948
+ /**
949
+ * Namespaced wrapper for isolated operations
950
+ */
951
+ class NamespacedCoordinator {
952
+ constructor(coordinator, namespace) {
953
+ this.coordinator = coordinator;
954
+ this.namespace = namespace;
955
+ }
956
+ async store(key, value, ttl) {
957
+ return this.coordinator.store(this.prefixKey(key), value, ttl);
958
+ }
959
+ async retrieve(key) {
960
+ return this.coordinator.retrieve(this.prefixKey(key));
961
+ }
962
+ async delete(key) {
963
+ return this.coordinator.delete(this.prefixKey(key));
964
+ }
965
+ async list(pattern) {
966
+ const keys = await this.coordinator.list(pattern ? this.prefixKey(pattern) : undefined);
967
+ return keys.map(k => this.unprefixKey(k));
968
+ }
969
+ prefixKey(key) {
970
+ return `${this.namespace}:${key}`;
971
+ }
972
+ unprefixKey(key) {
973
+ const prefix = `${this.namespace}:`;
974
+ return key.startsWith(prefix) ? key.slice(prefix.length) : key;
975
+ }
976
+ }
977
+ exports.NamespacedCoordinator = NamespacedCoordinator;
978
+ /**
979
+ * Convenience function to create a coordinator
980
+ */
981
+ async function createUnifiedMemoryCoordinator(config) {
982
+ const coordinator = new UnifiedMemoryCoordinator(config);
983
+ await coordinator.initialize();
984
+ return coordinator;
985
+ }
986
+ //# sourceMappingURL=UnifiedMemoryCoordinator.js.map