agentdb 1.2.0 → 1.3.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 (66) hide show
  1. package/README.md +180 -33
  2. package/dist/cli/agentdb-cli.d.ts +1 -0
  3. package/dist/cli/agentdb-cli.d.ts.map +1 -1
  4. package/dist/cli/agentdb-cli.js +108 -134
  5. package/dist/cli/agentdb-cli.js.map +1 -1
  6. package/dist/controllers/CausalMemoryGraph.d.ts.map +1 -1
  7. package/dist/controllers/CausalMemoryGraph.js +3 -3
  8. package/dist/controllers/CausalMemoryGraph.js.map +1 -1
  9. package/dist/controllers/CausalRecall.d.ts +25 -0
  10. package/dist/controllers/CausalRecall.d.ts.map +1 -1
  11. package/dist/controllers/CausalRecall.js +44 -1
  12. package/dist/controllers/CausalRecall.js.map +1 -1
  13. package/dist/controllers/EmbeddingService.d.ts.map +1 -1
  14. package/dist/controllers/EmbeddingService.js +4 -0
  15. package/dist/controllers/EmbeddingService.js.map +1 -1
  16. package/dist/controllers/ExplainableRecall.js +1 -1
  17. package/dist/controllers/LearningSystem.d.ts +194 -0
  18. package/dist/controllers/LearningSystem.d.ts.map +1 -0
  19. package/dist/controllers/LearningSystem.js +929 -0
  20. package/dist/controllers/LearningSystem.js.map +1 -0
  21. package/dist/controllers/NightlyLearner.d.ts.map +1 -1
  22. package/dist/controllers/NightlyLearner.js +9 -1
  23. package/dist/controllers/NightlyLearner.js.map +1 -1
  24. package/dist/controllers/ReasoningBank.d.ts +96 -0
  25. package/dist/controllers/ReasoningBank.d.ts.map +1 -0
  26. package/dist/controllers/ReasoningBank.js +302 -0
  27. package/dist/controllers/ReasoningBank.js.map +1 -0
  28. package/dist/controllers/ReflexionMemory.d.ts.map +1 -1
  29. package/dist/controllers/ReflexionMemory.js +4 -0
  30. package/dist/controllers/ReflexionMemory.js.map +1 -1
  31. package/dist/controllers/SkillLibrary.d.ts +37 -3
  32. package/dist/controllers/SkillLibrary.d.ts.map +1 -1
  33. package/dist/controllers/SkillLibrary.js +196 -15
  34. package/dist/controllers/SkillLibrary.js.map +1 -1
  35. package/dist/mcp/agentdb-mcp-server.d.ts +8 -0
  36. package/dist/mcp/agentdb-mcp-server.d.ts.map +1 -0
  37. package/dist/mcp/agentdb-mcp-server.js +1485 -352
  38. package/dist/mcp/agentdb-mcp-server.js.map +1 -0
  39. package/dist/mcp/learning-tools-handlers.d.ts +16 -0
  40. package/dist/mcp/learning-tools-handlers.d.ts.map +1 -0
  41. package/dist/mcp/learning-tools-handlers.js +105 -0
  42. package/dist/mcp/learning-tools-handlers.js.map +1 -0
  43. package/dist/optimizations/QueryOptimizer.d.ts.map +1 -1
  44. package/dist/optimizations/QueryOptimizer.js +3 -1
  45. package/dist/optimizations/QueryOptimizer.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/cli/agentdb-cli.ts +136 -51
  48. package/src/controllers/CausalMemoryGraph.ts +2 -3
  49. package/src/controllers/CausalRecall.ts +73 -1
  50. package/src/controllers/EmbeddingService.ts +6 -1
  51. package/src/controllers/ExplainableRecall.ts +1 -1
  52. package/src/controllers/LearningSystem.ts +1286 -0
  53. package/src/controllers/NightlyLearner.ts +11 -1
  54. package/src/controllers/ReasoningBank.ts +411 -0
  55. package/src/controllers/ReflexionMemory.ts +4 -0
  56. package/src/controllers/SkillLibrary.ts +254 -16
  57. package/src/mcp/agentdb-mcp-server.ts +1710 -0
  58. package/src/mcp/learning-tools-handlers.ts +106 -0
  59. package/src/optimizations/QueryOptimizer.ts +4 -2
  60. package/dist/benchmarks/comprehensive-benchmark.js +0 -664
  61. package/dist/benchmarks/frontier-benchmark.js +0 -419
  62. package/dist/benchmarks/reflexion-benchmark.js +0 -370
  63. package/dist/cli/agentdb-cli.js.backup +0 -718
  64. package/dist/schemas/frontier-schema.sql +0 -341
  65. package/dist/schemas/schema.sql +0 -382
  66. package/dist/tests/frontier-features.test.js +0 -665
@@ -59,8 +59,8 @@ export class SkillLibrary {
59
59
  const stmt = this.db.prepare(`
60
60
  INSERT INTO skills (
61
61
  name, description, signature, code, success_rate, uses,
62
- avg_reward, avg_latency_ms, created_from_episode, metadata
63
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
62
+ avg_reward, avg_latency_ms, metadata
63
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
64
64
  `);
65
65
 
66
66
  const result = stmt.run(
@@ -72,7 +72,6 @@ export class SkillLibrary {
72
72
  skill.uses,
73
73
  skill.avgReward,
74
74
  skill.avgLatencyMs,
75
- skill.createdFromEpisode || null,
76
75
  skill.metadata ? JSON.stringify(skill.metadata) : null
77
76
  );
78
77
 
@@ -226,15 +225,30 @@ export class SkillLibrary {
226
225
  }
227
226
 
228
227
  /**
229
- * Consolidate high-reward episodes into skills
230
- * This is the core learning mechanism
228
+ * Consolidate high-reward episodes into skills with ML pattern extraction
229
+ * This is the core learning mechanism enhanced with pattern analysis
231
230
  */
232
- consolidateEpisodesIntoSkills(config: {
231
+ async consolidateEpisodesIntoSkills(config: {
233
232
  minAttempts?: number;
234
233
  minReward?: number;
235
234
  timeWindowDays?: number;
236
- }): number {
237
- const { minAttempts = 3, minReward = 0.7, timeWindowDays = 7 } = config;
235
+ extractPatterns?: boolean;
236
+ }): Promise<{
237
+ created: number;
238
+ updated: number;
239
+ patterns: Array<{
240
+ task: string;
241
+ commonPatterns: string[];
242
+ successIndicators: string[];
243
+ avgReward: number;
244
+ }>;
245
+ }> {
246
+ const {
247
+ minAttempts = 3,
248
+ minReward = 0.7,
249
+ timeWindowDays = 7,
250
+ extractPatterns = true
251
+ } = config;
238
252
 
239
253
  const stmt = this.db.prepare(`
240
254
  SELECT
@@ -254,16 +268,47 @@ export class SkillLibrary {
254
268
 
255
269
  const candidates = stmt.all(timeWindowDays * 86400, minReward, minAttempts);
256
270
  let created = 0;
271
+ let updated = 0;
272
+ const patterns: Array<{
273
+ task: string;
274
+ commonPatterns: string[];
275
+ successIndicators: string[];
276
+ avgReward: number;
277
+ }> = [];
257
278
 
258
279
  for (const candidate of candidates as any[]) {
280
+ const episodeIds = candidate.episode_ids.split(',').map(Number);
281
+
282
+ // Extract patterns from successful episodes if requested
283
+ let extractedPatterns: string[] = [];
284
+ let successIndicators: string[] = [];
285
+ let enhancedDescription = `Auto-generated skill from successful episodes`;
286
+
287
+ if (extractPatterns) {
288
+ const patternData = await this.extractPatternsFromEpisodes(episodeIds);
289
+ extractedPatterns = patternData.commonPatterns;
290
+ successIndicators = patternData.successIndicators;
291
+
292
+ if (extractedPatterns.length > 0) {
293
+ enhancedDescription = `Skill learned from ${episodeIds.length} successful episodes. Common patterns: ${extractedPatterns.slice(0, 3).join(', ')}`;
294
+ }
295
+
296
+ patterns.push({
297
+ task: candidate.task,
298
+ commonPatterns: extractedPatterns,
299
+ successIndicators: successIndicators,
300
+ avgReward: candidate.avg_reward
301
+ });
302
+ }
303
+
259
304
  // Check if skill already exists
260
305
  const existing = this.db.prepare('SELECT id FROM skills WHERE name = ?').get(candidate.task);
261
306
 
262
307
  if (!existing) {
263
- // Create new skill
308
+ // Create new skill with extracted patterns
264
309
  const skill: Skill = {
265
310
  name: candidate.task,
266
- description: `Auto-generated skill from successful episodes`,
311
+ description: enhancedDescription,
267
312
  signature: {
268
313
  inputs: { task: 'string' },
269
314
  outputs: { result: 'any' }
@@ -274,15 +319,16 @@ export class SkillLibrary {
274
319
  avgLatencyMs: candidate.avg_latency || 0,
275
320
  createdFromEpisode: candidate.latest_episode_id,
276
321
  metadata: {
277
- sourceEpisodes: candidate.episode_ids.split(',').map(Number),
322
+ sourceEpisodes: episodeIds,
278
323
  autoGenerated: true,
279
- consolidatedAt: Date.now()
324
+ consolidatedAt: Date.now(),
325
+ extractedPatterns: extractedPatterns,
326
+ successIndicators: successIndicators,
327
+ patternConfidence: this.calculatePatternConfidence(episodeIds.length, candidate.success_rate)
280
328
  }
281
329
  };
282
330
 
283
- this.createSkill(skill).catch(err => {
284
- console.error('Error creating skill:', err);
285
- });
331
+ await this.createSkill(skill);
286
332
  created++;
287
333
  } else {
288
334
  // Update existing skill stats
@@ -292,10 +338,202 @@ export class SkillLibrary {
292
338
  candidate.avg_reward,
293
339
  candidate.avg_latency || 0
294
340
  );
341
+ updated++;
295
342
  }
296
343
  }
297
344
 
298
- return created;
345
+ return { created, updated, patterns };
346
+ }
347
+
348
+ /**
349
+ * Extract common patterns from successful episodes using ML-inspired analysis
350
+ */
351
+ private async extractPatternsFromEpisodes(episodeIds: number[]): Promise<{
352
+ commonPatterns: string[];
353
+ successIndicators: string[];
354
+ }> {
355
+ // Retrieve episodes with their outputs and critiques
356
+ const episodes = this.db.prepare(`
357
+ SELECT id, task, input, output, critique, reward, success, metadata
358
+ FROM episodes
359
+ WHERE id IN (${episodeIds.map(() => '?').join(',')})
360
+ AND success = 1
361
+ `).all(...episodeIds) as any[];
362
+
363
+ if (episodes.length === 0) {
364
+ return { commonPatterns: [], successIndicators: [] };
365
+ }
366
+
367
+ const commonPatterns: string[] = [];
368
+ const successIndicators: string[] = [];
369
+
370
+ // Pattern 1: Analyze output text for common keywords and phrases
371
+ const outputTexts = episodes
372
+ .map(ep => ep.output)
373
+ .filter(Boolean);
374
+
375
+ if (outputTexts.length > 0) {
376
+ const keywordFrequency = this.extractKeywordFrequency(outputTexts);
377
+ const topKeywords = this.getTopKeywords(keywordFrequency, 5);
378
+
379
+ if (topKeywords.length > 0) {
380
+ commonPatterns.push(`Common techniques: ${topKeywords.join(', ')}`);
381
+ }
382
+ }
383
+
384
+ // Pattern 2: Analyze critique patterns for successful strategies
385
+ const critiques = episodes
386
+ .map(ep => ep.critique)
387
+ .filter(Boolean);
388
+
389
+ if (critiques.length > 0) {
390
+ const critiqueKeywords = this.extractKeywordFrequency(critiques);
391
+ const topCritiquePatterns = this.getTopKeywords(critiqueKeywords, 3);
392
+
393
+ if (topCritiquePatterns.length > 0) {
394
+ successIndicators.push(...topCritiquePatterns);
395
+ }
396
+ }
397
+
398
+ // Pattern 3: Analyze reward distribution
399
+ const avgReward = episodes.reduce((sum, ep) => sum + ep.reward, 0) / episodes.length;
400
+ const highRewardCount = episodes.filter(ep => ep.reward > avgReward).length;
401
+ const highRewardRatio = highRewardCount / episodes.length;
402
+
403
+ if (highRewardRatio > 0.6) {
404
+ successIndicators.push(`High consistency (${(highRewardRatio * 100).toFixed(0)}% above average)`);
405
+ }
406
+
407
+ // Pattern 4: Analyze metadata for common parameters
408
+ const metadataPatterns = this.extractMetadataPatterns(episodes);
409
+ if (metadataPatterns.length > 0) {
410
+ commonPatterns.push(...metadataPatterns);
411
+ }
412
+
413
+ // Pattern 5: Temporal analysis - learning curve
414
+ const learningTrend = this.analyzeLearningTrend(episodes);
415
+ if (learningTrend) {
416
+ successIndicators.push(learningTrend);
417
+ }
418
+
419
+ return { commonPatterns, successIndicators };
420
+ }
421
+
422
+ /**
423
+ * Extract keyword frequency from text array using NLP-inspired techniques
424
+ */
425
+ private extractKeywordFrequency(texts: string[]): Map<string, number> {
426
+ const frequency = new Map<string, number>();
427
+
428
+ // Common stop words to filter out
429
+ const stopWords = new Set([
430
+ 'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
431
+ 'of', 'with', 'by', 'from', 'as', 'is', 'was', 'are', 'were', 'been',
432
+ 'be', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'should',
433
+ 'could', 'may', 'might', 'must', 'can', 'this', 'that', 'these', 'those'
434
+ ]);
435
+
436
+ for (const text of texts) {
437
+ // Extract words (alphanumeric sequences)
438
+ const words = text.toLowerCase().match(/\b[a-z0-9_-]+\b/g) || [];
439
+
440
+ for (const word of words) {
441
+ if (word.length > 3 && !stopWords.has(word)) {
442
+ frequency.set(word, (frequency.get(word) || 0) + 1);
443
+ }
444
+ }
445
+ }
446
+
447
+ return frequency;
448
+ }
449
+
450
+ /**
451
+ * Get top N keywords by frequency
452
+ */
453
+ private getTopKeywords(frequency: Map<string, number>, n: number): string[] {
454
+ return Array.from(frequency.entries())
455
+ .sort((a, b) => b[1] - a[1])
456
+ .slice(0, n)
457
+ .filter(([_, count]) => count >= 2) // Only keywords appearing at least twice
458
+ .map(([word, _]) => word);
459
+ }
460
+
461
+ /**
462
+ * Extract common patterns from episode metadata
463
+ */
464
+ private extractMetadataPatterns(episodes: any[]): string[] {
465
+ const patterns: string[] = [];
466
+ const metadataFields = new Map<string, Set<any>>();
467
+
468
+ for (const episode of episodes) {
469
+ if (episode.metadata) {
470
+ try {
471
+ const metadata = typeof episode.metadata === 'string'
472
+ ? JSON.parse(episode.metadata)
473
+ : episode.metadata;
474
+
475
+ for (const [key, value] of Object.entries(metadata)) {
476
+ if (!metadataFields.has(key)) {
477
+ metadataFields.set(key, new Set());
478
+ }
479
+ metadataFields.get(key)!.add(value);
480
+ }
481
+ } catch (e) {
482
+ // Skip invalid metadata
483
+ }
484
+ }
485
+ }
486
+
487
+ // Find fields with consistent values
488
+ metadataFields.forEach((values, field) => {
489
+ if (values.size === 1) {
490
+ // All episodes have the same value for this field
491
+ const value = Array.from(values)[0];
492
+ patterns.push(`Consistent ${field}: ${value}`);
493
+ }
494
+ });
495
+
496
+ return patterns;
497
+ }
498
+
499
+ /**
500
+ * Analyze learning trend across episodes
501
+ */
502
+ private analyzeLearningTrend(episodes: any[]): string | null {
503
+ if (episodes.length < 3) return null;
504
+
505
+ // Sort by episode ID (temporal order)
506
+ const sorted = [...episodes].sort((a, b) => a.id - b.id);
507
+
508
+ const firstHalfReward = sorted.slice(0, Math.floor(sorted.length / 2))
509
+ .reduce((sum, ep) => sum + ep.reward, 0) / Math.floor(sorted.length / 2);
510
+
511
+ const secondHalfReward = sorted.slice(Math.floor(sorted.length / 2))
512
+ .reduce((sum, ep) => sum + ep.reward, 0) / (sorted.length - Math.floor(sorted.length / 2));
513
+
514
+ const improvement = ((secondHalfReward - firstHalfReward) / firstHalfReward) * 100;
515
+
516
+ if (improvement > 10) {
517
+ return `Strong learning curve (+${improvement.toFixed(0)}% improvement)`;
518
+ } else if (improvement > 5) {
519
+ return `Moderate learning curve (+${improvement.toFixed(0)}% improvement)`;
520
+ } else if (Math.abs(improvement) < 5) {
521
+ return `Stable performance (±${Math.abs(improvement).toFixed(0)}%)`;
522
+ }
523
+
524
+ return null;
525
+ }
526
+
527
+ /**
528
+ * Calculate pattern confidence score based on sample size and success rate
529
+ */
530
+ private calculatePatternConfidence(sampleSize: number, successRate: number): number {
531
+ // Confidence increases with sample size and success rate
532
+ // Using a sigmoid-like function for smooth scaling
533
+ const sampleFactor = Math.min(sampleSize / 10, 1.0); // Saturates at 10 samples
534
+ const successFactor = successRate;
535
+
536
+ return Math.min(sampleFactor * successFactor, 0.99);
299
537
  }
300
538
 
301
539
  /**