adaptive-memory-multi-model-router 2.14.16 → 2.14.17
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.
- package/.a3m-vault.json +23 -0
- package/.github/workflows/ci.yml +253 -5
- package/.publish-tick +1 -1
- package/README.md +15 -17
- package/benchmark-results.json +45 -43
- package/dist/ensemble.d.ts +21 -0
- package/dist/ensemble.js +85 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +12 -4
- package/dist/tui/dashboard.js +66 -2
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/utils/tokenUtils.d.ts +48 -1
- package/dist/utils/tokenUtils.js +117 -4
- package/dist/utils/tokenUtils.js.map +1 -1
- package/docs/CITATIONS.md +2 -2
- package/docs/GEO_STATUS.md +43 -157
- package/docs/ai-plugin.json +4 -4
- package/docs/llms.txt +21 -27
- package/docs/sitemap.xml +14 -20
- package/package.json +2 -2
- package/research/PUBLISH_LOG.md +2 -2
- package/sitemap.xml +57 -0
- package/src/ensemble.ts +103 -0
- package/src/index.ts +13 -3
- package/src/tui/dashboard.ts +76 -3
- package/src/utils/tokenUtils.ts +142 -4
- package/test-council/1-structure-tests.test.js +353 -0
- package/test-council/1-structure-tests.test.ts +353 -0
- package/test-council/2-edge-case-tests.test.ts +361 -0
- package/test-council/3-performance-tests.test.ts +669 -0
- package/test-council/4-integration-tests.test.ts +391 -0
- package/test-council/5-agent-council-eval.test.ts +413 -0
- package/test-council/TEST_COUNCIL_REPORT.md +201 -0
- package/test-council/agents/edge-case-agent.ts +363 -0
- package/test-council/agents/performance-agent.ts +426 -0
- package/test-council/agents/structure-agent.ts +227 -0
- package/test-council/council.md +183 -0
- package/docs/.well-known/ai-plugin.json +0 -16
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests - Full Pipeline and End-to-End Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests that verify the entire system works together correctly.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
8
|
+
|
|
9
|
+
// Import all modules
|
|
10
|
+
const {
|
|
11
|
+
routeQuery,
|
|
12
|
+
routeBatch,
|
|
13
|
+
recommendForTask,
|
|
14
|
+
extractQueryFeatures,
|
|
15
|
+
getAvailableProviders,
|
|
16
|
+
healthCheck,
|
|
17
|
+
MemoryTree,
|
|
18
|
+
CostTracker,
|
|
19
|
+
createA3MRouter,
|
|
20
|
+
ProviderRetryHandler,
|
|
21
|
+
DEFAULT_PROVIDERS,
|
|
22
|
+
MODEL_PROFILES,
|
|
23
|
+
countTokens,
|
|
24
|
+
EnsembleOrchestrator,
|
|
25
|
+
} = require('../dist/index.js');
|
|
26
|
+
|
|
27
|
+
// ============================================================
|
|
28
|
+
// INTEGRATION TESTS - REALISTIC SCENARIOS
|
|
29
|
+
// ============================================================
|
|
30
|
+
|
|
31
|
+
describe('1. Integration - Realistic Query Scenarios', () => {
|
|
32
|
+
|
|
33
|
+
describe('Coding assistant workflow', () => {
|
|
34
|
+
it('routes code queries to appropriate provider', () => {
|
|
35
|
+
const result = routeQuery('Write a Python function to calculate fibonacci numbers');
|
|
36
|
+
expect(result.primary_model).toBeTruthy();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('routes debugging queries correctly', () => {
|
|
40
|
+
const result = routeQuery('Fix this Python code: for i in range(10) print(i)');
|
|
41
|
+
expect(result.primary_model).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('Writing assistant workflow', () => {
|
|
46
|
+
it('routes creative writing queries', () => {
|
|
47
|
+
const result = routeQuery('Write a short story about a robot learning to paint');
|
|
48
|
+
expect(result.primary_model).toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('routes summarization queries', () => {
|
|
52
|
+
const result = routeQuery('Summarize this article about climate change');
|
|
53
|
+
expect(result.primary_model).toBeTruthy();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('Translation workflow', () => {
|
|
58
|
+
it('routes translation queries', () => {
|
|
59
|
+
const result = routeQuery('Translate this paragraph to Spanish');
|
|
60
|
+
expect(result.primary_model).toBeTruthy();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ============================================================
|
|
66
|
+
// INTEGRATION TESTS - ROUTER FACTORY
|
|
67
|
+
// ============================================================
|
|
68
|
+
|
|
69
|
+
describe('2. Integration - Router Factory', () => {
|
|
70
|
+
|
|
71
|
+
describe('Full router workflow', () => {
|
|
72
|
+
it('creates router with all components', () => {
|
|
73
|
+
const router = createA3MRouter({
|
|
74
|
+
defaultProvider: 'groq',
|
|
75
|
+
enableCache: true,
|
|
76
|
+
enableGuardrails: true,
|
|
77
|
+
costLimit: 10.0
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
expect(router.route).toBeTruthy();
|
|
81
|
+
expect(router.routeBatch).toBeTruthy();
|
|
82
|
+
expect(router.recommendForTask).toBeTruthy();
|
|
83
|
+
expect(router.getAvailableProviders).toBeTruthy();
|
|
84
|
+
expect(router.healthCheck).toBeTruthy();
|
|
85
|
+
expect(router.costTracker).toBeTruthy();
|
|
86
|
+
expect(router.memoryTree).toBeTruthy();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('performs complete query flow', async () => {
|
|
90
|
+
const router = createA3MRouter({});
|
|
91
|
+
|
|
92
|
+
// Route a query
|
|
93
|
+
const routeResult = router.route('What is machine learning?');
|
|
94
|
+
expect(routeResult.primary_model).toBeTruthy();
|
|
95
|
+
|
|
96
|
+
// Add to memory
|
|
97
|
+
await router.memoryTree.add('User asked about machine learning');
|
|
98
|
+
|
|
99
|
+
// Search memory
|
|
100
|
+
const memoryResults = router.memoryTree.search('machine learning');
|
|
101
|
+
expect(Array.isArray(memoryResults)).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('handles batch routing workflow', async () => {
|
|
105
|
+
const router = createA3MRouter({});
|
|
106
|
+
|
|
107
|
+
const queries = [
|
|
108
|
+
'What is Python?',
|
|
109
|
+
'Write a hello world program',
|
|
110
|
+
'Explain photosynthesis'
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
const results = router.routeBatch(queries);
|
|
114
|
+
|
|
115
|
+
expect(results.length).toBe(queries.length);
|
|
116
|
+
|
|
117
|
+
// Add all to memory (async)
|
|
118
|
+
for (const result of results) {
|
|
119
|
+
await router.memoryTree.add(`Query with result from ${result.primary_model}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Verify routing worked
|
|
123
|
+
expect(results.every(r => r.primary_model)).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ============================================================
|
|
129
|
+
// INTEGRATION TESTS - MEMORY OPERATIONS
|
|
130
|
+
// ============================================================
|
|
131
|
+
|
|
132
|
+
describe('3. Integration - Memory Operations', () => {
|
|
133
|
+
|
|
134
|
+
it('adds and searches memory', async () => {
|
|
135
|
+
const memory = new MemoryTree();
|
|
136
|
+
|
|
137
|
+
await memory.add('Python tutorial: variables and types');
|
|
138
|
+
await memory.add('Python tutorial: functions');
|
|
139
|
+
await memory.add('JavaScript basics');
|
|
140
|
+
|
|
141
|
+
const results = memory.search('python tutorial');
|
|
142
|
+
expect(Array.isArray(results)).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('gets memory stats', async () => {
|
|
146
|
+
const memory = new MemoryTree();
|
|
147
|
+
|
|
148
|
+
await memory.add('test entry 1');
|
|
149
|
+
await memory.add('test entry 2');
|
|
150
|
+
|
|
151
|
+
const stats = memory.getStats();
|
|
152
|
+
expect(stats.totalChunks).toBeGreaterThan(0);
|
|
153
|
+
expect(typeof stats.maxDepth).toBe('number');
|
|
154
|
+
expect(typeof stats.treeSize).toBe('number');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ============================================================
|
|
159
|
+
// INTEGRATION TESTS - COST TRACKING
|
|
160
|
+
// ============================================================
|
|
161
|
+
|
|
162
|
+
describe('4. Integration - Cost Tracking', () => {
|
|
163
|
+
|
|
164
|
+
describe('CostTracker basic operations', () => {
|
|
165
|
+
it('creates cost tracker', () => {
|
|
166
|
+
const tracker = new CostTracker();
|
|
167
|
+
expect(tracker).toBeTruthy();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('calculates cost', () => {
|
|
171
|
+
const tracker = new CostTracker();
|
|
172
|
+
const cost = tracker.calculateCost('gpt-4o', 100, 50);
|
|
173
|
+
expect(cost).toBeTruthy();
|
|
174
|
+
expect(typeof cost.total).toBe('number');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('records request', () => {
|
|
178
|
+
const tracker = new CostTracker();
|
|
179
|
+
const snapshot = tracker.record('openai', 'gpt-4o', 100, 50);
|
|
180
|
+
expect(snapshot).toBeTruthy();
|
|
181
|
+
expect(snapshot.total_cost).toBeGreaterThan(0);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('gets summary', () => {
|
|
185
|
+
const tracker = new CostTracker();
|
|
186
|
+
tracker.record('openai', 'gpt-4o', 100, 50);
|
|
187
|
+
const summary = tracker.getSummary();
|
|
188
|
+
expect(summary).toBeTruthy();
|
|
189
|
+
expect(summary.request_count).toBe(1);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ============================================================
|
|
195
|
+
// INTEGRATION TESTS - PROVIDER HEALTH
|
|
196
|
+
// ============================================================
|
|
197
|
+
|
|
198
|
+
describe('5. Integration - Provider Health', () => {
|
|
199
|
+
|
|
200
|
+
describe('Health check integration', () => {
|
|
201
|
+
it('healthCheck function is available', () => {
|
|
202
|
+
expect(typeof healthCheck).toBe('function');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('getAvailableProviders shows all providers', () => {
|
|
206
|
+
const providers = getAvailableProviders();
|
|
207
|
+
expect(Object.keys(providers).length).toBeGreaterThan(0);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('recommendForTask works for different task types', () => {
|
|
211
|
+
const tasks = ['coding', 'writing', 'analysis', 'chat', 'translation'];
|
|
212
|
+
|
|
213
|
+
for (const task of tasks) {
|
|
214
|
+
const rec = recommendForTask(task);
|
|
215
|
+
expect(rec.primary).toBeTruthy();
|
|
216
|
+
expect(Array.isArray(rec.fallbacks)).toBe(true);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// ============================================================
|
|
223
|
+
// INTEGRATION TESTS - ERROR RECOVERY
|
|
224
|
+
// ============================================================
|
|
225
|
+
|
|
226
|
+
describe('6. Integration - Error Recovery', () => {
|
|
227
|
+
|
|
228
|
+
describe('Retry handler integration', () => {
|
|
229
|
+
let handler: ProviderRetryHandler;
|
|
230
|
+
|
|
231
|
+
beforeEach(() => {
|
|
232
|
+
handler = new ProviderRetryHandler();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('succeeds after transient failure', async () => {
|
|
236
|
+
const flakyFn = () => Promise.resolve('success');
|
|
237
|
+
|
|
238
|
+
const result = await handler.executeWithRetry('groq', flakyFn);
|
|
239
|
+
expect(result).toBe('success');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('validates context window', () => {
|
|
243
|
+
const result = handler.validateContextWindow('groq', 'short prompt');
|
|
244
|
+
expect(result.valid).toBe(true);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// ============================================================
|
|
250
|
+
// INTEGRATION TESTS - CONCURRENT OPERATIONS
|
|
251
|
+
// ============================================================
|
|
252
|
+
|
|
253
|
+
describe('7. Integration - Concurrent Operations', () => {
|
|
254
|
+
|
|
255
|
+
describe('Parallel query processing', () => {
|
|
256
|
+
it('handles parallel routeQuery calls', async () => {
|
|
257
|
+
const promises = Array(20).fill(null).map((_, i) =>
|
|
258
|
+
Promise.resolve(routeQuery(`concurrent query ${i}`))
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const results = await Promise.all(promises);
|
|
262
|
+
|
|
263
|
+
expect(results.length).toBe(20);
|
|
264
|
+
for (const r of results) {
|
|
265
|
+
expect(r.primary_model).toBeTruthy();
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// ============================================================
|
|
272
|
+
// INTEGRATION TESTS - DATA PIPELINES
|
|
273
|
+
// ============================================================
|
|
274
|
+
|
|
275
|
+
describe('8. Integration - Data Pipelines', () => {
|
|
276
|
+
|
|
277
|
+
describe('Query feature extraction pipeline', () => {
|
|
278
|
+
it('extracts features consistently', () => {
|
|
279
|
+
const query = 'Write a Python function to sort an array';
|
|
280
|
+
|
|
281
|
+
const features1 = extractQueryFeatures(query);
|
|
282
|
+
const features2 = extractQueryFeatures(query);
|
|
283
|
+
|
|
284
|
+
expect(features1.has_code).toBe(features2.has_code);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
describe('Token counting pipeline', () => {
|
|
289
|
+
it('counts tokens consistently', () => {
|
|
290
|
+
const text = 'This is a test sentence for token counting consistency.';
|
|
291
|
+
|
|
292
|
+
const tokens1 = countTokens(text);
|
|
293
|
+
const tokens2 = countTokens(text);
|
|
294
|
+
|
|
295
|
+
expect(tokens1).toBe(tokens2);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// ============================================================
|
|
301
|
+
// INTEGRATION TESTS - END-TO-END SCENARIOS
|
|
302
|
+
// ============================================================
|
|
303
|
+
|
|
304
|
+
describe('9. Integration - End-to-End Scenarios', () => {
|
|
305
|
+
|
|
306
|
+
describe('Complete user workflow', () => {
|
|
307
|
+
it('simulates complete conversation flow', () => {
|
|
308
|
+
const router = createA3MRouter({});
|
|
309
|
+
|
|
310
|
+
// User asks coding question
|
|
311
|
+
const q1 = router.route('Write a Python function to reverse a string');
|
|
312
|
+
expect(q1.primary_model).toBeTruthy();
|
|
313
|
+
|
|
314
|
+
// User asks follow-up
|
|
315
|
+
const q2 = router.route('Now add error handling');
|
|
316
|
+
expect(q2.primary_model).toBeTruthy();
|
|
317
|
+
|
|
318
|
+
// Verify both routed successfully
|
|
319
|
+
expect(q1.primary_model).toBeTruthy();
|
|
320
|
+
expect(q2.primary_model).toBeTruthy();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('simulates multi-turn conversation with memory', async () => {
|
|
324
|
+
const router = createA3MRouter({});
|
|
325
|
+
|
|
326
|
+
// First interaction
|
|
327
|
+
await router.memoryTree.add('User asked about web development');
|
|
328
|
+
|
|
329
|
+
// Second interaction
|
|
330
|
+
await router.memoryTree.add('User followed up on HTML question');
|
|
331
|
+
|
|
332
|
+
// Query
|
|
333
|
+
const result = router.route('How do I center a div?');
|
|
334
|
+
expect(result.primary_model).toBeTruthy();
|
|
335
|
+
|
|
336
|
+
// Verify memory works
|
|
337
|
+
const memoryResults = router.memoryTree.search('web');
|
|
338
|
+
expect(Array.isArray(memoryResults)).toBe(true);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('simulates batch processing workflow', async () => {
|
|
342
|
+
const router = createA3MRouter({});
|
|
343
|
+
|
|
344
|
+
const queries = [
|
|
345
|
+
'What is React?',
|
|
346
|
+
'Explain TypeScript',
|
|
347
|
+
'Write a REST API example',
|
|
348
|
+
'Compare SQL and NoSQL',
|
|
349
|
+
'How does HTTPS work?'
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
// Route all queries
|
|
353
|
+
const routes = router.routeBatch(queries);
|
|
354
|
+
|
|
355
|
+
// Add to memory
|
|
356
|
+
for (const route of routes) {
|
|
357
|
+
await router.memoryTree.add(`Query about something from ${route.primary_model}`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Verify batch processed
|
|
361
|
+
expect(routes.length).toBe(queries.length);
|
|
362
|
+
|
|
363
|
+
// Verify memory has entries
|
|
364
|
+
const memoryStats = router.memoryTree.getStats();
|
|
365
|
+
expect(memoryStats.totalChunks).toBeGreaterThanOrEqual(0);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// ============================================================
|
|
371
|
+
// INTEGRATION TESTS - MODEL PROFILES
|
|
372
|
+
// ============================================================
|
|
373
|
+
|
|
374
|
+
describe('10. Integration - Model Profiles', () => {
|
|
375
|
+
|
|
376
|
+
describe('Model profile access', () => {
|
|
377
|
+
it('has profiles for multiple providers', () => {
|
|
378
|
+
const providerSet = new Set(
|
|
379
|
+
Object.values(MODEL_PROFILES).map((p: any) => p.provider)
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
expect(providerSet.size).toBeGreaterThan(1);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('model profiles have strengths array', () => {
|
|
386
|
+
for (const profile of Object.values(MODEL_PROFILES) as any[]) {
|
|
387
|
+
expect(Array.isArray(profile.strengths)).toBe(true);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
});
|