agentdb 1.5.8 → 1.6.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 (62) hide show
  1. package/README.md +11 -11
  2. package/dist/agentdb.min.js +4 -4
  3. package/dist/cli/agentdb-cli.d.ts +29 -0
  4. package/dist/cli/agentdb-cli.d.ts.map +1 -1
  5. package/dist/cli/agentdb-cli.js +1009 -34
  6. package/dist/cli/agentdb-cli.js.map +1 -1
  7. package/dist/controllers/ContextSynthesizer.d.ts +65 -0
  8. package/dist/controllers/ContextSynthesizer.d.ts.map +1 -0
  9. package/dist/controllers/ContextSynthesizer.js +208 -0
  10. package/dist/controllers/ContextSynthesizer.js.map +1 -0
  11. package/dist/controllers/MMRDiversityRanker.d.ts +50 -0
  12. package/dist/controllers/MMRDiversityRanker.d.ts.map +1 -0
  13. package/dist/controllers/MMRDiversityRanker.js +130 -0
  14. package/dist/controllers/MMRDiversityRanker.js.map +1 -0
  15. package/dist/controllers/MetadataFilter.d.ts +70 -0
  16. package/dist/controllers/MetadataFilter.d.ts.map +1 -0
  17. package/dist/controllers/MetadataFilter.js +243 -0
  18. package/dist/controllers/MetadataFilter.js.map +1 -0
  19. package/dist/controllers/QUICClient.d.ts +109 -0
  20. package/dist/controllers/QUICClient.d.ts.map +1 -0
  21. package/dist/controllers/QUICClient.js +299 -0
  22. package/dist/controllers/QUICClient.js.map +1 -0
  23. package/dist/controllers/QUICServer.d.ts +121 -0
  24. package/dist/controllers/QUICServer.d.ts.map +1 -0
  25. package/dist/controllers/QUICServer.js +383 -0
  26. package/dist/controllers/QUICServer.js.map +1 -0
  27. package/dist/controllers/SyncCoordinator.d.ts +120 -0
  28. package/dist/controllers/SyncCoordinator.d.ts.map +1 -0
  29. package/dist/controllers/SyncCoordinator.js +441 -0
  30. package/dist/controllers/SyncCoordinator.js.map +1 -0
  31. package/dist/controllers/WASMVectorSearch.d.ts.map +1 -1
  32. package/dist/controllers/WASMVectorSearch.js +10 -2
  33. package/dist/controllers/WASMVectorSearch.js.map +1 -1
  34. package/dist/controllers/index.d.ts +12 -0
  35. package/dist/controllers/index.d.ts.map +1 -1
  36. package/dist/controllers/index.js +6 -0
  37. package/dist/controllers/index.js.map +1 -1
  38. package/dist/db-fallback.d.ts.map +1 -1
  39. package/dist/db-fallback.js +14 -11
  40. package/dist/db-fallback.js.map +1 -1
  41. package/dist/examples/quic-sync-example.d.ts +9 -0
  42. package/dist/examples/quic-sync-example.d.ts.map +1 -0
  43. package/dist/examples/quic-sync-example.js +169 -0
  44. package/dist/examples/quic-sync-example.js.map +1 -0
  45. package/dist/types/quic.d.ts +518 -0
  46. package/dist/types/quic.d.ts.map +1 -0
  47. package/dist/types/quic.js +272 -0
  48. package/dist/types/quic.js.map +1 -0
  49. package/package.json +9 -3
  50. package/src/browser-entry.js +41 -6
  51. package/src/cli/agentdb-cli.ts +1114 -33
  52. package/src/controllers/ContextSynthesizer.ts +285 -0
  53. package/src/controllers/MMRDiversityRanker.ts +187 -0
  54. package/src/controllers/MetadataFilter.ts +280 -0
  55. package/src/controllers/QUICClient.ts +413 -0
  56. package/src/controllers/QUICServer.ts +498 -0
  57. package/src/controllers/SyncCoordinator.ts +597 -0
  58. package/src/controllers/WASMVectorSearch.ts +11 -2
  59. package/src/controllers/index.ts +12 -0
  60. package/src/db-fallback.ts +13 -10
  61. package/src/examples/quic-sync-example.ts +198 -0
  62. package/src/types/quic.ts +772 -0
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Context Synthesis - Generate coherent narratives from multiple memories
3
+ *
4
+ * Takes a collection of retrieved episodes/patterns and synthesizes
5
+ * a coherent context summary with extracted patterns, success rates,
6
+ * and actionable insights.
7
+ */
8
+
9
+ export interface MemoryPattern {
10
+ task: string;
11
+ reward: number;
12
+ success: boolean;
13
+ critique?: string;
14
+ input?: string;
15
+ output?: string;
16
+ similarity?: number;
17
+ [key: string]: any;
18
+ }
19
+
20
+ export interface SynthesizedContext {
21
+ summary: string;
22
+ patterns: string[];
23
+ successRate: number;
24
+ averageReward: number;
25
+ recommendations: string[];
26
+ keyInsights: string[];
27
+ totalMemories: number;
28
+ }
29
+
30
+ export class ContextSynthesizer {
31
+ /**
32
+ * Synthesize context from multiple memories
33
+ *
34
+ * @param memories - Retrieved episodes/patterns
35
+ * @param options - Synthesis options
36
+ * @returns Synthesized context with insights
37
+ */
38
+ static synthesize(
39
+ memories: MemoryPattern[],
40
+ options: {
41
+ minPatternFrequency?: number;
42
+ includeRecommendations?: boolean;
43
+ maxSummaryLength?: number;
44
+ } = {}
45
+ ): SynthesizedContext {
46
+ const minPatternFrequency = options.minPatternFrequency ?? 2;
47
+ const includeRecommendations = options.includeRecommendations ?? true;
48
+
49
+ if (memories.length === 0) {
50
+ return {
51
+ summary: 'No relevant memories found.',
52
+ patterns: [],
53
+ successRate: 0,
54
+ averageReward: 0,
55
+ recommendations: [],
56
+ keyInsights: [],
57
+ totalMemories: 0,
58
+ };
59
+ }
60
+
61
+ // Calculate statistics
62
+ const successCount = memories.filter(m => m.success).length;
63
+ const successRate = successCount / memories.length;
64
+ const averageReward = memories.reduce((sum, m) => sum + (m.reward || 0), 0) / memories.length;
65
+
66
+ // Extract common patterns from critiques
67
+ const patterns = this.extractPatterns(memories, minPatternFrequency);
68
+
69
+ // Generate key insights
70
+ const keyInsights = this.generateKeyInsights(memories, successRate, averageReward);
71
+
72
+ // Generate recommendations
73
+ const recommendations = includeRecommendations
74
+ ? this.generateRecommendations(memories, patterns, successRate)
75
+ : [];
76
+
77
+ // Generate summary narrative
78
+ const summary = this.generateSummary(memories, patterns, successRate, averageReward);
79
+
80
+ return {
81
+ summary,
82
+ patterns,
83
+ successRate,
84
+ averageReward,
85
+ recommendations,
86
+ keyInsights,
87
+ totalMemories: memories.length,
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Extract common patterns from memory critiques
93
+ */
94
+ private static extractPatterns(memories: MemoryPattern[], minFrequency: number): string[] {
95
+ const phraseCount = new Map<string, number>();
96
+
97
+ // Extract meaningful phrases from critiques
98
+ for (const memory of memories) {
99
+ if (memory.critique) {
100
+ const phrases = this.extractPhrases(memory.critique);
101
+ for (const phrase of phrases) {
102
+ phraseCount.set(phrase, (phraseCount.get(phrase) || 0) + 1);
103
+ }
104
+ }
105
+ }
106
+
107
+ // Filter by minimum frequency
108
+ const patterns: string[] = [];
109
+ for (const [phrase, count] of phraseCount.entries()) {
110
+ if (count >= minFrequency) {
111
+ patterns.push(`${phrase} (${count}/${memories.length} times)`);
112
+ }
113
+ }
114
+
115
+ return patterns.slice(0, 10); // Top 10 patterns
116
+ }
117
+
118
+ /**
119
+ * Extract meaningful phrases from text
120
+ */
121
+ private static extractPhrases(text: string): string[] {
122
+ // Simple phrase extraction (can be enhanced with NLP)
123
+ const sentences = text.split(/[.!?]/).filter(s => s.trim().length > 0);
124
+ const phrases: string[] = [];
125
+
126
+ for (const sentence of sentences) {
127
+ const trimmed = sentence.trim();
128
+ // Extract phrases with key action words
129
+ if (
130
+ trimmed.match(/\b(use|implement|fix|improve|add|create|design|test)\b/i) &&
131
+ trimmed.length > 10 &&
132
+ trimmed.length < 100
133
+ ) {
134
+ phrases.push(trimmed.toLowerCase());
135
+ }
136
+ }
137
+
138
+ return phrases;
139
+ }
140
+
141
+ /**
142
+ * Generate key insights from memories
143
+ */
144
+ private static generateKeyInsights(
145
+ memories: MemoryPattern[],
146
+ successRate: number,
147
+ averageReward: number
148
+ ): string[] {
149
+ const insights: string[] = [];
150
+
151
+ // Success rate insight
152
+ if (successRate >= 0.8) {
153
+ insights.push(`High success rate (${(successRate * 100).toFixed(0)}%) indicates strong pattern match`);
154
+ } else if (successRate < 0.5) {
155
+ insights.push(`Low success rate (${(successRate * 100).toFixed(0)}%) suggests exploring alternative approaches`);
156
+ }
157
+
158
+ // Reward insight
159
+ if (averageReward >= 0.8) {
160
+ insights.push(`High average reward (${averageReward.toFixed(2)}) shows effective past solutions`);
161
+ } else if (averageReward < 0.6) {
162
+ insights.push(`Moderate reward (${averageReward.toFixed(2)}) indicates room for improvement`);
163
+ }
164
+
165
+ // Identify high-performing memories
166
+ const topMemories = memories
167
+ .filter(m => m.success && (m.reward || 0) >= 0.9)
168
+ .slice(0, 3);
169
+
170
+ if (topMemories.length > 0) {
171
+ insights.push(`${topMemories.length} exemplary solution(s) found with reward ≥0.9`);
172
+ }
173
+
174
+ // Task diversity
175
+ const uniqueTasks = new Set(memories.map(m => m.task)).size;
176
+ if (uniqueTasks > 1) {
177
+ insights.push(`${uniqueTasks} different task types provide diverse perspectives`);
178
+ }
179
+
180
+ return insights;
181
+ }
182
+
183
+ /**
184
+ * Generate actionable recommendations
185
+ */
186
+ private static generateRecommendations(
187
+ memories: MemoryPattern[],
188
+ patterns: string[],
189
+ successRate: number
190
+ ): string[] {
191
+ const recommendations: string[] = [];
192
+
193
+ // Extract successful strategies
194
+ const successfulMemories = memories.filter(m => m.success && (m.reward || 0) >= 0.8);
195
+
196
+ if (successfulMemories.length > 0) {
197
+ recommendations.push('Apply strategies from high-reward solutions');
198
+ }
199
+
200
+ // Pattern-based recommendations
201
+ if (patterns.length > 0) {
202
+ recommendations.push(`Follow common patterns: ${patterns[0].split(' (')[0]}`);
203
+ }
204
+
205
+ // Success rate recommendations
206
+ if (successRate >= 0.7) {
207
+ recommendations.push('Previous approaches were effective - follow similar methodology');
208
+ } else {
209
+ recommendations.push('Consider alternative approaches given mixed past results');
210
+ }
211
+
212
+ // Add general recommendations
213
+ if (memories.length >= 5) {
214
+ recommendations.push('Sufficient historical data available for confident decision-making');
215
+ } else {
216
+ recommendations.push('Limited data - proceed with caution and validate assumptions');
217
+ }
218
+
219
+ return recommendations.slice(0, 5);
220
+ }
221
+
222
+ /**
223
+ * Generate narrative summary
224
+ */
225
+ private static generateSummary(
226
+ memories: MemoryPattern[],
227
+ patterns: string[],
228
+ successRate: number,
229
+ averageReward: number
230
+ ): string {
231
+ const parts: string[] = [];
232
+
233
+ // Opening
234
+ parts.push(`Based on ${memories.length} similar past ${memories.length === 1 ? 'experience' : 'experiences'}`);
235
+
236
+ // Success rate
237
+ const successPercent = (successRate * 100).toFixed(0);
238
+ if (successRate >= 0.7) {
239
+ parts.push(`with a high success rate of ${successPercent}%`);
240
+ } else {
241
+ parts.push(`with a ${successPercent}% success rate`);
242
+ }
243
+
244
+ // Average reward
245
+ parts.push(`and average reward of ${averageReward.toFixed(2)}`);
246
+
247
+ // Key patterns
248
+ if (patterns.length > 0) {
249
+ parts.push('. Common effective approaches include:');
250
+ const topPatterns = patterns.slice(0, 3).map(p => p.split(' (')[0]);
251
+ parts.push(topPatterns.map((p, i) => `${i + 1}) ${p}`).join(', '));
252
+ }
253
+
254
+ // High performers
255
+ const topMemories = memories.filter(m => m.success && (m.reward || 0) >= 0.9);
256
+ if (topMemories.length > 0) {
257
+ parts.push(`. ${topMemories.length} exemplary solution(s) achieved reward ≥0.9`);
258
+ }
259
+
260
+ parts.push('.');
261
+
262
+ return parts.join(' ');
263
+ }
264
+
265
+ /**
266
+ * Extract actionable steps from successful memories
267
+ */
268
+ static extractActionableSteps(memories: MemoryPattern[]): string[] {
269
+ const steps: string[] = [];
270
+ const successfulMemories = memories.filter(m => m.success && (m.reward || 0) >= 0.8);
271
+
272
+ for (const memory of successfulMemories) {
273
+ if (memory.critique) {
274
+ // Extract step-like phrases
275
+ const matches = memory.critique.match(/\b\d+\.\s+([^.!?]+)/g);
276
+ if (matches) {
277
+ steps.push(...matches.map(m => m.trim()));
278
+ }
279
+ }
280
+ }
281
+
282
+ // Remove duplicates and return top 5
283
+ return Array.from(new Set(steps)).slice(0, 5);
284
+ }
285
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * MMR (Maximal Marginal Relevance) Diversity Ranking
3
+ *
4
+ * Implements MMR algorithm to select diverse results that balance
5
+ * relevance to query with diversity from already-selected results.
6
+ *
7
+ * Formula: MMR = argmax [λ × Sim(Di, Q) - (1-λ) × max Sim(Di, Dj)]
8
+ * Di∈R\S Dj∈S
9
+ *
10
+ * Where:
11
+ * - Di = candidate document
12
+ * - Q = query
13
+ * - S = already selected documents
14
+ * - λ = balance parameter (0 = max diversity, 1 = max relevance)
15
+ */
16
+
17
+ export interface MMROptions {
18
+ lambda?: number; // Balance between relevance and diversity (default: 0.5)
19
+ k?: number; // Number of results to return (default: 10)
20
+ metric?: 'cosine' | 'euclidean' | 'dot'; // Similarity metric
21
+ }
22
+
23
+ export interface MMRCandidate {
24
+ id: number;
25
+ embedding: number[];
26
+ similarity: number; // Similarity to query
27
+ [key: string]: any; // Additional data
28
+ }
29
+
30
+ export class MMRDiversityRanker {
31
+ /**
32
+ * Select diverse results using MMR algorithm
33
+ *
34
+ * @param candidates - All candidate results with embeddings
35
+ * @param queryEmbedding - Query vector
36
+ * @param options - MMR configuration
37
+ * @returns Diverse subset of candidates
38
+ */
39
+ static selectDiverse(
40
+ candidates: MMRCandidate[],
41
+ queryEmbedding: number[],
42
+ options: MMROptions = {}
43
+ ): MMRCandidate[] {
44
+ const lambda = options.lambda ?? 0.5;
45
+ const k = options.k ?? 10;
46
+ const metric = options.metric ?? 'cosine';
47
+
48
+ if (candidates.length === 0) {
49
+ return [];
50
+ }
51
+
52
+ if (candidates.length <= k) {
53
+ return candidates;
54
+ }
55
+
56
+ // Calculate initial similarities to query
57
+ const candidatesWithSim = candidates.map(c => ({
58
+ ...c,
59
+ similarity: c.similarity ?? this.calculateSimilarity(
60
+ queryEmbedding,
61
+ c.embedding,
62
+ metric
63
+ ),
64
+ }));
65
+
66
+ const selected: MMRCandidate[] = [];
67
+ const remaining = [...candidatesWithSim];
68
+
69
+ // Select first item (highest relevance)
70
+ remaining.sort((a, b) => b.similarity - a.similarity);
71
+ selected.push(remaining.shift()!);
72
+
73
+ // Iteratively select items with highest MMR score
74
+ while (selected.length < k && remaining.length > 0) {
75
+ let maxMMR = -Infinity;
76
+ let maxIdx = 0;
77
+
78
+ for (let i = 0; i < remaining.length; i++) {
79
+ const candidate = remaining[i];
80
+
81
+ // Calculate max similarity to already-selected items
82
+ let maxSimToSelected = -Infinity;
83
+ for (const selectedItem of selected) {
84
+ const sim = this.calculateSimilarity(
85
+ candidate.embedding,
86
+ selectedItem.embedding,
87
+ metric
88
+ );
89
+ maxSimToSelected = Math.max(maxSimToSelected, sim);
90
+ }
91
+
92
+ // Calculate MMR score
93
+ const mmrScore = lambda * candidate.similarity - (1 - lambda) * maxSimToSelected;
94
+
95
+ if (mmrScore > maxMMR) {
96
+ maxMMR = mmrScore;
97
+ maxIdx = i;
98
+ }
99
+ }
100
+
101
+ // Add item with highest MMR score
102
+ selected.push(remaining.splice(maxIdx, 1)[0]);
103
+ }
104
+
105
+ return selected;
106
+ }
107
+
108
+ /**
109
+ * Calculate similarity between two vectors
110
+ */
111
+ private static calculateSimilarity(
112
+ vec1: number[],
113
+ vec2: number[],
114
+ metric: 'cosine' | 'euclidean' | 'dot'
115
+ ): number {
116
+ if (vec1.length !== vec2.length) {
117
+ throw new Error(`Vector dimension mismatch: ${vec1.length} vs ${vec2.length}`);
118
+ }
119
+
120
+ switch (metric) {
121
+ case 'cosine': {
122
+ let dot = 0, mag1 = 0, mag2 = 0;
123
+ for (let i = 0; i < vec1.length; i++) {
124
+ dot += vec1[i] * vec2[i];
125
+ mag1 += vec1[i] * vec1[i];
126
+ mag2 += vec2[i] * vec2[i];
127
+ }
128
+ return dot / (Math.sqrt(mag1) * Math.sqrt(mag2));
129
+ }
130
+
131
+ case 'euclidean': {
132
+ let sum = 0;
133
+ for (let i = 0; i < vec1.length; i++) {
134
+ const diff = vec1[i] - vec2[i];
135
+ sum += diff * diff;
136
+ }
137
+ return 1 / (1 + Math.sqrt(sum)); // Normalized to 0-1
138
+ }
139
+
140
+ case 'dot': {
141
+ let dot = 0;
142
+ for (let i = 0; i < vec1.length; i++) {
143
+ dot += vec1[i] * vec2[i];
144
+ }
145
+ return dot;
146
+ }
147
+
148
+ default:
149
+ throw new Error(`Unknown metric: ${metric}`);
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Calculate diversity score for a set of results
155
+ *
156
+ * @param results - Results to analyze
157
+ * @param metric - Similarity metric
158
+ * @returns Average pairwise distance (higher = more diverse)
159
+ */
160
+ static calculateDiversityScore(
161
+ results: MMRCandidate[],
162
+ metric: 'cosine' | 'euclidean' | 'dot' = 'cosine'
163
+ ): number {
164
+ if (results.length < 2) {
165
+ return 1.0; // Single result is maximally diverse
166
+ }
167
+
168
+ let totalDistance = 0;
169
+ let comparisons = 0;
170
+
171
+ for (let i = 0; i < results.length; i++) {
172
+ for (let j = i + 1; j < results.length; j++) {
173
+ const similarity = this.calculateSimilarity(
174
+ results[i].embedding,
175
+ results[j].embedding,
176
+ metric
177
+ );
178
+ // Convert similarity to distance
179
+ const distance = metric === 'cosine' ? 1 - similarity : similarity;
180
+ totalDistance += distance;
181
+ comparisons++;
182
+ }
183
+ }
184
+
185
+ return comparisons > 0 ? totalDistance / comparisons : 0;
186
+ }
187
+ }