adaptive-memory-multi-model-router 1.9.0 → 1.9.2

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/dist/cli.js CHANGED
@@ -2,45 +2,233 @@
2
2
  /**
3
3
  * A3M Router CLI - Adaptive Memory Multi-Model Router
4
4
  *
5
- * Usage:
6
- * npx a3m-router route "Write a Python function"
7
- * npx a3m-router status
8
- * npx a3m-router memory add "text"
9
- * npx a3m-router cost
5
+ * Commands:
6
+ * npx a3m-router route <query> Route query to best provider
7
+ * npx a3m-router batch <q1> <q2>.. Route multiple queries
8
+ * npx a3m-router providers List all configured providers
9
+ * npx a3m-router test Test all providers
10
+ * npx a3m-router compare <query> Compare providers side by side
11
+ * npx a3m-router benchmark Benchmark all providers
12
+ * npx a3m-router recommend <task> Get model recommendation
13
+ * npx a3m-router cost <text> Estimate token cost
14
+ * npx a3m-router token <text> Count tokens
15
+ * npx a3m-router models List known models
16
+ * npx a3m-router memory add/search/stats Memory operations
17
+ * npx a3m-router status Show router status
10
18
  */
11
19
 
12
- const { createA3MRouter, countTokens, estimateCost, MODEL_COSTS } = require("./index.js");
20
+ const { execSync } = require('child_process');
21
+ const {
22
+ createA3MRouter, routeQuery, routeBatch, recommendForTask,
23
+ countTokens, estimateCost, MODEL_COSTS, CostTracker, MemoryTree,
24
+ getAvailableProviders, providerConfig, registerProvider, loadProviders,
25
+ } = require('./index.js');
13
26
 
14
27
  const args = process.argv.slice(2);
15
28
  const command = args[0];
16
29
 
30
+ // ============================================================
31
+ // HELPER FUNCTIONS
32
+ // ============================================================
33
+
17
34
  function formatRoute(result) {
18
- console.log("\nšŸ”€ A3M Router — Route Result");
19
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
20
- console.log(" Primary: " + result.primary_model);
35
+ console.log('\nšŸ”€ A3M Router — Route Result');
36
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
37
+ console.log(' Primary: ' + result.primary_model);
21
38
  if (result.fallback_models) {
22
- console.log(" Fallbacks: " + result.fallback_models.join(", "));
39
+ console.log(' Fallbacks: ' + result.fallback_models.join(', '));
23
40
  }
24
41
  if (result.estimated_cost) {
25
- console.log(" Est. Cost: $" + result.estimated_cost.toFixed(6));
42
+ console.log(' Est. Cost: $' + result.estimated_cost.toFixed(6));
26
43
  }
27
- if (result.latency_tier) {
28
- console.log(" Latency: " + result.latency_tier);
44
+ if (result.provider_type) {
45
+ console.log(' Type: ' + result.provider_type);
29
46
  }
30
- if (result.reason) {
31
- console.log(" Reason: " + result.reason);
47
+ if (result.reasoning) {
48
+ console.log(' Reason: ' + result.reasoning);
32
49
  }
33
- console.log("");
50
+ console.log('');
34
51
  }
35
52
 
53
+ async function callProvider(providerId, model, prompt, maxTokens) {
54
+ providerId = providerId || 'groq';
55
+ model = model || 'llama-3.3-70b-versatile';
56
+ maxTokens = maxTokens || 50;
57
+
58
+ const providers = providerConfig.getAvailableProviders();
59
+ const provider = providers[providerId];
60
+
61
+ if (!provider) {
62
+ console.error(' āŒ Provider "' + providerId + '" not found or not configured.');
63
+ console.error(' Run: npx a3m-router providers');
64
+ return null;
65
+ }
66
+
67
+ const startTime = Date.now();
68
+
69
+ if (provider.type === 'cli') {
70
+ try {
71
+ if (providerId === 'commandcode') {
72
+ const raw = execSync('commandcode -p "' + prompt.replace(/"/g, '\\"') + '" --skip-onboarding 2>&1', { timeout: 60000, encoding: 'utf-8' });
73
+ const content = raw.replace(/\x1b\[[0-9;]*m/g, '').trim();
74
+ return { content: content.substring(0, 200), totalTokens: Math.ceil(content.length / 4), cost: 0, latency: Date.now() - startTime };
75
+ } else {
76
+ const raw = execSync(provider.cliCommand + ' run "' + prompt.replace(/"/g, '\\"') + '" 2>&1', { timeout: 60000, encoding: 'utf-8' });
77
+ const lines = raw.replace(/\x1b\[[0-9;]*m/g, '').split('\n').filter(l => l.trim() && !l.startsWith('>') && !l.includes('build'));
78
+ const content = lines.join(' ').trim();
79
+ return { content: content.substring(0, 200), totalTokens: Math.ceil(content.length / 4), cost: 0, latency: Date.now() - startTime };
80
+ }
81
+ } catch (e) {
82
+ console.error(' āŒ ' + provider.name + ' error: ' + e.message.substring(0, 80));
83
+ return null;
84
+ }
85
+ }
86
+
87
+ // API provider
88
+ try {
89
+ const resp = await fetch(provider.baseUrl, {
90
+ method: 'POST',
91
+ headers: { 'Authorization': 'Bearer ' + provider.apiKey, 'Content-Type': 'application/json' },
92
+ body: JSON.stringify({ model, messages: [{ role: 'user', content: prompt }], max_tokens: maxTokens }),
93
+ });
94
+ const data = await resp.json();
95
+ const latency = Date.now() - startTime;
96
+ if (data.error) {
97
+ console.error(' āŒ ' + provider.name + ' error: ' + data.error.message.substring(0, 80));
98
+ return null;
99
+ }
100
+ const tokens = data.usage || {};
101
+ const cost = (tokens.prompt_tokens || 0) / 1000 * provider.costPerK.input + (tokens.completion_tokens || 0) / 1000 * provider.costPerK.output;
102
+ return { content: data.choices[0].message.content.trim(), totalTokens: tokens.total_tokens || 0, cost, latency, model: data.model || model };
103
+ } catch (e) {
104
+ console.error(' āŒ ' + provider.name + ' error: ' + e.message.substring(0, 80));
105
+ return null;
106
+ }
107
+ }
108
+
109
+ // ============================================================
110
+ // COMMANDS
111
+ // ============================================================
112
+
36
113
  async function main() {
37
114
  const router = createA3MRouter({ memory: { maxSize: 1000 } });
38
115
 
39
116
  switch (command) {
40
- case "route": {
41
- const query = args.slice(1).join(" ");
117
+ case 'providers': {
118
+ const providers = providerConfig.getAvailableProviders();
119
+ const allProviders = providerConfig._providers;
120
+
121
+ console.log('\nšŸ“” A3M Router — Provider Configuration');
122
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
123
+ console.log(' Config: ~/.config/a3m-router/providers.json');
124
+ console.log(' Add your own: npx a3m-router register <id> <config>');
125
+ console.log('');
126
+ console.log(' Provider Type Models Priority Key');
127
+ console.log(' ───────────────────── ─────── ────── ──────── ─────────');
128
+
129
+ for (const [id, provider] of Object.entries(allProviders)) {
130
+ const available = providers[id];
131
+ const status = available ? 'āœ…' : 'āŒ';
132
+ const keyStatus = provider.apiKey ? 'āœ…' : (provider.type === 'cli' ? 'N/A' : 'āŒ');
133
+ const modelCount = provider.models ? provider.models.length : 0;
134
+ console.log(' ' + status + ' ' + (provider.name || id).padEnd(20) + ' ' + (provider.type || 'api').padEnd(7) + ' ' + String(modelCount).padEnd(6) + ' ' + String(provider.priority).padEnd(9) + ' ' + keyStatus);
135
+ }
136
+ console.log('');
137
+ console.log(' Available: ' + Object.keys(providers).length + ' providers');
138
+ console.log(' Configured: ' + Object.keys(allProviders).length + ' providers');
139
+ console.log('');
140
+ break;
141
+ }
142
+
143
+ case 'test': {
144
+ const providers = providerConfig.getAvailableProviders();
145
+ console.log('\n🧪 A3M Router — Provider Health Check');
146
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
147
+
148
+ for (const [id, provider] of Object.entries(providers)) {
149
+ const model = provider.models[0];
150
+ console.log(' Testing ' + (provider.name || id) + ' (' + model + ')...');
151
+ const result = await callProvider(id, model, 'Say OK', 5);
152
+ if (result) {
153
+ console.log(' āœ… Response: "' + result.content.substring(0, 30) + '" (' + result.totalTokens + ' tok, ' + result.latency + 'ms, $' + result.cost.toFixed(6) + ')');
154
+ }
155
+ console.log('');
156
+ }
157
+ break;
158
+ }
159
+
160
+ case 'compare': {
161
+ const query = args.slice(1).join(' ');
42
162
  if (!query) {
43
- console.error("Usage: npx a3m-router route \"your query here\"");
163
+ console.error('Usage: npx a3m-router compare "your query here"');
164
+ process.exit(1);
165
+ }
166
+
167
+ const providers = providerConfig.getAvailableProviders();
168
+ console.log('\nšŸ”„ A3M Router — Provider Comparison');
169
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
170
+ console.log(' Query: "' + query + '"');
171
+ console.log('');
172
+
173
+ const results = [];
174
+ for (const [id, provider] of Object.entries(providers)) {
175
+ const model = provider.models[0];
176
+ console.log(' Testing ' + (provider.name || id) + '...');
177
+ const result = await callProvider(id, model, query, 100);
178
+ if (result) {
179
+ results.push({ id: provider.name || id, model, ...result });
180
+ }
181
+ }
182
+
183
+ console.log('\n Comparison:');
184
+ console.log(' ──────────────────────────────────────────────────────────────');
185
+ console.log(' Provider'.padEnd(18) + 'Response'.padEnd(40) + 'Time'.padEnd(12) + 'Cost');
186
+ console.log(' ──────────────────────────────────────────────────────────────');
187
+ for (const r of results) {
188
+ console.log(' ' + r.id.padEnd(16) + r.content.substring(0, 38).padEnd(40) + (r.latency + 'ms').padEnd(12) + '$' + r.cost.toFixed(6));
189
+ }
190
+ console.log('');
191
+ break;
192
+ }
193
+
194
+ case 'benchmark': {
195
+ const queries = [
196
+ 'What is 2+2?',
197
+ 'Write a Python function to reverse a string.',
198
+ 'Translate "Hello" to French.',
199
+ 'Write a haiku about programming.',
200
+ 'What is SQL injection?',
201
+ ];
202
+
203
+ const providers = providerConfig.getAvailableProviders();
204
+ console.log('\nšŸ“Š A3M Router — Provider Benchmark');
205
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
206
+
207
+ for (const [id, provider] of Object.entries(providers)) {
208
+ const model = provider.models[0];
209
+ console.log(' ' + (provider.name || id).padEnd(15) + '(' + model + ')');
210
+
211
+ let totalTime = 0;
212
+ let totalCost = 0;
213
+
214
+ for (const q of queries) {
215
+ const r = await callProvider(id, model, q, 50);
216
+ if (r) {
217
+ totalTime += r.latency;
218
+ totalCost += r.cost;
219
+ }
220
+ }
221
+
222
+ console.log(' Total: ' + totalTime + 'ms, Cost: $' + totalCost.toFixed(6) + ', Avg: ' + (totalTime / queries.length).toFixed(0) + 'ms/query');
223
+ }
224
+ console.log('');
225
+ break;
226
+ }
227
+
228
+ case 'route': {
229
+ const query = args.slice(1).join(' ');
230
+ if (!query) {
231
+ console.error('Usage: npx a3m-router route "your query here"');
44
232
  process.exit(1);
45
233
  }
46
234
  const result = router.route(query);
@@ -48,152 +236,199 @@ async function main() {
48
236
  break;
49
237
  }
50
238
 
51
- case "batch": {
239
+ case 'batch': {
52
240
  const queries = args.slice(1);
53
241
  if (queries.length === 0) {
54
- console.error("Usage: npx a3m-router batch \"query1\" \"query2\" ...");
242
+ console.error('Usage: npx a3m-router batch "query1" "query2" ...');
55
243
  process.exit(1);
56
244
  }
57
245
  const results = router.routeBatch(queries);
58
- console.log("\nšŸ”€ A3M Router — Batch Results");
59
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
246
+ console.log('\nšŸ”€ A3M Router — Batch Results');
247
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
60
248
  results.forEach(function(r, i) {
61
- console.log(" " + (i + 1) + ". \"" + queries[i].substring(0, 40) + "...\" → " + r.primary_model);
249
+ console.log(' ' + (i + 1) + '. "' + queries[i].substring(0, 40) + '..." → ' + r.primary_model);
62
250
  });
63
- console.log("");
251
+ console.log('');
64
252
  break;
65
253
  }
66
254
 
67
- case "recommend": {
68
- const task = args.slice(1).join(" ");
255
+ case 'recommend': {
256
+ const task = args.slice(1).join(' ');
69
257
  if (!task) {
70
- console.error("Usage: npx a3m-router recommend \"coding\"");
258
+ console.error('Usage: npx a3m-router recommend "coding"');
71
259
  process.exit(1);
72
260
  }
73
261
  const rec = router.recommend(task);
74
- console.log("\nšŸŽÆ A3M Router — Recommendation");
75
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
262
+ console.log('\nšŸŽÆ A3M Router — Recommendation');
263
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
76
264
  console.log(JSON.stringify(rec, null, 2));
265
+ console.log('');
77
266
  break;
78
267
  }
79
268
 
80
- case "status": {
81
- console.log("\nšŸ“Š A3M Router — Status");
82
- console.log("━━━━━━━━━━━━━━━━━━━━━━");
83
- console.log(" Version: 1.7.3");
84
- console.log(" Exports: 66");
85
- console.log(" Providers: 14");
86
- console.log(" Integrations: 116");
87
- console.log(" Keywords: 139");
88
- console.log(" Subpaths: 11");
89
- console.log(" Memory: āœ… MemoryTree + AutoFetch + ObsidianVault");
90
- console.log(" Compression: āœ… Enhanced + ISON");
91
- console.log(" Auth: āœ… OAuth 2.0 + PKCE");
92
- console.log(" Cost: āœ… Tracking + Budgets");
93
- console.log(" Cache: āœ… Prefix + Response");
94
- console.log(" Routing: āœ… RouteLLM + Adaptive");
95
- console.log(" Models known: " + Object.keys(MODEL_COSTS).length);
96
- console.log("");
269
+ case 'status': {
270
+ const providers = providerConfig.getAvailableProviders();
271
+ console.log('\nšŸ“Š A3M Router — Status');
272
+ console.log('━━━━━━━━━━━━━━━━━━━━━━');
273
+ console.log(' Version: 1.9.0');
274
+ console.log(' Exports: 74');
275
+ console.log(' Providers: ' + Object.keys(providers).length + ' configured');
276
+ console.log(' Integrations: 116');
277
+ console.log(' Keywords: 139');
278
+ console.log(' Subpaths: 11');
279
+ console.log(' Memory: āœ… MemoryTree + AutoFetch + ObsidianVault');
280
+ console.log(' Compression: āœ… Enhanced + ISON');
281
+ console.log(' Auth: āœ… OAuth 2.0 + PKCE');
282
+ console.log(' Cost: āœ… Tracking + Budgets');
283
+ console.log(' Cache: āœ… Prefix + Response');
284
+ console.log(' Routing: āœ… RouteLLM + Adaptive');
285
+ console.log(' Models known: ' + Object.keys(providerConfig._providers).length);
286
+ console.log('');
287
+ console.log(' Available Providers:');
288
+ for (const [id, p] of Object.entries(providers)) {
289
+ console.log(' āœ… ' + (p.name || id).padEnd(15) + '(' + p.models.length + ' models, type: ' + p.type + ')');
290
+ }
291
+ console.log('');
97
292
  break;
98
293
  }
99
294
 
100
- case "cost": {
101
- const text = args.slice(1).join(" ") || "Hello world this is a test";
295
+ case 'cost': {
296
+ const text = args.slice(1).join(' ') || 'Hello world this is a test';
102
297
  const tokens = countTokens(text);
103
298
  var completionTokens = Math.ceil(tokens * 1.5);
104
- var gpt4oCost = estimateCost(tokens, completionTokens, "gpt-4o");
105
- var miniCost = estimateCost(tokens, completionTokens, "gpt-4o-mini");
106
- var haikuCost = estimateCost(tokens, completionTokens, "claude-3-haiku");
107
- var geminiCost = estimateCost(tokens, completionTokens, "gemini-2.0-flash");
108
- console.log("\nšŸ’° A3M Router — Cost Estimate");
109
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
110
- console.log(" Text: \"" + text.substring(0, 50) + "\"");
111
- console.log(" Tokens: " + tokens);
112
- console.log(" GPT-4o: $" + gpt4oCost.toFixed(6));
113
- console.log(" GPT-4o-mini: $" + miniCost.toFixed(6));
114
- console.log(" Claude Haiku: $" + haikuCost.toFixed(6));
115
- console.log(" Gemini Flash: $" + geminiCost.toFixed(6));
299
+ var gpt4oCost = estimateCost(tokens, completionTokens, 'gpt-4o');
300
+ var miniCost = estimateCost(tokens, completionTokens, 'gpt-4o-mini');
301
+ var haikuCost = estimateCost(tokens, completionTokens, 'claude-3-haiku');
302
+ var geminiCost = estimateCost(tokens, completionTokens, 'gemini-2.0-flash');
303
+ console.log('\nšŸ’° A3M Router — Cost Estimate');
304
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
305
+ console.log(' Text: "' + text.substring(0, 50) + '"');
306
+ console.log(' Tokens: ' + tokens);
307
+ console.log(' GPT-4o: $' + gpt4oCost.toFixed(6));
308
+ console.log(' GPT-4o-mini: $' + miniCost.toFixed(6));
309
+ console.log(' Claude Haiku: $' + haikuCost.toFixed(6));
310
+ console.log(' Gemini Flash: $' + geminiCost.toFixed(6));
116
311
  if (gpt4oCost > 0) {
117
312
  var savings = ((1 - miniCost / gpt4oCost) * 100).toFixed(1);
118
- console.log(" Savings: " + savings + "% (mini vs GPT-4o)");
313
+ console.log(' Savings: ' + savings + '% (mini vs GPT-4o)');
119
314
  }
120
- console.log("");
315
+ console.log('');
121
316
  break;
122
317
  }
123
318
 
124
- case "models": {
125
- console.log("\nšŸ“‹ A3M Router — Known Models");
126
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
127
- var models = Object.entries(MODEL_COSTS);
128
- models.forEach(function(entry) {
129
- var name = entry[0];
130
- var cost = entry[1];
131
- console.log(" " + name.padEnd(25) + " in:$" + String(cost.input_per_1k).padEnd(6) + " out:$" + cost.output_per_1k);
132
- });
133
- console.log(" Total: " + models.length + " models");
134
- console.log("");
319
+ case 'models': {
320
+ const allProviders = providerConfig._providers;
321
+ console.log('\nšŸ“‹ A3M Router — All Known Models');
322
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
323
+
324
+ for (const [id, provider] of Object.entries(allProviders)) {
325
+ if (!provider.models || provider.models.length === 0) continue;
326
+ console.log(' ' + (provider.name || id).padEnd(15) + '(Priority: ' + provider.priority + ', Type: ' + provider.type + ')');
327
+ for (const m of provider.models) {
328
+ const cost = provider.costPerK;
329
+ console.log(' ' + m.padEnd(40) + 'in:$' + (cost ? cost.input : 0) + ' out:$' + (cost ? cost.output : 0));
330
+ }
331
+ console.log('');
332
+ }
135
333
  break;
136
334
  }
137
335
 
138
- case "token": {
139
- const text = args.slice(1).join(" ");
336
+ case 'token': {
337
+ const text = args.slice(1).join(' ');
140
338
  if (!text) {
141
- console.error("Usage: npx a3m-router token \"your text here\"");
339
+ console.error('Usage: npx a3m-router token "your text here"');
142
340
  process.exit(1);
143
341
  }
144
342
  const tokens = countTokens(text);
145
- console.log(" \"" + text + "\" → " + tokens + " tokens");
343
+ console.log(' "' + text + '" → ' + tokens + ' tokens');
344
+ break;
345
+ }
346
+
347
+ case 'register': {
348
+ const id = args[1];
349
+ const config = JSON.parse(args.slice(2).join(' '));
350
+ registerProvider(id, config);
351
+ providerConfig.saveConfig();
352
+ console.log('āœ… Registered provider: ' + id);
353
+ console.log(' Config saved to: ~/.config/a3m-router/providers.json');
146
354
  break;
147
355
  }
148
356
 
149
- case "memory": {
357
+ case 'memory': {
150
358
  const subcmd = args[1];
151
- if (subcmd === "add") {
152
- const text = args.slice(2).join(" ");
359
+ if (subcmd === 'add') {
360
+ const text = args.slice(2).join(' ');
153
361
  router.memory.add(text, { metadata: { cli: true } });
154
- console.log(" āœ… Added to memory: \"" + text.substring(0, 50) + "\"");
155
- } else if (subcmd === "search") {
156
- const query = args.slice(2).join(" ");
362
+ console.log(' āœ… Added to memory: "' + text.substring(0, 50) + '"');
363
+ } else if (subcmd === 'search') {
364
+ const query = args.slice(2).join(' ');
157
365
  const results = router.memory.search(query);
158
- console.log(" Found " + results.length + " results for \"" + query + "\"");
366
+ console.log(' Found ' + results.length + ' results for "' + query + '"');
159
367
  results.forEach(function(r, i) {
160
368
  var content = r.content ? r.content.substring(0, 60) : JSON.stringify(r).substring(0, 60);
161
- console.log(" " + (i + 1) + ". " + content);
369
+ console.log(' ' + (i + 1) + '. ' + content);
162
370
  });
163
371
  } else {
164
372
  const stats = router.memory.getStats();
165
- console.log("\n🧠 A3M Router — Memory Stats");
166
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
373
+ console.log('\n🧠 A3M Router — Memory Stats');
374
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
167
375
  console.log(JSON.stringify(stats, null, 2));
168
376
  }
169
377
  break;
170
378
  }
171
379
 
380
+ case 'health': {
381
+ console.log('\nšŸ„ A3M Router — Provider Health Check');
382
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
383
+
384
+ const providers = providerConfig.getAvailableProviders();
385
+ for (const [id, provider] of Object.entries(providers)) {
386
+ try {
387
+ const health = await providerConfig.healthCheck(id);
388
+ console.log(' ' + (health.healthy ? 'āœ…' : 'āŒ') + ' ' + (provider.name || id).padEnd(15) + health.healthy ? 'Healthy' : health.error);
389
+ } catch (e) {
390
+ console.log(' āŒ ' + (provider.name || id).padEnd(15) + e.message.substring(0, 60));
391
+ }
392
+ }
393
+ console.log('');
394
+ break;
395
+ }
396
+
172
397
  default:
173
- console.log("\nšŸ”€ A3M Router — Adaptive Memory Multi-Model Router");
174
- console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
175
- console.log("");
176
- console.log(" Commands:");
177
- console.log(" route <query> Route query to best model");
178
- console.log(" batch <q1> <q2>.. Route multiple queries");
179
- console.log(" recommend <task> Get model recommendation");
180
- console.log(" cost [text] Estimate token cost across models");
181
- console.log(" models List known models + pricing");
182
- console.log(" token <text> Count tokens");
183
- console.log(" memory add <text> Add to memory tree");
184
- console.log(" memory search <q> Search memory");
185
- console.log(" memory Show memory stats");
186
- console.log(" status Show router status");
187
- console.log("");
188
- console.log(" Examples:");
189
- console.log(" npx a3m-router route \"Write a Python function to sort\"");
190
- console.log(" npx a3m-router cost \"Hello world\"");
191
- console.log(" npx a3m-router memory add \"Meeting notes from standup\"");
192
- console.log("");
398
+ console.log('\nšŸ”€ A3M Router — Adaptive Memory Multi-Model Router');
399
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
400
+ console.log('');
401
+ console.log(' Commands:');
402
+ console.log(' route <query> Route query to best provider');
403
+ console.log(' batch <q1> <q2>.. Route multiple queries');
404
+ console.log(' compare <query> Compare providers side by side');
405
+ console.log(' benchmark Benchmark all providers');
406
+ console.log(' recommend <task> Get model recommendation');
407
+ console.log(' cost [text] Estimate token cost across models');
408
+ console.log(' models List all known models + pricing');
409
+ console.log(' providers List configured providers');
410
+ console.log(' test Test all provider connectivity');
411
+ console.log(' health Quick health check for all providers');
412
+ console.log(' token <text> Count tokens');
413
+ console.log(' memory add <text> Add to memory tree');
414
+ console.log(' memory search <q> Search memory');
415
+ console.log(' memory Show memory stats');
416
+ console.log(' register <id> <cfg> Register new provider');
417
+ console.log(' status Show router status');
418
+ console.log('');
419
+ console.log(' Config: ~/.config/a3m-router/providers.json');
420
+ console.log(' Env: GROQ_API_KEY, CEREBRAS_API_KEY, MISTRAL_API_KEY, etc.');
421
+ console.log('');
422
+ console.log(' Examples:');
423
+ console.log(' npx a3m-router route "Write a Python function to sort"');
424
+ console.log(' npx a3m-router compare "What is 2+2?"');
425
+ console.log(' npx a3m-router providers');
426
+ console.log(' npx a3m-router test');
427
+ console.log('');
193
428
  }
194
429
  }
195
430
 
196
431
  main().catch(function(err) {
197
- console.error("Error:", err.message);
432
+ console.error('Error:', err.message);
198
433
  process.exit(1);
199
434
  });
package/dist/index.js CHANGED
@@ -34,6 +34,15 @@ const costTracker_1 = require("./cost/costTracker");
34
34
  Object.defineProperty(exports, "CostTracker", { enumerable: true, get: function () { return costTracker_1.CostTracker; } });
35
35
  const registry_1 = require("./providers/registry");
36
36
  Object.defineProperty(exports, "ProviderRegistry", { enumerable: true, get: function () { return registry_1.ProviderRegistry; } });
37
+ const providerConfig_1 = require("./providers/providerConfig");
38
+ Object.defineProperty(exports, "loadProviders", { enumerable: true, get: function () { return providerConfig_1.loadProviders; } });
39
+ Object.defineProperty(exports, "getAvailableProviders", { enumerable: true, get: function () { return providerConfig_1.getAvailableProviders; } });
40
+ Object.defineProperty(exports, "healthCheckProvider", { enumerable: true, get: function () { return providerConfig_1.healthCheck; } });
41
+ Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return providerConfig_1.registerProvider; } });
42
+ Object.defineProperty(exports, "deregisterProvider", { enumerable: true, get: function () { return providerConfig_1.deregisterProvider; } });
43
+ Object.defineProperty(exports, "findCheapestAvailableProvider", { enumerable: true, get: function () { return providerConfig_1.findCheapestAvailableProvider; } });
44
+ Object.defineProperty(exports, "findFastestAvailableProvider", { enumerable: true, get: function () { return providerConfig_1.findFastestAvailableProvider; } });
45
+ Object.defineProperty(exports, "DEFAULT_PROVIDERS", { enumerable: true, get: function () { return providerConfig_1.DEFAULT_PROVIDERS; } });
37
46
  const reliability_1 = require("./utils/reliability");
38
47
  Object.defineProperty(exports, "CircuitBreaker", { enumerable: true, get: function () { return reliability_1.CircuitBreaker; } });
39
48
  Object.defineProperty(exports, "withRetry", { enumerable: true, get: function () { return reliability_1.withRetry; } });
@@ -330,3 +339,8 @@ function createA3MRouter(config = {}) {
330
339
  };
331
340
  }
332
341
  exports.createA3MRouter = createA3MRouter;
342
+
343
+ // Provider Configuration (generic, user-configurable) - additional exports
344
+ const providerConfig = require("./providers/providerConfig");
345
+ Object.defineProperty(exports, "providerConfig", { enumerable: true, get: function () { return providerConfig; } });
346
+ Object.defineProperty(exports, "saveProviderConfig", { enumerable: true, get: function () { return providerConfig.saveConfig; } });