adaptive-memory-multi-model-router 2.2.6 → 2.2.8

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 (51) hide show
  1. package/README.md +146 -105
  2. package/assets/benchmark-results.png +0 -0
  3. package/assets/complexity-scoring-v2.png +0 -0
  4. package/assets/complexity-scoring.png +0 -0
  5. package/assets/cost-comparison-chart.png +0 -0
  6. package/assets/cost-comparison-v2.png +0 -0
  7. package/assets/feature-comparison-v2.png +0 -0
  8. package/assets/feature-comparison-v3.png +0 -0
  9. package/assets/provider-health-chart.png +0 -0
  10. package/assets/provider-health-v2.png +0 -0
  11. package/assets/routing-flow-v2.png +0 -0
  12. package/assets/routing-flow-v3.png +0 -0
  13. package/assets/routing-flow.png +0 -0
  14. package/assets/tier-distribution.png +0 -0
  15. package/benchmark-results.json +620 -46
  16. package/dist/analytics/costAnalytics.d.ts +0 -1
  17. package/dist/cache/semanticCache.d.ts +0 -41
  18. package/dist/cache/semanticCache.d.ts.map +1 -1
  19. package/dist/cache/semanticCache.js +0 -142
  20. package/dist/cache/semanticCache.js.map +1 -1
  21. package/dist/cli.js +478 -35
  22. package/dist/cost/costTracker.js +3 -0
  23. package/dist/index.d.ts +0 -16
  24. package/dist/index.js +64 -264
  25. package/dist/integrations/langchainAdapter.d.ts +0 -1
  26. package/dist/integrations/oauth.d.ts +0 -1
  27. package/dist/memory/autoFetch.d.ts +0 -1
  28. package/dist/memory/memoryTree.d.ts +0 -1
  29. package/dist/memory/obsidianVault.d.ts +0 -1
  30. package/dist/providers/providerConfig.d.ts +0 -1
  31. package/dist/providers/providerConfig.js +0 -2
  32. package/dist/providers/registry.js +128 -126
  33. package/dist/routing/advancedRouter.js +427 -310
  34. package/dist/sdk.js +100 -109
  35. package/dist/security/guardrails.d.ts +0 -1
  36. package/dist/server/dashboard.d.ts +0 -1
  37. package/dist/server/modelMapper.d.ts +0 -1
  38. package/dist/server/proxyServer.d.ts +0 -1
  39. package/package.json +96 -389
  40. package/scripts/run-mmlu-benchmark.js +176 -0
  41. package/scripts/run-provider-benchmark.js +244 -0
  42. package/src/cache/semanticCache.ts +0 -148
  43. package/src/index.ts +99 -0
  44. package/test/provider-test.js +70 -91
  45. package/test.js +41 -67
  46. package/tsconfig.json +5 -15
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/index.js.map +0 -1
  49. package/dist/sdk.d.ts.map +0 -1
  50. package/dist/sdk.js.map +0 -1
  51. package/test.js.bak +0 -376
package/dist/cli.js CHANGED
@@ -1,59 +1,502 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * TMLPD PI CLI
3
+ * A3M Router CLI - Adaptive Memory Multi-Model Router
4
+ *
5
+ * Commands:
6
+ * npx a3m-router serve [--port 8787] Start OpenAI-compatible proxy server
7
+ * npx a3m-router route <query> Route query to best provider
8
+ * npx a3m-router batch <q1> <q2>.. Route multiple queries
9
+ * npx a3m-router providers List all configured providers
10
+ * npx a3m-router test Test all providers
11
+ * npx a3m-router compare <query> Compare providers side by side
12
+ * npx a3m-router benchmark Benchmark all providers
13
+ * npx a3m-router recommend <task> Get model recommendation
14
+ * npx a3m-router cost <text> Estimate token cost
15
+ * npx a3m-router token <text> Count tokens
16
+ * npx a3m-router models List known models
17
+ * npx a3m-router memory add/search/stats Memory operations
18
+ * npx a3m-router status Show router status
4
19
  */
5
20
 
6
- const { createTMLPD } = require("./dist/index.js");
21
+ const { execSync } = require('child_process');
22
+ const {
23
+ createA3MRouter, routeQuery, routeBatch, recommendForTask,
24
+ countTokens, estimateCost, MODEL_COSTS, CostTracker, MemoryTree,
25
+ getAvailableProviders, providerConfig, registerProvider, loadProviders,
26
+ } = require('./index.js');
27
+
28
+ let createProxyServer;
29
+ try {
30
+ createProxyServer = require('./server/proxyServer.js').createProxyServer;
31
+ } catch (e) {
32
+ // Server module not yet compiled
33
+ }
7
34
 
8
35
  const args = process.argv.slice(2);
9
36
  const command = args[0];
10
37
 
38
+ // ============================================================
39
+ // HELPER FUNCTIONS
40
+ // ============================================================
41
+
42
+ function formatRoute(result) {
43
+ console.log('\nšŸ”€ A3M Router — Route Result');
44
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
45
+ console.log(' Primary: ' + result.primary_model);
46
+ if (result.fallback_models) {
47
+ console.log(' Fallbacks: ' + result.fallback_models.join(', '));
48
+ }
49
+ if (result.estimated_cost) {
50
+ console.log(' Est. Cost: $' + result.estimated_cost.toFixed(6));
51
+ }
52
+ if (result.provider_type) {
53
+ console.log(' Type: ' + result.provider_type);
54
+ }
55
+ if (result.reasoning) {
56
+ console.log(' Reason: ' + result.reasoning);
57
+ showStarPrompt();
58
+ }
59
+ console.log('');
60
+ }
61
+
62
+
63
+ // ============================================================
64
+ // STAR PROMPT (shown once per user)
65
+ // ============================================================
66
+ function showStarPrompt() {
67
+ const fs = require('fs');
68
+ const path = require('path');
69
+ const home = process.env.HOME || process.env.USERPROFILE || '/tmp';
70
+ const marker = path.join(home, '.a3m-router', '.star-prompt-shown');
71
+
72
+ try {
73
+ // Only show once
74
+ if (fs.existsSync(marker)) return;
75
+
76
+ // Create directory if needed
77
+ const dir = path.dirname(marker);
78
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
79
+
80
+ console.log('');
81
+ console.log(' \x1b[2m── ────────────────────────────────────────\x1b[0m');
82
+ console.log(' \x1b[2m⭐ Found this useful? Star us on GitHub:\x1b[0m');
83
+ console.log(' \x1b[1m\x1b[36m https://github.com/Das-rebel/adaptive-memory-multi-model-router\x1b[0m');
84
+ console.log(' \x1b[2m── ────────────────────────────────────────\x1b[0m');
85
+ console.log('');
86
+
87
+ // Mark as shown
88
+ fs.writeFileSync(marker, new Date().toISOString());
89
+ } catch (e) {
90
+ // Silently fail - don't break CLI for this
91
+ }
92
+ }
93
+
94
+ async function callProvider(providerId, model, prompt, maxTokens) {
95
+ providerId = providerId || 'groq';
96
+ model = model || 'llama-3.3-70b-versatile';
97
+ maxTokens = maxTokens || 50;
98
+
99
+ const providers = providerConfig.getAvailableProviders();
100
+ const provider = providers[providerId];
101
+
102
+ if (!provider) {
103
+ console.error(' āŒ Provider "' + providerId + '" not found or not configured.');
104
+ console.error(' Run: npx a3m-router providers');
105
+ return null;
106
+ }
107
+
108
+ const startTime = Date.now();
109
+
110
+ if (provider.type === 'cli') {
111
+ try {
112
+ if (providerId === 'commandcode') {
113
+ const raw = execSync('commandcode -p "' + prompt.replace(/"/g, '\\"') + '" --skip-onboarding 2>&1', { timeout: 60000, encoding: 'utf-8' });
114
+ const content = raw.replace(/\x1b\[[0-9;]*m/g, '').trim();
115
+ return { content: content.substring(0, 200), totalTokens: Math.ceil(content.length / 4), cost: 0, latency: Date.now() - startTime };
116
+ } else {
117
+ const raw = execSync(provider.cliCommand + ' run "' + prompt.replace(/"/g, '\\"') + '" 2>&1', { timeout: 60000, encoding: 'utf-8' });
118
+ const lines = raw.replace(/\x1b\[[0-9;]*m/g, '').split('\n').filter(l => l.trim() && !l.startsWith('>') && !l.includes('build'));
119
+ const content = lines.join(' ').trim();
120
+ return { content: content.substring(0, 200), totalTokens: Math.ceil(content.length / 4), cost: 0, latency: Date.now() - startTime };
121
+ }
122
+ } catch (e) {
123
+ console.error(' āŒ ' + provider.name + ' error: ' + e.message.substring(0, 80));
124
+ return null;
125
+ }
126
+ }
127
+
128
+ // API provider
129
+ try {
130
+ const resp = await fetch(provider.baseUrl, {
131
+ method: 'POST',
132
+ headers: { 'Authorization': 'Bearer ' + provider.apiKey, 'Content-Type': 'application/json' },
133
+ body: JSON.stringify({ model, messages: [{ role: 'user', content: prompt }], max_tokens: maxTokens }),
134
+ });
135
+ const data = await resp.json();
136
+ const latency = Date.now() - startTime;
137
+ if (data.error) {
138
+ console.error(' āŒ ' + provider.name + ' error: ' + data.error.message.substring(0, 80));
139
+ return null;
140
+ }
141
+ const tokens = data.usage || {};
142
+ const cost = (tokens.prompt_tokens || 0) / 1000 * provider.costPerK.input + (tokens.completion_tokens || 0) / 1000 * provider.costPerK.output;
143
+ return { content: data.choices[0].message.content.trim(), totalTokens: tokens.total_tokens || 0, cost, latency, model: data.model || model };
144
+ } catch (e) {
145
+ console.error(' āŒ ' + provider.name + ' error: ' + e.message.substring(0, 80));
146
+ return null;
147
+ }
148
+ }
149
+
150
+ // ============================================================
151
+ // COMMANDS
152
+ // ============================================================
153
+
11
154
  async function main() {
155
+ const router = createA3MRouter({ memory: { maxSize: 1000 } });
156
+
12
157
  switch (command) {
13
- case "execute": {
14
- const tmlpd = createTMLPD();
15
- const prompt = args.slice(1).join(" ");
16
- const result = await tmlpd.execute(prompt);
17
- console.log(JSON.stringify(result, null, 2));
158
+ case 'providers': {
159
+ const providers = providerConfig.getAvailableProviders();
160
+ const allProviders = providerConfig._providers;
161
+
162
+ console.log('\nšŸ“” A3M Router — Provider Configuration');
163
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
164
+ console.log(' Config: ~/.config/a3m-router/providers.json');
165
+ console.log(' Add your own: npx a3m-router register <id> <config>');
166
+ console.log('');
167
+ console.log(' Provider Type Models Priority Key');
168
+ console.log(' ───────────────────── ─────── ────── ──────── ─────────');
169
+
170
+ for (const [id, provider] of Object.entries(allProviders)) {
171
+ const available = providers[id];
172
+ const status = available ? 'āœ…' : 'āŒ';
173
+ const keyStatus = provider.apiKey ? 'āœ…' : (provider.type === 'cli' ? 'N/A' : 'āŒ');
174
+ const modelCount = provider.models ? provider.models.length : 0;
175
+ console.log(' ' + status + ' ' + (provider.name || id).padEnd(20) + ' ' + (provider.type || 'api').padEnd(7) + ' ' + String(modelCount).padEnd(6) + ' ' + String(provider.priority).padEnd(9) + ' ' + keyStatus);
176
+ }
177
+ console.log('');
178
+ console.log(' Available: ' + Object.keys(providers).length + ' providers');
179
+ console.log(' Configured: ' + Object.keys(allProviders).length + ' providers');
180
+ console.log('');
18
181
  break;
19
182
  }
20
- case "parallel": {
21
- const tmlpd = createTMLPD();
22
- const models = args.slice(1).join(" ").split(",").map(m => m.trim());
23
- const prompt = "Compare these models";
24
- const result = await tmlpd.executeParallel(prompt, models);
25
- console.log(JSON.stringify(result, null, 2));
183
+
184
+ case 'test': {
185
+ const providers = providerConfig.getAvailableProviders();
186
+ console.log('\n🧪 A3M Router — Provider Health Check');
187
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
188
+
189
+ for (const [id, provider] of Object.entries(providers)) {
190
+ const model = provider.models[0];
191
+ console.log(' Testing ' + (provider.name || id) + ' (' + model + ')...');
192
+ const result = await callProvider(id, model, 'Say OK', 5);
193
+ if (result) {
194
+ console.log(' āœ… Response: "' + result.content.substring(0, 30) + '" (' + result.totalTokens + ' tok, ' + result.latency + 'ms, $' + result.cost.toFixed(6) + ')');
195
+ }
196
+ console.log('');
197
+ }
26
198
  break;
27
199
  }
28
- case "cost": {
29
- const tmlpd = createTMLPD();
30
- const summary = tmlpd.getCostSummary();
31
- console.log(JSON.stringify(summary, null, 2));
200
+
201
+ case 'compare': {
202
+ const query = args.slice(1).join(' ');
203
+ if (!query) {
204
+ console.error('Usage: npx a3m-router compare "your query here"');
205
+ process.exit(1);
206
+ }
207
+
208
+ const providers = providerConfig.getAvailableProviders();
209
+ console.log('\nšŸ”„ A3M Router — Provider Comparison');
210
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
211
+ console.log(' Query: "' + query + '"');
212
+ console.log('');
213
+
214
+ const results = [];
215
+ for (const [id, provider] of Object.entries(providers)) {
216
+ const model = provider.models[0];
217
+ console.log(' Testing ' + (provider.name || id) + '...');
218
+ const result = await callProvider(id, model, query, 100);
219
+ if (result) {
220
+ results.push({ id: provider.name || id, model, ...result });
221
+ }
222
+ }
223
+
224
+ console.log('\n Comparison:');
225
+ console.log(' ──────────────────────────────────────────────────────────────');
226
+ console.log(' Provider'.padEnd(18) + 'Response'.padEnd(40) + 'Time'.padEnd(12) + 'Cost');
227
+ console.log(' ──────────────────────────────────────────────────────────────');
228
+ for (const r of results) {
229
+ console.log(' ' + r.id.padEnd(16) + r.content.substring(0, 38).padEnd(40) + (r.latency + 'ms').padEnd(12) + '$' + r.cost.toFixed(6));
230
+ }
231
+ console.log('');
32
232
  break;
33
233
  }
34
- case "status": {
35
- const tmlpd = createTMLPD();
36
- const status = tmlpd.getProviderStatus();
37
- console.log(JSON.stringify(status, null, 2));
234
+
235
+ case 'benchmark': {
236
+ const queries = [
237
+ 'What is 2+2?',
238
+ 'Write a Python function to reverse a string.',
239
+ 'Translate "Hello" to French.',
240
+ 'Write a haiku about programming.',
241
+ 'What is SQL injection?',
242
+ ];
243
+
244
+ const providers = providerConfig.getAvailableProviders();
245
+ console.log('\nšŸ“Š A3M Router — Provider Benchmark');
246
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
247
+
248
+ for (const [id, provider] of Object.entries(providers)) {
249
+ const model = provider.models[0];
250
+ console.log(' ' + (provider.name || id).padEnd(15) + '(' + model + ')');
251
+
252
+ let totalTime = 0;
253
+ let totalCost = 0;
254
+
255
+ for (const q of queries) {
256
+ const r = await callProvider(id, model, q, 50);
257
+ if (r) {
258
+ totalTime += r.latency;
259
+ totalCost += r.cost;
260
+ }
261
+ }
262
+
263
+ console.log(' Total: ' + totalTime + 'ms, Cost: $' + totalCost.toFixed(6) + ', Avg: ' + (totalTime / queries.length).toFixed(0) + 'ms/query');
264
+ }
265
+ console.log('');
38
266
  break;
39
267
  }
40
- case "cache": {
41
- const tmlpd = createTMLPD();
42
- const stats = tmlpd.getCacheStats();
43
- console.log(JSON.stringify(stats, null, 2));
268
+
269
+ case 'route': {
270
+ const query = args.slice(1).join(' ');
271
+ if (!query) {
272
+ console.error('Usage: npx a3m-router route "your query here"');
273
+ process.exit(1);
274
+ }
275
+ const result = router.route(query);
276
+ formatRoute(result);
277
+ break;
278
+ }
279
+
280
+ case 'batch': {
281
+ const queries = args.slice(1);
282
+ if (queries.length === 0) {
283
+ console.error('Usage: npx a3m-router batch "query1" "query2" ...');
284
+ process.exit(1);
285
+ }
286
+ const results = router.routeBatch(queries);
287
+ console.log('\nšŸ”€ A3M Router — Batch Results');
288
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
289
+ results.forEach(function(r, i) {
290
+ console.log(' ' + (i + 1) + '. "' + queries[i].substring(0, 40) + '..." → ' + r.primary_model);
291
+ });
292
+ console.log('');
44
293
  break;
45
294
  }
46
- default:
47
- console.log(`TMLPD PI v1.0.0
48
295
 
49
- Usage:
50
- tmlpd-pi execute <prompt> Execute single prompt
51
- tmlpd-pi parallel <models> Execute in parallel
52
- tmlpd-pi cost Show cost summary
53
- tmlpd-pi status Show provider status
54
- tmlpd-pi cache Show cache stats
55
- `);
296
+ case 'recommend': {
297
+ const task = args.slice(1).join(' ');
298
+ if (!task) {
299
+ console.error('Usage: npx a3m-router recommend "coding"');
300
+ process.exit(1);
301
+ }
302
+ const rec = router.recommend(task);
303
+ console.log('\nšŸŽÆ A3M Router — Recommendation');
304
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
305
+ console.log(JSON.stringify(rec, null, 2));
306
+ console.log('');
307
+ break;
308
+ }
309
+
310
+ case 'status': {
311
+ const providers = providerConfig.getAvailableProviders();
312
+ console.log('\nšŸ“Š A3M Router — Status');
313
+ console.log('━━━━━━━━━━━━━━━━━━━━━━');
314
+ console.log(' Version: 1.9.0');
315
+ console.log(' Exports: 74');
316
+ console.log(' Providers: ' + Object.keys(providers).length + ' configured');
317
+ console.log(' Integrations: 116');
318
+ console.log(' Keywords: 139');
319
+ console.log(' Subpaths: 11');
320
+ console.log(' Memory: āœ… MemoryTree + AutoFetch + ObsidianVault');
321
+ console.log(' Compression: āœ… Enhanced + ISON');
322
+ console.log(' Auth: āœ… OAuth 2.0 + PKCE');
323
+ console.log(' Cost: āœ… Tracking + Budgets');
324
+ console.log(' Cache: āœ… Prefix + Response');
325
+ console.log(' Routing: āœ… RouteLLM + Adaptive');
326
+ console.log(' Models known: ' + Object.keys(providerConfig._providers).length);
327
+ console.log('');
328
+ console.log(' Available Providers:');
329
+ for (const [id, p] of Object.entries(providers)) {
330
+ console.log(' āœ… ' + (p.name || id).padEnd(15) + '(' + p.models.length + ' models, type: ' + p.type + ')');
331
+ }
332
+ console.log('');
333
+ break;
334
+ }
335
+
336
+ case 'cost': {
337
+ const text = args.slice(1).join(' ') || 'Hello world this is a test';
338
+ const tokens = countTokens(text);
339
+ var completionTokens = Math.ceil(tokens * 1.5);
340
+ var gpt4oCost = estimateCost(tokens, completionTokens, 'gpt-4o');
341
+ var miniCost = estimateCost(tokens, completionTokens, 'gpt-4o-mini');
342
+ var haikuCost = estimateCost(tokens, completionTokens, 'claude-3-haiku');
343
+ var geminiCost = estimateCost(tokens, completionTokens, 'gemini-2.0-flash');
344
+ console.log('\nšŸ’° A3M Router — Cost Estimate');
345
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
346
+ console.log(' Text: "' + text.substring(0, 50) + '"');
347
+ console.log(' Tokens: ' + tokens);
348
+ console.log(' GPT-4o: $' + gpt4oCost.toFixed(6));
349
+ console.log(' GPT-4o-mini: $' + miniCost.toFixed(6));
350
+ console.log(' Claude Haiku: $' + haikuCost.toFixed(6));
351
+ console.log(' Gemini Flash: $' + geminiCost.toFixed(6));
352
+ if (gpt4oCost > 0) {
353
+ var savings = ((1 - miniCost / gpt4oCost) * 100).toFixed(1);
354
+ console.log(' Savings: ' + savings + '% (mini vs GPT-4o)');
355
+ }
356
+ console.log('');
357
+ break;
358
+ }
359
+
360
+ case 'models': {
361
+ const allProviders = providerConfig._providers;
362
+ console.log('\nšŸ“‹ A3M Router — All Known Models');
363
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
364
+
365
+ for (const [id, provider] of Object.entries(allProviders)) {
366
+ if (!provider.models || provider.models.length === 0) continue;
367
+ console.log(' ' + (provider.name || id).padEnd(15) + '(Priority: ' + provider.priority + ', Type: ' + provider.type + ')');
368
+ for (const m of provider.models) {
369
+ const cost = provider.costPerK;
370
+ console.log(' ' + m.padEnd(40) + 'in:$' + (cost ? cost.input : 0) + ' out:$' + (cost ? cost.output : 0));
371
+ }
372
+ console.log('');
373
+ }
374
+ break;
375
+ }
376
+
377
+ case 'token': {
378
+ const text = args.slice(1).join(' ');
379
+ if (!text) {
380
+ console.error('Usage: npx a3m-router token "your text here"');
381
+ process.exit(1);
382
+ }
383
+ const tokens = countTokens(text);
384
+ console.log(' "' + text + '" → ' + tokens + ' tokens');
385
+ break;
386
+ }
387
+
388
+ case 'register': {
389
+ const id = args[1];
390
+ const config = JSON.parse(args.slice(2).join(' '));
391
+ registerProvider(id, config);
392
+ providerConfig.saveConfig();
393
+ console.log('āœ… Registered provider: ' + id);
394
+ console.log(' Config saved to: ~/.config/a3m-router/providers.json');
395
+ break;
396
+ }
397
+
398
+ case 'memory': {
399
+ const subcmd = args[1];
400
+ if (subcmd === 'add') {
401
+ const text = args.slice(2).join(' ');
402
+ router.memory.add(text, { metadata: { cli: true } });
403
+ console.log(' āœ… Added to memory: "' + text.substring(0, 50) + '"');
404
+ } else if (subcmd === 'search') {
405
+ const query = args.slice(2).join(' ');
406
+ const results = router.memory.search(query);
407
+ console.log(' Found ' + results.length + ' results for "' + query + '"');
408
+ results.forEach(function(r, i) {
409
+ var content = r.content ? r.content.substring(0, 60) : JSON.stringify(r).substring(0, 60);
410
+ console.log(' ' + (i + 1) + '. ' + content);
411
+ });
412
+ } else {
413
+ const stats = router.memory.getStats();
414
+ console.log('\n🧠 A3M Router — Memory Stats');
415
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
416
+ console.log(JSON.stringify(stats, null, 2));
417
+ }
418
+ break;
419
+ }
420
+
421
+ case 'health': {
422
+ console.log('\nšŸ„ A3M Router — Provider Health Check');
423
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
424
+
425
+ const providers = providerConfig.getAvailableProviders();
426
+ for (const [id, provider] of Object.entries(providers)) {
427
+ try {
428
+ const health = await providerConfig.healthCheck(id);
429
+ console.log(' ' + (health.healthy ? 'āœ…' : 'āŒ') + ' ' + (provider.name || id).padEnd(15) + health.healthy ? 'Healthy' : health.error);
430
+ } catch (e) {
431
+ console.log(' āŒ ' + (provider.name || id).padEnd(15) + e.message.substring(0, 60));
432
+ }
433
+ }
434
+ console.log('');
435
+ break;
436
+ }
437
+
438
+ case 'serve': {
439
+ if (!createProxyServer) {
440
+ console.error('\n Error: Server module not available.');
441
+ console.error(' Build first: npm run build');
442
+ console.error(' Or use directly: node -e "require(\'./server/proxyServer.js\').createProxyServer()"\n');
443
+ process.exit(1);
444
+ }
445
+
446
+ // Parse --port argument
447
+ var portArg = args.indexOf('--port');
448
+ var port = undefined;
449
+ if (portArg !== -1 && args[portArg + 1]) {
450
+ port = parseInt(args[portArg + 1], 10);
451
+ if (isNaN(port)) {
452
+ console.error(' Error: --port must be a number');
453
+ process.exit(1);
454
+ }
455
+ }
456
+
457
+ console.log('\n Starting A3M Router Proxy Server...');
458
+ createProxyServer(port);
459
+ break;
460
+ }
461
+
462
+ default:
463
+ console.log('\nšŸ”€ A3M Router — Adaptive Memory Multi-Model Router');
464
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
465
+ console.log('');
466
+ console.log(' Commands:');
467
+ console.log(' serve [--port 8787] Start OpenAI-compatible proxy server');
468
+ console.log(' route <query> Route query to best provider');
469
+ console.log(' batch <q1> <q2>.. Route multiple queries');
470
+ console.log(' compare <query> Compare providers side by side');
471
+ console.log(' benchmark Benchmark all providers');
472
+ console.log(' recommend <task> Get model recommendation');
473
+ console.log(' cost [text] Estimate token cost across models');
474
+ console.log(' models List all known models + pricing');
475
+ console.log(' providers List configured providers');
476
+ console.log(' test Test all provider connectivity');
477
+ console.log(' health Quick health check for all providers');
478
+ console.log(' token <text> Count tokens');
479
+ console.log(' memory add <text> Add to memory tree');
480
+ console.log(' memory search <q> Search memory');
481
+ console.log(' memory Show memory stats');
482
+ console.log(' register <id> <cfg> Register new provider');
483
+ console.log(' status Show router status');
484
+ console.log('');
485
+ console.log(' Config: ~/.config/a3m-router/providers.json');
486
+ console.log(' Env: GROQ_API_KEY, CEREBRAS_API_KEY, MISTRAL_API_KEY, etc.');
487
+ console.log('');
488
+ console.log(' Examples:');
489
+ console.log(' npx a3m-router serve # Start proxy on :8787');
490
+ console.log(' npx a3m-router serve --port 3000 # Start proxy on :3000');
491
+ console.log(' npx a3m-router route "Write a Python function to sort"');
492
+ console.log(' npx a3m-router compare "What is 2+2?"');
493
+ console.log(' npx a3m-router providers');
494
+ console.log(' npx a3m-router test');
495
+ console.log('');
56
496
  }
57
497
  }
58
498
 
59
- main().catch(console.error);
499
+ main().catch(function(err) {
500
+ console.error('Error:', err.message);
501
+ process.exit(1);
502
+ });
@@ -236,5 +236,8 @@ class CostTracker {
236
236
  return [...this.history];
237
237
  }
238
238
  }
239
+ // Alias for convenience
240
+ CostTracker.prototype.getStatus = CostTracker.prototype.getSummary;
241
+
239
242
  exports.CostTracker = CostTracker;
240
243
  //# sourceMappingURL=costTracker.js.map
package/dist/index.d.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  export { routeQuery, routeBatch, recommendForTask, extractQueryFeatures, MODEL_PROFILES, updateModelProfile, getProviderHealth, } from './routing/advancedRouter';
2
2
  export { DEFAULT_PROVIDERS, getAvailableProviders, registerProvider, deregisterProvider, updateProvider, healthCheck, checkAllProviders, findCheapestAvailableProvider, findFastestAvailableProvider, loadConfig, saveConfig, } from './providers/providerConfig';
3
- export { ProviderRegistry } from './providers/registry';
4
- export { providerConfig } from './providers/providerConfig';
5
- export { estimateCost } from './routing/advancedRouter';
6
3
  export type { ProviderTier, ProviderFormat, ProviderType, ProviderCost, ProviderDefinition, } from './providers/providerConfig';
7
4
  export { CostTracker } from './cost/costTracker';
8
5
  export { MemoryTree } from './memory/memoryTree';
@@ -29,19 +26,6 @@ export declare function createA3MRouter(options?: A3MRouterOptions): {
29
26
  healthCheck: typeof healthCheck;
30
27
  costTracker: any;
31
28
  memoryTree: MemoryTree;
32
- providers: any;
33
- cache: any;
34
- compression: {
35
- compress: (input: string) => any;
36
- decompress: (input: Buffer) => any;
37
- };
38
- vault: {
39
- store: (key: string, value: any) => Promise<void>;
40
- retrieve: (key: string) => Promise<null>;
41
- };
42
- autoFetch: boolean;
43
- oauth: boolean;
44
29
  options: A3MRouterOptions;
45
30
  };
46
31
  export default createA3MRouter;
47
- //# sourceMappingURL=index.d.ts.map