@arcanea/guardian-evolution 0.1.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 (85) hide show
  1. package/dist/algorithms/a2c.d.ts +86 -0
  2. package/dist/algorithms/a2c.d.ts.map +1 -0
  3. package/dist/algorithms/a2c.js +361 -0
  4. package/dist/algorithms/a2c.js.map +1 -0
  5. package/dist/algorithms/curiosity.d.ts +82 -0
  6. package/dist/algorithms/curiosity.d.ts.map +1 -0
  7. package/dist/algorithms/curiosity.js +392 -0
  8. package/dist/algorithms/curiosity.js.map +1 -0
  9. package/dist/algorithms/decision-transformer.d.ts +82 -0
  10. package/dist/algorithms/decision-transformer.d.ts.map +1 -0
  11. package/dist/algorithms/decision-transformer.js +415 -0
  12. package/dist/algorithms/decision-transformer.js.map +1 -0
  13. package/dist/algorithms/dqn.d.ts +72 -0
  14. package/dist/algorithms/dqn.d.ts.map +1 -0
  15. package/dist/algorithms/dqn.js +303 -0
  16. package/dist/algorithms/dqn.js.map +1 -0
  17. package/dist/algorithms/index.d.ts +32 -0
  18. package/dist/algorithms/index.d.ts.map +1 -0
  19. package/dist/algorithms/index.js +74 -0
  20. package/dist/algorithms/index.js.map +1 -0
  21. package/dist/algorithms/ppo.d.ts +72 -0
  22. package/dist/algorithms/ppo.d.ts.map +1 -0
  23. package/dist/algorithms/ppo.js +331 -0
  24. package/dist/algorithms/ppo.js.map +1 -0
  25. package/dist/algorithms/q-learning.d.ts +77 -0
  26. package/dist/algorithms/q-learning.d.ts.map +1 -0
  27. package/dist/algorithms/q-learning.js +259 -0
  28. package/dist/algorithms/q-learning.js.map +1 -0
  29. package/dist/algorithms/sarsa.d.ts +82 -0
  30. package/dist/algorithms/sarsa.d.ts.map +1 -0
  31. package/dist/algorithms/sarsa.js +297 -0
  32. package/dist/algorithms/sarsa.js.map +1 -0
  33. package/dist/index.d.ts +118 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +201 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/modes/balanced.d.ts +60 -0
  38. package/dist/modes/balanced.d.ts.map +1 -0
  39. package/dist/modes/balanced.js +234 -0
  40. package/dist/modes/balanced.js.map +1 -0
  41. package/dist/modes/batch.d.ts +82 -0
  42. package/dist/modes/batch.d.ts.map +1 -0
  43. package/dist/modes/batch.js +316 -0
  44. package/dist/modes/batch.js.map +1 -0
  45. package/dist/modes/edge.d.ts +85 -0
  46. package/dist/modes/edge.d.ts.map +1 -0
  47. package/dist/modes/edge.js +310 -0
  48. package/dist/modes/edge.js.map +1 -0
  49. package/dist/modes/index.d.ts +55 -0
  50. package/dist/modes/index.d.ts.map +1 -0
  51. package/dist/modes/index.js +83 -0
  52. package/dist/modes/index.js.map +1 -0
  53. package/dist/modes/real-time.d.ts +58 -0
  54. package/dist/modes/real-time.d.ts.map +1 -0
  55. package/dist/modes/real-time.js +196 -0
  56. package/dist/modes/real-time.js.map +1 -0
  57. package/dist/modes/research.d.ts +79 -0
  58. package/dist/modes/research.d.ts.map +1 -0
  59. package/dist/modes/research.js +389 -0
  60. package/dist/modes/research.js.map +1 -0
  61. package/dist/pattern-learner.d.ts +117 -0
  62. package/dist/pattern-learner.d.ts.map +1 -0
  63. package/dist/pattern-learner.js +603 -0
  64. package/dist/pattern-learner.js.map +1 -0
  65. package/dist/reasoning-bank.d.ts +259 -0
  66. package/dist/reasoning-bank.d.ts.map +1 -0
  67. package/dist/reasoning-bank.js +993 -0
  68. package/dist/reasoning-bank.js.map +1 -0
  69. package/dist/reasoningbank-adapter.d.ts +168 -0
  70. package/dist/reasoningbank-adapter.d.ts.map +1 -0
  71. package/dist/reasoningbank-adapter.js +463 -0
  72. package/dist/reasoningbank-adapter.js.map +1 -0
  73. package/dist/sona-integration.d.ts +168 -0
  74. package/dist/sona-integration.d.ts.map +1 -0
  75. package/dist/sona-integration.js +316 -0
  76. package/dist/sona-integration.js.map +1 -0
  77. package/dist/sona-manager.d.ts +147 -0
  78. package/dist/sona-manager.d.ts.map +1 -0
  79. package/dist/sona-manager.js +695 -0
  80. package/dist/sona-manager.js.map +1 -0
  81. package/dist/types.d.ts +431 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +11 -0
  84. package/dist/types.js.map +1 -0
  85. package/package.json +47 -0
@@ -0,0 +1,993 @@
1
+ /**
2
+ * ReasoningBank Integration with AgentDB
3
+ *
4
+ * Implements the 4-step learning pipeline with real vector storage:
5
+ * 1. RETRIEVE - Top-k memory injection with MMR diversity (using AgentDB HNSW)
6
+ * 2. JUDGE - LLM-as-judge trajectory evaluation
7
+ * 3. DISTILL - Extract strategy memories from trajectories
8
+ * 4. CONSOLIDATE - Dedup, detect contradictions, prune old patterns
9
+ *
10
+ * Performance Targets:
11
+ * - Retrieval: <10ms with AgentDB HNSW (150x faster than brute-force)
12
+ * - Learning step: <10ms
13
+ * - Consolidation: <100ms
14
+ *
15
+ * @module reasoning-bank
16
+ */
17
+ // ============================================================================
18
+ // AgentDB Integration
19
+ // ============================================================================
20
+ let AgentDB;
21
+ let agentdbImportPromise;
22
+ async function ensureAgentDBImport() {
23
+ if (!agentdbImportPromise) {
24
+ agentdbImportPromise = (async () => {
25
+ try {
26
+ const agentdbModule = await import('agentdb');
27
+ AgentDB = agentdbModule.AgentDB || agentdbModule.default;
28
+ }
29
+ catch {
30
+ // AgentDB not available - will use fallback
31
+ AgentDB = undefined;
32
+ }
33
+ })();
34
+ }
35
+ return agentdbImportPromise;
36
+ }
37
+ /**
38
+ * Default ReasoningBank configuration
39
+ */
40
+ const DEFAULT_CONFIG = {
41
+ maxTrajectories: 5000,
42
+ distillationThreshold: 0.6,
43
+ retrievalK: 3,
44
+ mmrLambda: 0.7,
45
+ maxPatternAgeDays: 30,
46
+ dedupThreshold: 0.95,
47
+ enableContradictionDetection: true,
48
+ dbPath: undefined,
49
+ vectorDimension: 768,
50
+ namespace: 'reasoning-bank',
51
+ enableAgentDB: true,
52
+ };
53
+ // ============================================================================
54
+ // ReasoningBank Class
55
+ // ============================================================================
56
+ /**
57
+ * ReasoningBank - Trajectory storage and learning pipeline with AgentDB
58
+ *
59
+ * This class implements a complete learning pipeline for AI agents:
60
+ * - Store and retrieve trajectories using vector similarity
61
+ * - Judge trajectory quality using rule-based evaluation
62
+ * - Distill successful trajectories into reusable patterns
63
+ * - Consolidate patterns to remove duplicates and contradictions
64
+ */
65
+ export class ReasoningBank {
66
+ config;
67
+ trajectories = new Map();
68
+ memories = new Map();
69
+ patterns = new Map();
70
+ eventListeners = new Set();
71
+ // AgentDB instance for vector storage
72
+ agentdb = null;
73
+ agentdbAvailable = false;
74
+ initialized = false;
75
+ // Performance tracking
76
+ retrievalCount = 0;
77
+ totalRetrievalTime = 0;
78
+ distillationCount = 0;
79
+ totalDistillationTime = 0;
80
+ judgeCount = 0;
81
+ totalJudgeTime = 0;
82
+ consolidationCount = 0;
83
+ totalConsolidationTime = 0;
84
+ constructor(config = {}) {
85
+ this.config = { ...DEFAULT_CONFIG, ...config };
86
+ }
87
+ // ==========================================================================
88
+ // Initialization
89
+ // ==========================================================================
90
+ /**
91
+ * Initialize ReasoningBank with AgentDB
92
+ */
93
+ async initialize() {
94
+ if (this.initialized)
95
+ return;
96
+ if (this.config.enableAgentDB) {
97
+ await ensureAgentDBImport();
98
+ this.agentdbAvailable = AgentDB !== undefined;
99
+ if (this.agentdbAvailable) {
100
+ try {
101
+ this.agentdb = new AgentDB({
102
+ dbPath: this.config.dbPath || ':memory:',
103
+ namespace: this.config.namespace,
104
+ vectorDimension: this.config.vectorDimension,
105
+ vectorBackend: 'auto',
106
+ });
107
+ await this.agentdb.initialize();
108
+ this.emitEvent({ type: 'memory_consolidated', memoriesCount: 0 });
109
+ }
110
+ catch (error) {
111
+ console.warn('AgentDB initialization failed, using fallback:', error);
112
+ this.agentdbAvailable = false;
113
+ }
114
+ }
115
+ }
116
+ this.initialized = true;
117
+ }
118
+ /**
119
+ * Shutdown and cleanup resources
120
+ */
121
+ async shutdown() {
122
+ if (this.agentdb) {
123
+ await this.agentdb.close?.();
124
+ }
125
+ this.initialized = false;
126
+ }
127
+ // ==========================================================================
128
+ // STEP 1: RETRIEVE - Top-k memory injection with MMR diversity
129
+ // ==========================================================================
130
+ /**
131
+ * Retrieve relevant memories using Maximal Marginal Relevance (MMR)
132
+ *
133
+ * Uses AgentDB HNSW index for 150x faster retrieval when available.
134
+ *
135
+ * @param queryEmbedding - Query vector for similarity search
136
+ * @param k - Number of results to return (default: config.retrievalK)
137
+ * @returns Retrieval results with relevance and diversity scores
138
+ */
139
+ async retrieve(queryEmbedding, k) {
140
+ const startTime = performance.now();
141
+ const retrieveK = k ?? this.config.retrievalK;
142
+ if (this.memories.size === 0) {
143
+ return [];
144
+ }
145
+ let candidates = [];
146
+ // Try AgentDB HNSW search first
147
+ if (this.agentdb && this.agentdbAvailable) {
148
+ try {
149
+ const results = await this.searchWithAgentDB(queryEmbedding, retrieveK * 3);
150
+ candidates = results
151
+ .map(r => {
152
+ const entry = this.memories.get(r.id);
153
+ return entry ? { entry, relevance: r.similarity } : null;
154
+ })
155
+ .filter((c) => c !== null);
156
+ }
157
+ catch {
158
+ // Fall through to brute-force
159
+ }
160
+ }
161
+ // Fallback: brute-force search
162
+ if (candidates.length === 0) {
163
+ for (const entry of this.memories.values()) {
164
+ const relevance = this.cosineSimilarity(queryEmbedding, entry.memory.embedding);
165
+ candidates.push({ entry, relevance });
166
+ }
167
+ candidates.sort((a, b) => b.relevance - a.relevance);
168
+ }
169
+ // Apply MMR for diversity
170
+ const results = [];
171
+ const selected = [];
172
+ while (results.length < retrieveK && candidates.length > 0) {
173
+ let bestIdx = 0;
174
+ let bestScore = -Infinity;
175
+ for (let i = 0; i < candidates.length; i++) {
176
+ const candidate = candidates[i];
177
+ // Compute MMR score: lambda * relevance - (1 - lambda) * max_similarity_to_selected
178
+ const relevance = candidate.relevance;
179
+ let maxSimilarity = 0;
180
+ for (const sel of selected) {
181
+ const sim = this.cosineSimilarity(candidate.entry.memory.embedding, sel.memory.embedding);
182
+ maxSimilarity = Math.max(maxSimilarity, sim);
183
+ }
184
+ const diversityScore = 1 - maxSimilarity;
185
+ const mmrScore = this.config.mmrLambda * relevance +
186
+ (1 - this.config.mmrLambda) * diversityScore;
187
+ if (mmrScore > bestScore) {
188
+ bestScore = mmrScore;
189
+ bestIdx = i;
190
+ }
191
+ }
192
+ // Add best candidate
193
+ const best = candidates[bestIdx];
194
+ selected.push(best.entry);
195
+ results.push({
196
+ memory: best.entry.memory,
197
+ relevanceScore: best.relevance,
198
+ diversityScore: 1 - this.computeMaxSimilarity(best.entry, selected.slice(0, -1)),
199
+ combinedScore: bestScore,
200
+ });
201
+ // Remove from candidates
202
+ candidates.splice(bestIdx, 1);
203
+ }
204
+ // Update stats
205
+ this.retrievalCount++;
206
+ this.totalRetrievalTime += performance.now() - startTime;
207
+ return results;
208
+ }
209
+ /**
210
+ * Search for similar memories by content string
211
+ *
212
+ * @param content - Text content to search for
213
+ * @param k - Number of results
214
+ * @returns Retrieval results
215
+ */
216
+ async retrieveByContent(content, k) {
217
+ // Simple content-based retrieval using memory strategies
218
+ const retrieveK = k ?? this.config.retrievalK;
219
+ const results = [];
220
+ const contentLower = content.toLowerCase();
221
+ const entries = Array.from(this.memories.values());
222
+ // Score by content similarity
223
+ const scored = entries.map(entry => ({
224
+ entry,
225
+ score: this.computeContentSimilarity(contentLower, entry.memory.strategy),
226
+ }));
227
+ scored.sort((a, b) => b.score - a.score);
228
+ for (let i = 0; i < Math.min(retrieveK, scored.length); i++) {
229
+ const { entry, score } = scored[i];
230
+ if (score > 0) {
231
+ results.push({
232
+ memory: entry.memory,
233
+ relevanceScore: score,
234
+ diversityScore: 1,
235
+ combinedScore: score,
236
+ });
237
+ }
238
+ }
239
+ return results;
240
+ }
241
+ // ==========================================================================
242
+ // STEP 2: JUDGE - LLM-as-judge trajectory evaluation
243
+ // ==========================================================================
244
+ /**
245
+ * Judge a trajectory and produce a verdict
246
+ *
247
+ * Uses rule-based evaluation to assess trajectory quality.
248
+ * In production, this could be enhanced with LLM-as-judge.
249
+ *
250
+ * @param trajectory - Completed trajectory to judge
251
+ * @returns Verdict with success status and analysis
252
+ */
253
+ async judge(trajectory) {
254
+ const startTime = performance.now();
255
+ if (!trajectory.isComplete) {
256
+ throw new Error('Cannot judge incomplete trajectory');
257
+ }
258
+ // Analyze trajectory steps
259
+ const stepAnalysis = this.analyzeSteps(trajectory.steps);
260
+ // Compute success based on quality and step analysis
261
+ const success = trajectory.qualityScore >= this.config.distillationThreshold &&
262
+ stepAnalysis.positiveRatio > 0.6;
263
+ // Identify strengths and weaknesses
264
+ const strengths = this.identifyStrengths(trajectory, stepAnalysis);
265
+ const weaknesses = this.identifyWeaknesses(trajectory, stepAnalysis);
266
+ // Generate improvement suggestions
267
+ const improvements = this.generateImprovements(weaknesses);
268
+ // Compute relevance for similar future tasks
269
+ const relevanceScore = this.computeRelevanceScore(trajectory);
270
+ const verdict = {
271
+ success,
272
+ confidence: this.computeConfidence(trajectory, stepAnalysis),
273
+ strengths,
274
+ weaknesses,
275
+ improvements,
276
+ relevanceScore,
277
+ };
278
+ // Store verdict with trajectory
279
+ trajectory.verdict = verdict;
280
+ // Update stats
281
+ this.judgeCount++;
282
+ this.totalJudgeTime += performance.now() - startTime;
283
+ return verdict;
284
+ }
285
+ // ==========================================================================
286
+ // STEP 3: DISTILL - Extract strategy memories from trajectories
287
+ // ==========================================================================
288
+ /**
289
+ * Distill a trajectory into a reusable memory
290
+ *
291
+ * @param trajectory - Trajectory to distill
292
+ * @returns Distilled memory or null if quality too low
293
+ */
294
+ async distill(trajectory) {
295
+ const startTime = performance.now();
296
+ // Must be judged first
297
+ if (!trajectory.verdict) {
298
+ await this.judge(trajectory);
299
+ }
300
+ // Only distill successful trajectories
301
+ if (!trajectory.verdict.success ||
302
+ trajectory.qualityScore < this.config.distillationThreshold) {
303
+ return null;
304
+ }
305
+ // Extract strategy from trajectory
306
+ const strategy = this.extractStrategy(trajectory);
307
+ // Extract key learnings
308
+ const keyLearnings = this.extractKeyLearnings(trajectory);
309
+ // Compute aggregated embedding
310
+ const embedding = this.computeAggregateEmbedding(trajectory);
311
+ const memory = {
312
+ memoryId: `mem_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
313
+ trajectoryId: trajectory.trajectoryId,
314
+ strategy,
315
+ keyLearnings,
316
+ embedding,
317
+ quality: trajectory.qualityScore,
318
+ usageCount: 0,
319
+ lastUsed: Date.now(),
320
+ };
321
+ // Store the memory
322
+ const entry = {
323
+ memory,
324
+ trajectory,
325
+ verdict: trajectory.verdict,
326
+ consolidated: false,
327
+ };
328
+ this.memories.set(memory.memoryId, entry);
329
+ // Store in AgentDB for vector search
330
+ if (this.agentdb && this.agentdbAvailable) {
331
+ await this.storeInAgentDB(memory);
332
+ }
333
+ // Also store trajectory reference
334
+ trajectory.distilledMemory = memory;
335
+ // Update stats
336
+ this.distillationCount++;
337
+ this.totalDistillationTime += performance.now() - startTime;
338
+ this.emitEvent({
339
+ type: 'trajectory_completed',
340
+ trajectoryId: trajectory.trajectoryId,
341
+ qualityScore: trajectory.qualityScore,
342
+ });
343
+ return memory;
344
+ }
345
+ /**
346
+ * Batch distill multiple trajectories
347
+ *
348
+ * @param trajectories - Array of trajectories to distill
349
+ * @returns Array of distilled memories (excludes nulls)
350
+ */
351
+ async distillBatch(trajectories) {
352
+ const memories = [];
353
+ for (const trajectory of trajectories) {
354
+ const memory = await this.distill(trajectory);
355
+ if (memory) {
356
+ memories.push(memory);
357
+ }
358
+ }
359
+ return memories;
360
+ }
361
+ // ==========================================================================
362
+ // STEP 4: CONSOLIDATE - Dedup, detect contradictions, prune old patterns
363
+ // ==========================================================================
364
+ /**
365
+ * Consolidate memories: deduplicate, detect contradictions, prune old
366
+ *
367
+ * @returns Consolidation statistics
368
+ */
369
+ async consolidate() {
370
+ const startTime = performance.now();
371
+ const result = {
372
+ removedDuplicates: 0,
373
+ contradictionsDetected: 0,
374
+ prunedPatterns: 0,
375
+ mergedPatterns: 0,
376
+ };
377
+ // 1. Deduplicate similar memories
378
+ result.removedDuplicates = await this.deduplicateMemories();
379
+ // 2. Detect contradictions
380
+ if (this.config.enableContradictionDetection) {
381
+ result.contradictionsDetected = await this.detectContradictions();
382
+ }
383
+ // 3. Prune old patterns
384
+ result.prunedPatterns = await this.pruneOldPatterns();
385
+ // 4. Merge similar patterns
386
+ result.mergedPatterns = await this.mergePatterns();
387
+ // Update stats
388
+ this.consolidationCount++;
389
+ this.totalConsolidationTime += performance.now() - startTime;
390
+ // Emit consolidation event
391
+ this.emitEvent({
392
+ type: 'memory_consolidated',
393
+ memoriesCount: this.memories.size,
394
+ });
395
+ return result;
396
+ }
397
+ // ==========================================================================
398
+ // Pattern Management
399
+ // ==========================================================================
400
+ /**
401
+ * Convert a distilled memory to a pattern
402
+ */
403
+ memoryToPattern(memory) {
404
+ const pattern = {
405
+ patternId: `pat_${memory.memoryId}`,
406
+ name: this.generatePatternName(memory),
407
+ domain: this.inferDomain(memory),
408
+ embedding: memory.embedding,
409
+ strategy: memory.strategy,
410
+ successRate: memory.quality,
411
+ usageCount: memory.usageCount,
412
+ qualityHistory: [memory.quality],
413
+ evolutionHistory: [],
414
+ createdAt: Date.now(),
415
+ updatedAt: Date.now(),
416
+ };
417
+ this.patterns.set(pattern.patternId, pattern);
418
+ return pattern;
419
+ }
420
+ /**
421
+ * Evolve a pattern based on new experience
422
+ */
423
+ evolvePattern(patternId, newExperience) {
424
+ const pattern = this.patterns.get(patternId);
425
+ if (!pattern)
426
+ return;
427
+ const previousQuality = pattern.successRate;
428
+ // Update quality history
429
+ pattern.qualityHistory.push(newExperience.qualityScore);
430
+ if (pattern.qualityHistory.length > 100) {
431
+ pattern.qualityHistory = pattern.qualityHistory.slice(-100);
432
+ }
433
+ // Update success rate
434
+ pattern.successRate = pattern.qualityHistory.reduce((a, b) => a + b, 0) /
435
+ pattern.qualityHistory.length;
436
+ pattern.usageCount++;
437
+ pattern.updatedAt = Date.now();
438
+ // Record evolution
439
+ const evolutionType = this.determineEvolutionType(previousQuality, pattern.successRate);
440
+ pattern.evolutionHistory.push({
441
+ timestamp: Date.now(),
442
+ type: evolutionType,
443
+ previousQuality,
444
+ newQuality: pattern.successRate,
445
+ description: `Updated based on trajectory ${newExperience.trajectoryId}`,
446
+ });
447
+ // Emit event
448
+ this.emitEvent({
449
+ type: 'pattern_evolved',
450
+ patternId,
451
+ evolutionType,
452
+ });
453
+ }
454
+ /**
455
+ * Get all patterns
456
+ */
457
+ getPatterns() {
458
+ return Array.from(this.patterns.values());
459
+ }
460
+ /**
461
+ * Find patterns matching a query
462
+ */
463
+ async findPatterns(queryEmbedding, k = 5) {
464
+ const results = [];
465
+ for (const pattern of this.patterns.values()) {
466
+ const score = this.cosineSimilarity(queryEmbedding, pattern.embedding);
467
+ results.push({ pattern, score });
468
+ }
469
+ results.sort((a, b) => b.score - a.score);
470
+ return results.slice(0, k).map(r => r.pattern);
471
+ }
472
+ // ==========================================================================
473
+ // Trajectory Management
474
+ // ==========================================================================
475
+ /**
476
+ * Store a trajectory
477
+ */
478
+ storeTrajectory(trajectory) {
479
+ this.trajectories.set(trajectory.trajectoryId, trajectory);
480
+ // Prune if over capacity
481
+ if (this.trajectories.size > this.config.maxTrajectories) {
482
+ this.pruneTrajectories();
483
+ }
484
+ }
485
+ /**
486
+ * Get trajectory by ID
487
+ */
488
+ getTrajectory(trajectoryId) {
489
+ return this.trajectories.get(trajectoryId);
490
+ }
491
+ /**
492
+ * Get all trajectories
493
+ */
494
+ getTrajectories() {
495
+ return Array.from(this.trajectories.values());
496
+ }
497
+ /**
498
+ * Get successful trajectories
499
+ */
500
+ getSuccessfulTrajectories() {
501
+ return Array.from(this.trajectories.values())
502
+ .filter(t => t.verdict?.success);
503
+ }
504
+ /**
505
+ * Get failed trajectories
506
+ */
507
+ getFailedTrajectories() {
508
+ return Array.from(this.trajectories.values())
509
+ .filter(t => t.isComplete && !t.verdict?.success);
510
+ }
511
+ // ==========================================================================
512
+ // Statistics
513
+ // ==========================================================================
514
+ /**
515
+ * Get ReasoningBank statistics
516
+ */
517
+ getStats() {
518
+ return {
519
+ trajectoryCount: this.trajectories.size,
520
+ memoryCount: this.memories.size,
521
+ patternCount: this.patterns.size,
522
+ avgRetrievalTimeMs: this.retrievalCount > 0
523
+ ? this.totalRetrievalTime / this.retrievalCount
524
+ : 0,
525
+ avgDistillationTimeMs: this.distillationCount > 0
526
+ ? this.totalDistillationTime / this.distillationCount
527
+ : 0,
528
+ avgJudgeTimeMs: this.judgeCount > 0
529
+ ? this.totalJudgeTime / this.judgeCount
530
+ : 0,
531
+ avgConsolidationTimeMs: this.consolidationCount > 0
532
+ ? this.totalConsolidationTime / this.consolidationCount
533
+ : 0,
534
+ consolidatedMemories: Array.from(this.memories.values())
535
+ .filter(e => e.consolidated).length,
536
+ successfulTrajectories: this.getSuccessfulTrajectories().length,
537
+ failedTrajectories: this.getFailedTrajectories().length,
538
+ agentdbEnabled: this.agentdbAvailable ? 1 : 0,
539
+ retrievalCount: this.retrievalCount,
540
+ distillationCount: this.distillationCount,
541
+ judgeCount: this.judgeCount,
542
+ consolidationCount: this.consolidationCount,
543
+ };
544
+ }
545
+ /**
546
+ * Get detailed metrics for hooks
547
+ */
548
+ getDetailedMetrics() {
549
+ const successfulTrajectories = this.getSuccessfulTrajectories();
550
+ const allTrajectories = this.getTrajectories();
551
+ const successRate = allTrajectories.length > 0
552
+ ? successfulTrajectories.length / allTrajectories.length
553
+ : 0;
554
+ // Extract domain-based routing stats
555
+ const domainStats = new Map();
556
+ for (const t of allTrajectories) {
557
+ const domain = t.domain || 'general';
558
+ const stats = domainStats.get(domain) || { count: 0, successes: 0 };
559
+ stats.count++;
560
+ if (t.verdict?.success)
561
+ stats.successes++;
562
+ domainStats.set(domain, stats);
563
+ }
564
+ const topAgents = Array.from(domainStats.entries())
565
+ .map(([agent, stats]) => ({
566
+ agent,
567
+ count: stats.count,
568
+ successRate: stats.count > 0 ? stats.successes / stats.count : 0,
569
+ }))
570
+ .sort((a, b) => b.count - a.count)
571
+ .slice(0, 5);
572
+ // Extract common patterns
573
+ const patternStrategies = Array.from(this.patterns.values())
574
+ .sort((a, b) => b.usageCount - a.usageCount)
575
+ .slice(0, 5)
576
+ .map(p => p.strategy);
577
+ return {
578
+ routing: {
579
+ totalRoutes: allTrajectories.length,
580
+ avgConfidence: successfulTrajectories.length > 0
581
+ ? successfulTrajectories.reduce((sum, t) => sum + (t.verdict?.confidence || 0), 0) / successfulTrajectories.length
582
+ : 0,
583
+ topAgents,
584
+ },
585
+ edits: {
586
+ totalEdits: this.memories.size,
587
+ successRate,
588
+ commonPatterns: patternStrategies.slice(0, 4),
589
+ },
590
+ commands: {
591
+ totalCommands: this.distillationCount,
592
+ successRate,
593
+ avgExecutionTime: this.totalDistillationTime / Math.max(this.distillationCount, 1),
594
+ commonCommands: patternStrategies.slice(0, 4),
595
+ },
596
+ };
597
+ }
598
+ // ==========================================================================
599
+ // Event System
600
+ // ==========================================================================
601
+ addEventListener(listener) {
602
+ this.eventListeners.add(listener);
603
+ }
604
+ removeEventListener(listener) {
605
+ this.eventListeners.delete(listener);
606
+ }
607
+ emitEvent(event) {
608
+ for (const listener of this.eventListeners) {
609
+ try {
610
+ listener(event);
611
+ }
612
+ catch (error) {
613
+ console.error('Error in ReasoningBank event listener:', error);
614
+ }
615
+ }
616
+ }
617
+ // ==========================================================================
618
+ // AgentDB Integration Helpers
619
+ // ==========================================================================
620
+ /**
621
+ * Store memory in AgentDB for vector search
622
+ */
623
+ async storeInAgentDB(memory) {
624
+ if (!this.agentdb)
625
+ return;
626
+ try {
627
+ if (typeof this.agentdb.store === 'function') {
628
+ await this.agentdb.store(memory.memoryId, {
629
+ content: memory.strategy,
630
+ embedding: memory.embedding,
631
+ metadata: {
632
+ trajectoryId: memory.trajectoryId,
633
+ quality: memory.quality,
634
+ keyLearnings: memory.keyLearnings,
635
+ usageCount: memory.usageCount,
636
+ lastUsed: memory.lastUsed,
637
+ },
638
+ });
639
+ }
640
+ }
641
+ catch (error) {
642
+ console.warn('Failed to store in AgentDB:', error);
643
+ }
644
+ }
645
+ /**
646
+ * Search using AgentDB HNSW index
647
+ */
648
+ async searchWithAgentDB(queryEmbedding, k) {
649
+ if (!this.agentdb)
650
+ return [];
651
+ try {
652
+ if (typeof this.agentdb.search === 'function') {
653
+ return await this.agentdb.search(queryEmbedding, k);
654
+ }
655
+ // Try HNSW controller if available
656
+ const hnsw = this.agentdb.getController?.('hnsw');
657
+ if (hnsw) {
658
+ const results = await hnsw.search(queryEmbedding, k);
659
+ return results.map((r) => ({
660
+ id: String(r.id),
661
+ similarity: r.similarity || 1 - r.distance,
662
+ }));
663
+ }
664
+ }
665
+ catch {
666
+ // Fall through to return empty
667
+ }
668
+ return [];
669
+ }
670
+ /**
671
+ * Delete from AgentDB
672
+ */
673
+ async deleteFromAgentDB(memoryId) {
674
+ if (!this.agentdb)
675
+ return;
676
+ try {
677
+ if (typeof this.agentdb.delete === 'function') {
678
+ await this.agentdb.delete(memoryId);
679
+ }
680
+ }
681
+ catch {
682
+ // Ignore deletion errors
683
+ }
684
+ }
685
+ // ==========================================================================
686
+ // Private Helper Methods
687
+ // ==========================================================================
688
+ cosineSimilarity(a, b) {
689
+ if (a.length !== b.length)
690
+ return 0;
691
+ let dot = 0, normA = 0, normB = 0;
692
+ for (let i = 0; i < a.length; i++) {
693
+ dot += a[i] * b[i];
694
+ normA += a[i] * a[i];
695
+ normB += b[i] * b[i];
696
+ }
697
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
698
+ // Clamp to [0, 1] to handle floating point precision issues
699
+ const similarity = denom > 0 ? dot / denom : 0;
700
+ return Math.max(0, Math.min(1, similarity));
701
+ }
702
+ computeContentSimilarity(query, content) {
703
+ const queryWords = new Set(query.toLowerCase().split(/\s+/));
704
+ const contentWords = content.toLowerCase().split(/\s+/);
705
+ let matches = 0;
706
+ for (const word of contentWords) {
707
+ if (queryWords.has(word))
708
+ matches++;
709
+ }
710
+ return contentWords.length > 0 ? matches / contentWords.length : 0;
711
+ }
712
+ computeMaxSimilarity(entry, selected) {
713
+ let maxSim = 0;
714
+ for (const sel of selected) {
715
+ const sim = this.cosineSimilarity(entry.memory.embedding, sel.memory.embedding);
716
+ maxSim = Math.max(maxSim, sim);
717
+ }
718
+ return maxSim;
719
+ }
720
+ analyzeSteps(steps) {
721
+ const rewardSum = steps.reduce((s, step) => s + step.reward, 0);
722
+ const positiveSteps = steps.filter(s => s.reward > 0.5).length;
723
+ return {
724
+ totalSteps: steps.length,
725
+ avgReward: steps.length > 0 ? rewardSum / steps.length : 0,
726
+ positiveRatio: steps.length > 0 ? positiveSteps / steps.length : 0,
727
+ trajectory: steps.length > 1
728
+ ? (steps[steps.length - 1].reward - steps[0].reward)
729
+ : 0,
730
+ };
731
+ }
732
+ identifyStrengths(trajectory, analysis) {
733
+ const strengths = [];
734
+ if (analysis.avgReward > 0.7) {
735
+ strengths.push('High average reward across steps');
736
+ }
737
+ if (analysis.trajectory > 0.2) {
738
+ strengths.push('Positive reward trajectory');
739
+ }
740
+ if (trajectory.qualityScore > 0.8) {
741
+ strengths.push('High overall quality');
742
+ }
743
+ if (analysis.totalSteps < 5 && trajectory.qualityScore > 0.6) {
744
+ strengths.push('Efficient solution (few steps)');
745
+ }
746
+ return strengths;
747
+ }
748
+ identifyWeaknesses(trajectory, analysis) {
749
+ const weaknesses = [];
750
+ if (analysis.avgReward < 0.4) {
751
+ weaknesses.push('Low average reward');
752
+ }
753
+ if (analysis.trajectory < -0.1) {
754
+ weaknesses.push('Declining reward trajectory');
755
+ }
756
+ if (analysis.positiveRatio < 0.5) {
757
+ weaknesses.push('Many negative/neutral steps');
758
+ }
759
+ if (analysis.totalSteps > 10 && trajectory.qualityScore < 0.7) {
760
+ weaknesses.push('Long trajectory with mediocre outcome');
761
+ }
762
+ return weaknesses;
763
+ }
764
+ generateImprovements(weaknesses) {
765
+ const improvements = [];
766
+ for (const weakness of weaknesses) {
767
+ if (weakness.includes('Low average reward')) {
768
+ improvements.push('Consider alternative strategies for each step');
769
+ }
770
+ if (weakness.includes('Declining')) {
771
+ improvements.push('Re-evaluate approach when reward decreases');
772
+ }
773
+ if (weakness.includes('negative/neutral')) {
774
+ improvements.push('Focus on steps with clearer positive signals');
775
+ }
776
+ if (weakness.includes('Long trajectory')) {
777
+ improvements.push('Look for shortcuts or more direct approaches');
778
+ }
779
+ }
780
+ return improvements;
781
+ }
782
+ computeRelevanceScore(trajectory) {
783
+ // Base relevance on quality and recency
784
+ const qualityFactor = trajectory.qualityScore;
785
+ const ageDays = (Date.now() - trajectory.startTime) / (1000 * 60 * 60 * 24);
786
+ const recencyFactor = Math.exp(-ageDays / 30); // Decay over 30 days
787
+ return qualityFactor * 0.7 + recencyFactor * 0.3;
788
+ }
789
+ computeConfidence(trajectory, analysis) {
790
+ // More steps = more confidence
791
+ const stepFactor = Math.min(analysis.totalSteps / 10, 1);
792
+ // Consistent rewards = more confidence
793
+ const consistencyFactor = analysis.positiveRatio;
794
+ // Clear outcome = more confidence
795
+ const outcomeFactor = Math.abs(trajectory.qualityScore - 0.5) * 2;
796
+ return (stepFactor * 0.3 + consistencyFactor * 0.4 + outcomeFactor * 0.3);
797
+ }
798
+ extractStrategy(trajectory) {
799
+ const actions = trajectory.steps.map(s => s.action);
800
+ const uniqueActions = [...new Set(actions)];
801
+ if (uniqueActions.length <= 3) {
802
+ return `Apply ${uniqueActions.join(' -> ')}`;
803
+ }
804
+ return `Multi-step approach: ${uniqueActions.slice(0, 3).join(', ')}...`;
805
+ }
806
+ extractKeyLearnings(trajectory) {
807
+ const learnings = [];
808
+ const verdict = trajectory.verdict;
809
+ // Add key success factors
810
+ if (verdict.success) {
811
+ learnings.push(`Successful approach for ${trajectory.domain} domain`);
812
+ for (const strength of verdict.strengths.slice(0, 2)) {
813
+ learnings.push(`Strength: ${strength}`);
814
+ }
815
+ }
816
+ else {
817
+ learnings.push(`Approach needs refinement`);
818
+ for (const improvement of verdict.improvements.slice(0, 2)) {
819
+ learnings.push(`Improvement: ${improvement}`);
820
+ }
821
+ }
822
+ return learnings;
823
+ }
824
+ computeAggregateEmbedding(trajectory) {
825
+ if (trajectory.steps.length === 0) {
826
+ return new Float32Array(this.config.vectorDimension);
827
+ }
828
+ const dim = trajectory.steps[0].stateAfter.length;
829
+ const aggregate = new Float32Array(dim);
830
+ // Weighted average of step embeddings (higher weight for later steps)
831
+ let totalWeight = 0;
832
+ for (let i = 0; i < trajectory.steps.length; i++) {
833
+ const weight = (i + 1) / trajectory.steps.length;
834
+ totalWeight += weight;
835
+ const step = trajectory.steps[i];
836
+ for (let j = 0; j < dim; j++) {
837
+ aggregate[j] += step.stateAfter[j] * weight;
838
+ }
839
+ }
840
+ // Normalize
841
+ for (let j = 0; j < dim; j++) {
842
+ aggregate[j] /= totalWeight;
843
+ }
844
+ return aggregate;
845
+ }
846
+ async deduplicateMemories() {
847
+ let removed = 0;
848
+ const entries = Array.from(this.memories.entries());
849
+ for (let i = 0; i < entries.length; i++) {
850
+ for (let j = i + 1; j < entries.length; j++) {
851
+ const sim = this.cosineSimilarity(entries[i][1].memory.embedding, entries[j][1].memory.embedding);
852
+ if (sim > this.config.dedupThreshold) {
853
+ // Keep the higher quality one
854
+ if (entries[i][1].memory.quality >= entries[j][1].memory.quality) {
855
+ this.memories.delete(entries[j][0]);
856
+ await this.deleteFromAgentDB(entries[j][0]);
857
+ }
858
+ else {
859
+ this.memories.delete(entries[i][0]);
860
+ await this.deleteFromAgentDB(entries[i][0]);
861
+ }
862
+ removed++;
863
+ }
864
+ }
865
+ }
866
+ return removed;
867
+ }
868
+ async detectContradictions() {
869
+ let contradictions = 0;
870
+ const entries = Array.from(this.memories.values());
871
+ for (let i = 0; i < entries.length; i++) {
872
+ for (let j = i + 1; j < entries.length; j++) {
873
+ // Similar context but opposite outcomes
874
+ const sim = this.cosineSimilarity(entries[i].memory.embedding, entries[j].memory.embedding);
875
+ if (sim > 0.8) {
876
+ const qualityDiff = Math.abs(entries[i].memory.quality - entries[j].memory.quality);
877
+ if (qualityDiff > 0.4) {
878
+ contradictions++;
879
+ // Mark lower quality as consolidated (to exclude from retrieval)
880
+ if (entries[i].memory.quality < entries[j].memory.quality) {
881
+ entries[i].consolidated = true;
882
+ }
883
+ else {
884
+ entries[j].consolidated = true;
885
+ }
886
+ }
887
+ }
888
+ }
889
+ }
890
+ return contradictions;
891
+ }
892
+ async pruneOldPatterns() {
893
+ const now = Date.now();
894
+ const maxAge = this.config.maxPatternAgeDays * 24 * 60 * 60 * 1000;
895
+ let pruned = 0;
896
+ for (const [id, pattern] of this.patterns) {
897
+ const age = now - pattern.updatedAt;
898
+ if (age > maxAge && pattern.usageCount < 5) {
899
+ this.patterns.delete(id);
900
+ pruned++;
901
+ }
902
+ }
903
+ return pruned;
904
+ }
905
+ async mergePatterns() {
906
+ let merged = 0;
907
+ const patterns = Array.from(this.patterns.entries());
908
+ for (let i = 0; i < patterns.length; i++) {
909
+ for (let j = i + 1; j < patterns.length; j++) {
910
+ const sim = this.cosineSimilarity(patterns[i][1].embedding, patterns[j][1].embedding);
911
+ if (sim > 0.9 && patterns[i][1].domain === patterns[j][1].domain) {
912
+ // Merge into higher quality pattern
913
+ const [keepId, keep] = patterns[i][1].successRate >= patterns[j][1].successRate
914
+ ? patterns[i]
915
+ : patterns[j];
916
+ const [removeId, remove] = patterns[i][1].successRate < patterns[j][1].successRate
917
+ ? patterns[i]
918
+ : patterns[j];
919
+ // Combine statistics
920
+ keep.usageCount += remove.usageCount;
921
+ keep.qualityHistory.push(...remove.qualityHistory);
922
+ keep.evolutionHistory.push({
923
+ timestamp: Date.now(),
924
+ type: 'merge',
925
+ previousQuality: keep.successRate,
926
+ newQuality: (keep.successRate + remove.successRate) / 2,
927
+ description: `Merged with pattern ${removeId}`,
928
+ });
929
+ this.patterns.delete(removeId);
930
+ merged++;
931
+ }
932
+ }
933
+ }
934
+ return merged;
935
+ }
936
+ pruneTrajectories() {
937
+ const entries = Array.from(this.trajectories.entries())
938
+ .sort((a, b) => a[1].qualityScore - b[1].qualityScore);
939
+ const toRemove = entries.length - Math.floor(this.config.maxTrajectories * 0.8);
940
+ for (let i = 0; i < toRemove && i < entries.length; i++) {
941
+ this.trajectories.delete(entries[i][0]);
942
+ }
943
+ }
944
+ generatePatternName(memory) {
945
+ const words = memory.strategy.split(' ').slice(0, 4);
946
+ return words.join('_').toLowerCase().replace(/[^a-z0-9_]/g, '');
947
+ }
948
+ inferDomain(memory) {
949
+ // First check if we have the trajectory directly in our store
950
+ const trajectory = this.trajectories.get(memory.trajectoryId);
951
+ if (trajectory?.domain) {
952
+ return trajectory.domain;
953
+ }
954
+ // Check if the memory entry has the trajectory with domain info
955
+ const memoryEntry = this.memories.get(memory.memoryId);
956
+ if (memoryEntry?.trajectory?.domain) {
957
+ return memoryEntry.trajectory.domain;
958
+ }
959
+ return 'general';
960
+ }
961
+ determineEvolutionType(prev, curr) {
962
+ const delta = curr - prev;
963
+ if (delta > 0.05)
964
+ return 'improvement';
965
+ if (delta < -0.1)
966
+ return 'prune';
967
+ return 'improvement';
968
+ }
969
+ /**
970
+ * Check if AgentDB is available and initialized
971
+ */
972
+ isAgentDBAvailable() {
973
+ return this.agentdbAvailable;
974
+ }
975
+ }
976
+ // ============================================================================
977
+ // Factory Function
978
+ // ============================================================================
979
+ /**
980
+ * Factory function for creating ReasoningBank
981
+ */
982
+ export function createReasoningBank(config) {
983
+ return new ReasoningBank(config);
984
+ }
985
+ /**
986
+ * Create and initialize a ReasoningBank instance
987
+ */
988
+ export async function createInitializedReasoningBank(config) {
989
+ const bank = new ReasoningBank(config);
990
+ await bank.initialize();
991
+ return bank;
992
+ }
993
+ //# sourceMappingURL=reasoning-bank.js.map