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.
Files changed (38) hide show
  1. package/.a3m-vault.json +23 -0
  2. package/.github/workflows/ci.yml +253 -5
  3. package/.publish-tick +1 -1
  4. package/README.md +15 -17
  5. package/benchmark-results.json +45 -43
  6. package/dist/ensemble.d.ts +21 -0
  7. package/dist/ensemble.js +85 -0
  8. package/dist/index.d.ts +3 -1
  9. package/dist/index.js +12 -4
  10. package/dist/tui/dashboard.js +66 -2
  11. package/dist/tui/dashboard.js.map +1 -1
  12. package/dist/utils/tokenUtils.d.ts +48 -1
  13. package/dist/utils/tokenUtils.js +117 -4
  14. package/dist/utils/tokenUtils.js.map +1 -1
  15. package/docs/CITATIONS.md +2 -2
  16. package/docs/GEO_STATUS.md +43 -157
  17. package/docs/ai-plugin.json +4 -4
  18. package/docs/llms.txt +21 -27
  19. package/docs/sitemap.xml +14 -20
  20. package/package.json +2 -2
  21. package/research/PUBLISH_LOG.md +2 -2
  22. package/sitemap.xml +57 -0
  23. package/src/ensemble.ts +103 -0
  24. package/src/index.ts +13 -3
  25. package/src/tui/dashboard.ts +76 -3
  26. package/src/utils/tokenUtils.ts +142 -4
  27. package/test-council/1-structure-tests.test.js +353 -0
  28. package/test-council/1-structure-tests.test.ts +353 -0
  29. package/test-council/2-edge-case-tests.test.ts +361 -0
  30. package/test-council/3-performance-tests.test.ts +669 -0
  31. package/test-council/4-integration-tests.test.ts +391 -0
  32. package/test-council/5-agent-council-eval.test.ts +413 -0
  33. package/test-council/TEST_COUNCIL_REPORT.md +201 -0
  34. package/test-council/agents/edge-case-agent.ts +363 -0
  35. package/test-council/agents/performance-agent.ts +426 -0
  36. package/test-council/agents/structure-agent.ts +227 -0
  37. package/test-council/council.md +183 -0
  38. package/docs/.well-known/ai-plugin.json +0 -16
@@ -0,0 +1,363 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Edge Case Agent - Identifies failure modes and boundary conditions
4
+ *
5
+ * This agent identifies:
6
+ * - Empty/null/undefined inputs
7
+ * - Boundary values
8
+ * - Error handling paths
9
+ * - Race conditions
10
+ * - Concurrent access patterns
11
+ */
12
+
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+
16
+ interface EdgeCase {
17
+ category: 'input' | 'boundary' | 'error' | 'concurrency' | 'timeout';
18
+ description: string;
19
+ testName: string;
20
+ code: string;
21
+ severity: 'critical' | 'high' | 'medium' | 'low';
22
+ }
23
+
24
+ // Common edge case patterns
25
+ const EDGE_CASE_PATTERNS = {
26
+ emptyString: {
27
+ pattern: /function\s+\w+\s*\([^)]*text\s*:?\s*string/i,
28
+ cases: [
29
+ { input: "''", description: 'empty string' },
30
+ { input: '" "', description: 'whitespace-only string' },
31
+ { input: '""', description: 'double empty quotes' },
32
+ ]
33
+ },
34
+ nullUndefined: {
35
+ pattern: /function\s+\w+\s*\([^)]*\w+\s*:?\s*\w+/i,
36
+ cases: [
37
+ { input: 'null', description: 'null value' },
38
+ { input: 'undefined', description: 'undefined value' },
39
+ ]
40
+ },
41
+ arrays: {
42
+ pattern: /function\s+\w+\s*\([^)]*array|items|\[\]/i,
43
+ cases: [
44
+ { input: '[]', description: 'empty array' },
45
+ { input: '[null]', description: 'array with null' },
46
+ { input: '[undefined]', description: 'array with undefined' },
47
+ ]
48
+ },
49
+ numbers: {
50
+ pattern: /function\s+\w+\s*\([^)]*count|size|length|index/i,
51
+ cases: [
52
+ { input: '0', description: 'zero' },
53
+ { input: '-1', description: 'negative one' },
54
+ { input: 'Number.MAX_VALUE', description: 'MAX_VALUE' },
55
+ { input: 'Number.MIN_VALUE', description: 'MIN_VALUE' },
56
+ { input: 'Infinity', description: 'Infinity' },
57
+ { input: '-Infinity', description: '-Infinity' },
58
+ { input: 'NaN', description: 'NaN' },
59
+ ]
60
+ },
61
+ functions: {
62
+ pattern: /async\s+function\s+\w+|function\s+\w+\s*\([^)]*callback/i,
63
+ cases: [
64
+ { input: 'Promise.resolve()', description: 'immediately resolving promise' },
65
+ { input: 'Promise.reject(new Error())', description: 'immediately rejecting promise' },
66
+ { input: '() => new Promise(r => setTimeout(() => r(), 10000))', description: 'slow function (10s)' },
67
+ { input: '() => new Promise((_, r) => setTimeout(() => r(new Error()), 1000))', description: 'slow error (1s)' },
68
+ ]
69
+ }
70
+ };
71
+
72
+ interface AnalysisResult {
73
+ edgeCases: EdgeCase[];
74
+ coverage: number;
75
+ criticalPaths: string[];
76
+ }
77
+
78
+ // Main analysis function
79
+ function analyzeEdgeCases(projectRoot: string): AnalysisResult {
80
+ const srcDir = path.join(projectRoot, 'src');
81
+ const edgeCases: EdgeCase[] = [];
82
+
83
+ // Find all TypeScript files
84
+ const files = findTsFiles(srcDir);
85
+
86
+ for (const file of files) {
87
+ const content = fs.readFileSync(file, 'utf-8');
88
+ const fileCases = analyzeFile(content, file);
89
+ edgeCases.push(...fileCases);
90
+ }
91
+
92
+ // Calculate coverage based on existing tests
93
+ const testFiles = findTestFiles(projectRoot);
94
+ const testContent = testFiles.map(f => fs.readFileSync(f, 'utf-8')).join('\n');
95
+
96
+ const testedPatterns = new Set<string>();
97
+ for (const edge of edgeCases) {
98
+ if (testContent.includes(edge.testName) || testContent.includes(edge.description)) {
99
+ testedPatterns.add(edge.testName);
100
+ }
101
+ }
102
+
103
+ const coverage = edgeCases.length > 0
104
+ ? (testedPatterns.size / edgeCases.length) * 100
105
+ : 0;
106
+
107
+ // Identify critical paths
108
+ const criticalPaths = identifyCriticalPaths(edgeCases);
109
+
110
+ return { edgeCases, coverage, criticalPaths };
111
+ }
112
+
113
+ function findTsFiles(dir: string): string[] {
114
+ const files: string[] = [];
115
+
116
+ function walk(d: string) {
117
+ const entries = fs.readdirSync(d, { withFileTypes: true });
118
+ for (const entry of entries) {
119
+ if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '__pycache__') continue;
120
+ const fullPath = path.join(d, entry.name);
121
+ if (entry.isDirectory()) {
122
+ walk(fullPath);
123
+ } else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {
124
+ files.push(fullPath);
125
+ }
126
+ }
127
+ }
128
+
129
+ walk(dir);
130
+ return files;
131
+ }
132
+
133
+ function findTestFiles(projectRoot: string): string[] {
134
+ const testDirs = ['test', 'tests', 'test-council'];
135
+ const files: string[] = [];
136
+
137
+ for (const dir of testDirs) {
138
+ const testDir = path.join(projectRoot, dir);
139
+ if (fs.existsSync(testDir)) {
140
+ files.push(...findInDir(testDir));
141
+ }
142
+ }
143
+
144
+ return files;
145
+ }
146
+
147
+ function findInDir(dir: string): string[] {
148
+ const files: string[] = [];
149
+
150
+ function walk(d: string) {
151
+ const entries = fs.readdirSync(d, { withFileTypes: true });
152
+ for (const entry of entries) {
153
+ if (entry.name === 'node_modules' || entry.name === 'dist') continue;
154
+ const fullPath = path.join(d, entry.name);
155
+ if (entry.isDirectory()) {
156
+ walk(fullPath);
157
+ } else if (entry.name.match(/\.(test|spec)\.(ts|js)$/)) {
158
+ files.push(fullPath);
159
+ }
160
+ }
161
+ }
162
+
163
+ walk(dir);
164
+ return files;
165
+ }
166
+
167
+ function analyzeFile(content: string, file: string): EdgeCase[] {
168
+ const cases: EdgeCase[] = [];
169
+ const baseName = path.basename(file, '.ts');
170
+
171
+ // Check for patterns and generate edge cases
172
+ for (const [patternName, pattern] of Object.entries(EDGE_CASE_PATTERNS)) {
173
+ if (pattern.pattern.test(content)) {
174
+ for (const testCase of pattern.cases) {
175
+ cases.push({
176
+ category: getCategory(patternName),
177
+ description: `${testCase.description} input for ${baseName}`,
178
+ testName: `handles ${testCase.description}`,
179
+ code: generateTestCode(baseName, testCase),
180
+ severity: getSeverity(patternName, testCase)
181
+ });
182
+ }
183
+ }
184
+ }
185
+
186
+ // Add error handling cases
187
+ const errorCases = analyzeErrorHandling(content, baseName);
188
+ cases.push(...errorCases);
189
+
190
+ // Add concurrency cases
191
+ const concurrencyCases = analyzeConcurrency(content, baseName);
192
+ cases.push(...concurrencyCases);
193
+
194
+ return cases;
195
+ }
196
+
197
+ function getCategory(patternName: string): EdgeCase['category'] {
198
+ if (patternName === 'functions') return 'timeout';
199
+ if (patternName === 'numbers') return 'boundary';
200
+ return 'input';
201
+ }
202
+
203
+ function getSeverity(patternName: string, testCase: { input: string }): EdgeCase['severity'] {
204
+ if (patternName === 'numbers') {
205
+ if (['0', '-1', 'NaN', 'Infinity', '-Infinity'].includes(testCase.input)) {
206
+ return 'high';
207
+ }
208
+ }
209
+ if (testCase.input === 'null' || testCase.input === 'undefined') {
210
+ return 'high';
211
+ }
212
+ return 'medium';
213
+ }
214
+
215
+ function generateTestCode(baseName: string, testCase: { input: string; description: string }): string {
216
+ return `// Test for ${testCase.description}
217
+ it('handles ${testCase.description}', () => {
218
+ // TODO: Implement edge case test
219
+ expect(true).toBe(true);
220
+ });`;
221
+ }
222
+
223
+ function analyzeErrorHandling(content: string, baseName: string): EdgeCase[] {
224
+ const cases: EdgeCase[] = [];
225
+
226
+ // Find throw statements
227
+ const throwMatches = content.matchAll(/throw\s+new\s+Error\s*\(\s*['"]([^'"]+)/g);
228
+ for (const match of throwMatches) {
229
+ cases.push({
230
+ category: 'error',
231
+ description: `error case: ${match[1]}`,
232
+ testName: `throws error: ${match[1]}`,
233
+ code: `it('throws error: ${match[1]}', () => { expect(() => subject()).toThrow(); });`,
234
+ severity: 'critical'
235
+ });
236
+ }
237
+
238
+ // Find if (error) patterns
239
+ if (content.includes('catch') || content.includes('if (err')) {
240
+ cases.push({
241
+ category: 'error',
242
+ description: 'error in catch block',
243
+ testName: 'handles catch block',
244
+ code: `it('handles catch block', () => { /* test error handling */ });`,
245
+ severity: 'high'
246
+ });
247
+ }
248
+
249
+ return cases;
250
+ }
251
+
252
+ function analyzeConcurrency(content: string, baseName: string): EdgeCase[] {
253
+ const cases: EdgeCase[] = [];
254
+
255
+ // Check for async/await patterns
256
+ if (content.includes('async') && content.includes('await')) {
257
+ cases.push({
258
+ category: 'concurrency',
259
+ description: 'concurrent async calls',
260
+ testName: 'handles concurrent async calls',
261
+ code: `it('handles concurrent async calls', async () => {
262
+ await Promise.all([
263
+ subject(),
264
+ subject(),
265
+ subject()
266
+ ]);
267
+ });`,
268
+ severity: 'high'
269
+ });
270
+ }
271
+
272
+ // Check for shared state
273
+ if (content.match(/\bthis\.\w+\s*=/g)?.length > 3) {
274
+ cases.push({
275
+ category: 'concurrency',
276
+ description: 'shared state mutation',
277
+ testName: 'handles shared state safely',
278
+ code: `it('handles shared state safely', async () => {
279
+ // Run multiple times to check for race conditions
280
+ await Promise.all([subject(), subject(), subject()]);
281
+ });`,
282
+ severity: 'medium'
283
+ });
284
+ }
285
+
286
+ return cases;
287
+ }
288
+
289
+ function identifyCriticalPaths(edgeCases: EdgeCase[]): string[] {
290
+ const critical = edgeCases
291
+ .filter(e => e.severity === 'critical')
292
+ .map(e => e.testName);
293
+
294
+ return [...new Set(critical)];
295
+ }
296
+
297
+ // Generate comprehensive edge case tests
298
+ function generateEdgeCaseTests(result: AnalysisResult): string {
299
+ const tests: string[] = [];
300
+
301
+ tests.push(`// Auto-generated edge case tests
302
+ // Total edge cases identified: ${result.edgeCases.length}
303
+ // Critical paths: ${result.criticalPaths.length}
304
+
305
+ describe('Edge Case Coverage', () => {`);
306
+
307
+ const byCategory = new Map<string, EdgeCase[]>();
308
+ for (const edge of result.edgeCases) {
309
+ if (!byCategory.has(edge.category)) {
310
+ byCategory.set(edge.category, []);
311
+ }
312
+ byCategory.get(edge.category)!.push(edge);
313
+ }
314
+
315
+ for (const [category, cases] of byCategory) {
316
+ tests.push(`\n describe('${category.toUpperCase()} cases', () => {`);
317
+
318
+ for (const edge of cases.slice(0, 10)) { // Limit per category
319
+ tests.push(` ${edge.code.replace('it(', "it('${category}: ").replace("() => {", "', () => {")}`);
320
+ }
321
+
322
+ tests.push(' });');
323
+ }
324
+
325
+ tests.push('});');
326
+
327
+ return tests.join('\n');
328
+ }
329
+
330
+ // Run agent if executed directly
331
+ if (require.main === module) {
332
+ const projectRoot = path.resolve(__dirname, '../..');
333
+ const result = analyzeEdgeCases(projectRoot);
334
+
335
+ console.log('\n========================================');
336
+ console.log('EDGE CASE AGENT - Analysis Report');
337
+ console.log('========================================\n');
338
+ console.log(`Total Edge Cases: ${result.edgeCases.length}`);
339
+ console.log(`Critical Paths: ${result.criticalPaths.length}`);
340
+ console.log(`Estimated Coverage: ${result.coverage.toFixed(1)}%\n`);
341
+
342
+ console.log('By Category:');
343
+ const byCategory = new Map<string, number>();
344
+ for (const edge of result.edgeCases) {
345
+ byCategory.set(edge.category, (byCategory.get(edge.category) || 0) + 1);
346
+ }
347
+ for (const [cat, count] of byCategory) {
348
+ console.log(` ${cat}: ${count}`);
349
+ }
350
+
351
+ console.log('\nCritical Paths:');
352
+ for (const path of result.criticalPaths.slice(0, 10)) {
353
+ console.log(` - ${path}`);
354
+ }
355
+
356
+ // Generate test code
357
+ const generated = generateEdgeCaseTests(result);
358
+ const outputPath = path.join(__dirname, '../2-edge-case-tests-generated.ts');
359
+ fs.writeFileSync(outputPath, generated);
360
+ console.log(`\nGenerated tests written to: ${outputPath}`);
361
+ }
362
+
363
+ export { analyzeEdgeCases, AnalysisResult, EdgeCase, generateEdgeCaseTests };