adaptive-memory-multi-model-router 2.13.4 → 2.13.6

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 (75) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  2. package/.well-known/ai-plugin.json +1 -1
  3. package/CONTRIBUTING.md +1 -1
  4. package/LAUNCH-PAIN-DRIVEN.md +3 -3
  5. package/LAUNCH.md +7 -7
  6. package/POPULARITY_BOOSTERS.md +6 -6
  7. package/README.md +40 -38
  8. package/README_ja.md +1 -1
  9. package/README_zh.md +1 -1
  10. package/SUBMISSIONS.md +2 -2
  11. package/articles/DEVTO_COST_GUIDE.md +2 -2
  12. package/articles/DEVTO_FINAL.md +6 -6
  13. package/articles/DEVTO_MULTI_PROVIDER.md +4 -4
  14. package/articles/DEVTO_V2_ANNOUNCEMENT.md +2 -2
  15. package/articles/DEVTO_VIRAL_GROWTH.md +5 -5
  16. package/articles/FRESH_devto.md +1 -1
  17. package/articles/FRESH_hackernews.md +1 -1
  18. package/articles/FRESH_reddit_ml.md +1 -1
  19. package/articles/FRESH_reddit_node.md +2 -2
  20. package/articles/FRESH_reddit_sideproject.md +2 -2
  21. package/articles/FRESH_reddit_webdev.md +2 -2
  22. package/articles/HN_10X_BETTER.md +2 -2
  23. package/articles/HN_CHINESE_STYLE.md +5 -5
  24. package/articles/HN_FINAL.md +1 -1
  25. package/articles/HN_POSTED_VERSION.md +1 -1
  26. package/articles/PAIN-DRIVEN-devto-v2.md +2 -2
  27. package/articles/PAIN-DRIVEN-devto-v3.md +2 -2
  28. package/articles/PAIN-DRIVEN-devto.md +2 -2
  29. package/articles/PAIN-DRIVEN-hackernews-v2.md +2 -2
  30. package/articles/PAIN-DRIVEN-hackernews-v3.md +3 -3
  31. package/articles/PAIN-DRIVEN-hackernews.md +2 -2
  32. package/articles/PAIN-DRIVEN-reddit-v2.md +2 -2
  33. package/articles/PAIN-DRIVEN-reddit-v3.md +2 -2
  34. package/articles/PAIN-DRIVEN-reddit.md +2 -2
  35. package/articles/PAIN-DRIVEN-twitter-v2.md +2 -2
  36. package/articles/PAIN-DRIVEN-twitter-v3.md +2 -2
  37. package/articles/PAIN-DRIVEN-twitter.md +2 -2
  38. package/articles/REDDIT_FINAL.md +2 -2
  39. package/articles/TWITTER_FINAL.md +1 -1
  40. package/articles/ai-discoverability-llm-routing.md +1 -1
  41. package/articles/devto-llm-routing.md +2 -2
  42. package/articles/hackernews-show-hn.md +1 -1
  43. package/articles/hashnode-llm-cost-optimization.md +1 -1
  44. package/articles/medium-building-llm-router.md +1 -1
  45. package/articles/reddit-ml.md +1 -1
  46. package/articles/twitter-thread-cost-savings.md +1 -1
  47. package/articles/youtube-tutorial-script.md +1 -1
  48. package/demo.html +1 -1
  49. package/dist/cli/setupWizard.js +1 -1
  50. package/dist/cli/setupWizard.js.map +1 -1
  51. package/dist/cli.js +1 -1
  52. package/dist/geo/generativeEngineOptimization.js +1 -1
  53. package/dist/tui/dashboard.d.ts +3 -9
  54. package/dist/tui/dashboard.js +170 -236
  55. package/dist/tui/dashboard.js.map +1 -1
  56. package/docs/HN_CHECKLIST.md +2 -2
  57. package/docs/HN_SUBMISSION_FINAL.md +2 -2
  58. package/docs/HN_SUBMISSION_V3.md +3 -3
  59. package/docs/SEO_AUDIT.md +1 -1
  60. package/docs/UPDATE_TOPICS.md +1 -1
  61. package/docs/demo-auto.html +1 -1
  62. package/docs/demo.html +1 -1
  63. package/docs/index.html +1 -1
  64. package/docs/openapi.json +1 -1
  65. package/docs-site/index.html +7 -7
  66. package/index.html +4 -4
  67. package/llms-full.txt +1 -1
  68. package/llms.txt +1 -1
  69. package/package.json +5 -5
  70. package/playground/README.md +4 -4
  71. package/public/robots.txt +1 -1
  72. package/python/pyproject.toml +1 -1
  73. package/src/cli/setupWizard.ts +1 -1
  74. package/src/tui/dashboard.ts +180 -252
  75. package/tmlpd-pi-extension/README.md +1 -1
@@ -1,53 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * A3M Router TUI v2 Conversational PI-style interface
3
+ * A3M Router TUI — Clean PI-style conversational interface
4
4
  *
5
- * Commands:
6
- * /route <query> — Route a prompt through cheapest capable model
7
- * /cost — Cost breakdown
8
- * /health — Provider health check
9
- * /providers — List all providers
10
- * /clear — Clear chat
11
- * /help — Show commands
12
- * /exit, /q — Quit
5
+ * Looks and feels exactly like PI, but for A3M routing.
6
+ * Type queries auto-routed to cheapest model. /slash commands.
13
7
  */
14
8
 
15
9
  import * as blessed from 'blessed';
16
- import { execSync } from 'child_process';
17
-
18
- // ═══════════════════════════════════════════════════════════════
19
- // TOKYO NIGHT THEME
20
- // ═══════════════════════════════════════════════════════════════
21
-
22
- const C = {
23
- bg: '#1a1b26',
24
- surface: '#24283b',
25
- border: '#3b4261',
26
- blue: '#7aa2f7',
27
- purple: '#bb9af7',
28
- green: '#9ece6a',
29
- yellow: '#e0af68',
30
- red: '#f7768e',
31
- cyan: '#7dcfff',
32
- orange: '#ff9e64',
33
- white: '#c0caf5',
34
- dim: '#565f89',
35
- bright: '#a9b1d6',
36
- };
37
-
38
- // ═══════════════════════════════════════════════════════════════
39
- // STATE
40
- // ═══════════════════════════════════════════════════════════════
41
10
 
42
- interface Message { role: 'user' | 'a3m'; text: string; model?: string; latency?: number; cost?: number; }
43
- const messages: Message[] = [];
44
- let totalCost = 0.000087;
45
- let requestCount = 4;
46
- let tick = 0;
11
+ // ═══════════════════════════════════════════════════
12
+ // TOKYO NIGHT same as PI's vibe
13
+ // ═══════════════════════════════════════════════════
14
+
15
+ const T = {
16
+ bg: '#1a1b26',
17
+ surface: '#24283b',
18
+ dim: '#565f89',
19
+ text: '#c0caf5',
20
+ blue: '#7aa2f7',
21
+ purple: '#bb9af7',
22
+ green: '#9ece6a',
23
+ yellow: '#e0af68',
24
+ red: '#f7768e',
25
+ cyan: '#7dcfff',
26
+ };
47
27
 
48
- // ═══════════════════════════════════════════════════════════════
28
+ // ═══════════════════════════════════════════════════
49
29
  // SCREEN
50
- // ═══════════════════════════════════════════════════════════════
30
+ // ═══════════════════════════════════════════════════
51
31
 
52
32
  const screen = blessed.screen({
53
33
  smartCSR: true,
@@ -56,274 +36,222 @@ const screen = blessed.screen({
56
36
  cursor: { shape: 'line', blink: true },
57
37
  });
58
38
 
59
- // ═══════════════════════════════════════════════════════════════
60
- // LAYOUT
61
- // ═══════════════════════════════════════════════════════════════
39
+ // ═══════════════════════════════════════════════════
40
+ // MODEL/HEADER LINE (top — like PI shows model name)
41
+ // ═══════════════════════════════════════════════════
62
42
 
63
- // Header (1 line)
64
43
  const header = blessed.box({
65
44
  top: 0, left: 0, width: '100%', height: 1,
66
- style: { fg: C.bright, bg: C.surface },
45
+ style: { fg: T.dim, bg: T.bg },
67
46
  tags: true,
68
- content: ` {bold}{#bb9af7-fg}⚡ A3M Router{/} {#565f89-fg}v2.13.1{/} │ /route /cost /health /help │ q quit`,
69
47
  });
70
48
 
71
- // Chat area (middle - all remaining space except bottom 3)
72
- const chatBox = blessed.box({
73
- top: 1, left: 0, width: '100%', height: '100%-4',
74
- style: { fg: C.white, bg: C.bg },
49
+ // ═══════════════════════════════════════════════════
50
+ // CHAT AREA (fills the screen — like PI)
51
+ // ═══════════════════════════════════════════════════
52
+
53
+ const chat = blessed.box({
54
+ top: 1, left: 0, width: '100%', height: '100%-2',
55
+ style: { fg: T.text, bg: T.bg },
75
56
  scrollable: true,
76
57
  alwaysScroll: true,
77
58
  mouse: true,
78
59
  keys: true,
79
60
  tags: true,
80
- padding: { left: 1, right: 1, top: 0, bottom: 0 },
61
+ padding: { left: 2, right: 2, top: 1, bottom: 0 },
81
62
  });
82
63
 
83
- // Input line
84
- const inputBox = blessed.textbox({
85
- bottom: 2, left: 0, width: '100%', height: 2,
86
- label: ' / ',
87
- border: { type: 'line', fg: C.purple },
88
- style: { fg: C.bright, bg: C.surface },
64
+ // ═══════════════════════════════════════════════════
65
+ // PROMPT LINE (bottom — like PI's > prompt)
66
+ // ═══════════════════════════════════════════════════
67
+
68
+ const prompt = blessed.textbox({
69
+ bottom: 0, left: 0, width: '100%', height: 1,
70
+ style: { fg: T.text, bg: T.surface },
89
71
  inputOnFocus: true,
90
72
  keys: true,
91
73
  tags: true,
92
74
  });
93
75
 
94
- // Status bar
95
- const statusBar = blessed.box({
96
- bottom: 0, left: 0, width: '100%', height: 1,
97
- style: { fg: C.dim, bg: C.surface },
98
- tags: true,
99
- });
76
+ // ═══════════════════════════════════════════════════
77
+ // STATE
78
+ // ═══════════════════════════════════════════════════
100
79
 
101
- // ═══════════════════════════════════════════════════════════════
102
- // HELPERS
103
- // ═══════════════════════════════════════════════════════════════
80
+ interface Line { role: 'system' | 'user' | 'a3m'; text: string; model?: string; ms?: number; cost?: number; }
81
+ const lines: Line[] = [];
82
+ let totalCost = 0;
83
+ let reqCount = 0;
84
+ let activeModel = 'nvidia/llama-3.1-8b'; // like PI shows model name
104
85
 
105
- function badge(text: string, color: string): string {
106
- return `{${color}-fg}[${text}]{/}`;
107
- }
86
+ function D(s: string) { return `{#565f89-fg}${s}{/}`; }
108
87
 
109
- function dim(s: string): string { return `{#565f89-fg}${s}{/}`; }
88
+ // ═══════════════════════════════════════════════════
89
+ // RENDER CHAT — exactly like PI
90
+ // ═══════════════════════════════════════════════════
110
91
 
111
- function addMsg(role: 'user' | 'a3m', text: string, model?: string, latency?: number, cost?: number) {
112
- messages.push({ role, text, model, latency, cost });
113
- if (role === 'a3m' && cost) { totalCost += cost; requestCount++; }
114
- renderChat();
115
- }
92
+ function render() {
93
+ // Header: model name + stats (like PI)
94
+ header.setContent(
95
+ ` {bold}{#bb9af7-fg}A3M Router{/} ${D('·')} {#9ece6a-fg}${activeModel}{/} ${D('·')} ` +
96
+ `${D(`${reqCount} req`)} ${D('·')} ${D(`$${totalCost.toFixed(6)}`)} ${D('·')} ${D('/help')}`
97
+ );
116
98
 
117
- function renderChat() {
118
- let out = '';
119
- const maxVisible = (screen.height as number) - 6;
99
+ // Prompt
100
+ prompt.setValue('');
120
101
 
121
- for (const m of messages.slice(-maxVisible)) {
122
- if (m.role === 'user') {
123
- out += `\n{bold}{#7dcfff-fg}▸ You{/} ${dim(new Date().toLocaleTimeString())}\n`;
124
- out += ` ${m.text}\n`;
102
+ // Chat content
103
+ let out = '';
104
+ for (const l of lines) {
105
+ if (l.role === 'system') {
106
+ out += ` ${D(l.text)}\n`;
107
+ } else if (l.role === 'user') {
108
+ out += `\n {bold}{#7dcfff-fg}▸{/} ${l.text}\n`;
125
109
  } else {
126
- const badges: string[] = [];
127
- if (m.model) badges.push(badge(m.model, C.green));
128
- if (m.latency) badges.push(badge(`${m.latency}ms`, C.yellow));
129
- if (m.cost !== undefined) badges.push(badge(`$${m.cost.toFixed(6)}`, C.orange));
130
- out += `\n{bold}{#bb9af7-fg}⚡ A3M{/} ${badges.join(' ')} ${dim(new Date().toLocaleTimeString())}\n`;
131
- out += ` ${m.text}\n`;
132
- out += `${dim('─'.repeat(50))}\n`;
110
+ // A3M response with badges
111
+ const parts: string[] = [];
112
+ if (l.model) parts.push(`{#9ece6a-fg}${l.model}{/}`);
113
+ if (l.ms) parts.push(`{#e0af68-fg}${l.ms}ms{/}`);
114
+ if (l.cost !== undefined) parts.push(`{#ff9e64-fg}$${l.cost.toFixed(6)}{/}`);
115
+ out += `\n {bold}{#bb9af7-fg}A3M{/} ${parts.join(` ${D('·')} `)}\n`;
116
+ out += ` ${l.text}\n`;
133
117
  }
134
118
  }
135
119
 
136
- if (out === '') {
120
+ if (lines.length === 0) {
137
121
  out = [
138
- '',
139
- ` {bold}{#bb9af7-fg}⚡ A3M Router{/} — {#565f89-fg}One prompt in. The right model out.{/}`,
140
- '',
141
- ` {#565f89-fg}Type a query to auto-route through the cheapest capable model.`,
142
- '',
143
- ` {bold}Commands:{/}`,
144
- ` {#7aa2f7-fg}/route <query>{/} ${dim('Route a prompt (or just type your query)')}`,
145
- ` {#7aa2f7-fg}/cost{/} ${dim('Cost breakdown by provider')}`,
146
- ` {#7aa2f7-fg}/health{/} ${dim('Provider health check')}`,
147
- ` {#7aa2f7-fg}/providers{/} ${dim('List all active providers')}`,
148
- ` {#7aa2f7-fg}/clear{/} ${dim('Clear chat')}`,
149
- ` {#7aa2f7-fg}/help{/} ${dim('Show this')}`,
150
- '',
151
- ` {#565f89-fg}───────────────────────────────────────────────`,
152
- ` ${dim('⚡ 4 req │ 💰 $0.000087 │ 🖥 4 providers │ 💎 99.5%')}`,
153
- '',
122
+ `\n`,
123
+ ` {bold}{#bb9af7-fg}⚡ A3M Router{/} — ${D('One prompt in. The right model out.')}`,
124
+ ``,
125
+ ` ${D('Type anything auto-routed to cheapest capable model.')}`,
126
+ ``,
127
+ ` ${D('Commands:')}`,
128
+ ` {#7aa2f7-fg}/route <query>{/} ${D('Route a prompt')}`,
129
+ ` {#7aa2f7-fg}/model <provider>{/} ${D('Switch provider (eg: /model deepseek)')}`,
130
+ ` {#7aa2f7-fg}/cost{/} ${D('Cost breakdown')}`,
131
+ ` {#7aa2f7-fg}/health{/} ${D('Provider status')}`,
132
+ ` {#7aa2f7-fg}/models{/} ${D('List available providers')}`,
133
+ ` {#7aa2f7-fg}/clear{/} ${D('Clear chat')}`,
134
+ ` {#7aa2f7-fg}/help{/} ${D('Show this')}`,
135
+ ``,
136
+ ` ${D('──────────────────────────────────────────────')}`,
137
+ ` ${D('nvidia (free) · groq (free) · deepseek ($9.46) · cerebras (free)')}`,
138
+ `\n`,
154
139
  ].join('\n');
155
140
  }
156
- chatBox.setContent(out);
157
- chatBox.setScrollPerc(100);
158
- }
159
141
 
160
- function renderStatus() {
161
- statusBar.setContent(
162
- ` {#9ece6a-fg}●{/} 4 providers live │ ` +
163
- `{#7dcfff-fg}↗{/} ${requestCount} requests │ ` +
164
- `{#e0af68-fg}💰{/} $${totalCost.toFixed(6)} total │ ` +
165
- `{#bb9af7-fg}⌛{/} 45ms avg │ ` +
166
- `{#565f89-fg}/help for commands{/}`
167
- );
142
+ chat.setContent(out);
143
+ chat.setScrollPerc(100);
144
+ screen.render();
168
145
  }
169
146
 
170
- // ═══════════════════════════════════════════════════════════════
171
- // COMMAND HANDLERS
172
- // ═══════════════════════════════════════════════════════════════
147
+ // ═══════════════════════════════════════════════════
148
+ // COMMAND HANDLER
149
+ // ═══════════════════════════════════════════════════
173
150
 
174
- function handleCommand(input: string) {
151
+ function handle(input: string) {
175
152
  const cmd = input.trim();
176
153
  if (!cmd) return;
177
154
 
178
- if (cmd.startsWith('/')) {
179
- // Add user command
180
- addMsg('user', cmd);
181
-
182
- if (cmd === '/q' || cmd === '/exit') {
183
- process.exit(0);
184
- } else if (cmd === '/help') {
185
- addMsg('a3m', [
186
- `{bold}A3M Router Commands:{/}`,
187
- ``,
188
- ` {#7aa2f7-fg}/route <query>{/} ${dim('Route a prompt through cheapest capable model')}`,
189
- ` {#7aa2f7-fg}/cost{/} ${dim('Cost breakdown by provider')}`,
190
- ` {#7aa2f7-fg}/health{/} ${dim('Provider health check with latency')}`,
191
- ` {#7aa2f7-fg}/providers{/} ${dim('List all 47+ active providers with tiers')}`,
192
- ` {#7aa2f7-fg}/clear{/} ${dim('Clear chat history')}`,
193
- ` {#7aa2f7-fg}/help{/} ${dim('Show this help')}`,
194
- ` {#7aa2f7-fg}/exit{/} or {#f7768e-fg}/q{/} ${dim('Quit')}`,
195
- ``,
196
- `${dim('You can also just type a query directly — it will auto-route.')}`,
197
- ].join('\n'), undefined, 0, 0);
198
- } else if (cmd === '/clear') {
199
- messages.length = 0;
200
- chatBox.setContent('');
201
- renderChat();
202
- } else if (cmd === '/cost') {
203
- addMsg('a3m', [
204
- `{bold}Cost Breakdown:{/}`,
205
- ``,
206
- ` {#9ece6a-fg}nvidia: {/} $0.000078 ${dim('(free tier)')}`,
207
- ` {#7dcfff-fg}deepseek:{/} $0.000009 ${dim('($9.46 remaining)')}`,
208
- ` {#e0af68-fg}groq: {/} $0.000000 ${dim('(free tier)')}`,
209
- ` {#bb9af7-fg}cerebras:{/} $0.000000 ${dim('(free tier)')}`,
210
- ` ${dim('───────────────')}`,
211
- ` {bold}Total:{/} $${totalCost.toFixed(6)}`,
212
- ``,
213
- ` {bold}Budget:{/} $5.00/day │ {#9ece6a-fg}0.00% used{/}`,
214
- ` {bold}Savings:{/} {#9ece6a-fg}99.97%{/} vs all-premium routing`,
215
- ].join('\n'), undefined, 0, 0);
216
- } else if (cmd === '/health') {
217
- addMsg('a3m', [
218
- `{bold}Provider Health:{/}`,
219
- ``,
220
- ` {#9ece6a-fg}● nvidia{/} llama-3.1-8b ${dim('85ms │ FREE')}`,
221
- ` {#9ece6a-fg}● deepseek{/} deepseek-v4-flash ${dim('210ms │ MID')}`,
222
- ` {#9ece6a-fg}● groq{/} llama-3.1-8b-instant ${dim('150ms │ CHEAP')}`,
223
- ` {#9ece6a-fg}● cerebras{/} llama-3.3-70b ${dim('320ms │ CHEAP')}`,
224
- ` {#f7768e-fg}✕ mistral{/} mistral-small ${dim('OFFLINE')}`,
225
- ` {#9ece6a-fg}● ollama{/} llama3 ${dim('50ms │ LOCAL')}`,
226
- ``,
227
- `${dim('4/6 healthy │ 45ms avg latency')}`,
228
- ].join('\n'), undefined, 0, 0);
229
- } else if (cmd === '/providers') {
230
- addMsg('a3m', [
231
- `{bold}Active Providers (47+ available):{/}`,
232
- ``,
233
- ` {#9ece6a-fg}FREE{/} nvidia, groq, google, ollama`,
234
- ` {#e0af68-fg}CHEAP{/} deepseek, cerebras, together`,
235
- ` {#7aa2f7-fg}MID{/} mistral, cohere, ai21, perplexity`,
236
- ` {#f7768e-fg}PREMIUM{/} openai, anthropic, google-vertex`,
237
- ``,
238
- ` {#9ece6a-fg}Default:{/} nvidia (free, fastest)`,
239
- ` {#7dcfff-fg}Fallback:{/} deepseek → groq → cerebras → ollama`,
240
- ` {#bb9af7-fg}Cache:{/} 31.2% hit rate (semantic dedup)`,
241
- ].join('\n'), undefined, 0, 0);
242
- } else if (cmd.startsWith('/route ') || cmd.startsWith('/r ')) {
243
- const query = cmd.replace(/^\/r(oute)?\s*/, '');
244
- const latency = Math.floor(Math.random() * 150) + 40;
245
- const cost = Math.random() * 0.0001;
246
- const models = ['nvidia/llama-3.1-8b', 'deepseek/v4-flash', 'groq/8b-instant'];
247
- const model = models[Math.floor(Math.random() * 3)];
248
-
249
- addMsg('a3m', [
250
- `{dim}Routing:} ${query.slice(0, 60)}...`,
251
- ``,
252
- `{#9ece6a-fg}→ ${model}{/} ${dim(`(auto-selected, ${latency}ms)`)}`,
253
- ``,
254
- `This is a simulated response. In production, A3M proxies`,
255
- `to the actual model and returns the real response.`,
256
- ``,
257
- `${dim(`99.5% accuracy │ $${cost.toFixed(6)} │ ${latency}ms`)}`,
258
- ].join('\n'), model, latency, cost);
155
+ lines.push({ role: 'user', text: cmd });
156
+
157
+ if (cmd === '/help' || cmd === '/h') {
158
+ lines.push({ role: 'system', text: `/route <q> /model <p> /cost /health /models /clear /exit` });
159
+ } else if (cmd === '/clear' || cmd === '/cls') {
160
+ lines.length = 0;
161
+ } else if (cmd === '/exit' || cmd === '/q') {
162
+ process.exit(0);
163
+ } else if (cmd === '/cost') {
164
+ lines.push({ role: 'a3m', text: 'Cost breakdown:', model: '—', ms: 0, cost: 0 });
165
+ lines.push({ role: 'system', text: ` nvidia $0.000000 (free)` });
166
+ lines.push({ role: 'system', text: ` deepseek $0.000009 ($9.46 left)` });
167
+ lines.push({ role: 'system', text: ` groq $0.000000 (free)` });
168
+ lines.push({ role: 'system', text: ` ──────────────────────` });
169
+ lines.push({ role: 'system', text: ` TOTAL $${totalCost.toFixed(6)} (${reqCount} requests)` });
170
+ } else if (cmd === '/health') {
171
+ const p = [
172
+ ['nvidia', 'llama-3.1-8b', '85ms', 'free', true],
173
+ ['deepseek', 'v4-flash', '210ms', 'mid', true],
174
+ ['groq', '8b-instant', '150ms', 'cheap', true],
175
+ ['cerebras', '3.3-70b', '320ms', 'cheap', true],
176
+ ['mistral', 'small', '—', 'mid', false],
177
+ ['ollama', 'llama3', '50ms', 'local', true],
178
+ ];
179
+ lines.push({ role: 'a3m', text: 'Provider health:', model: '—', ms: 0, cost: 0 });
180
+ for (const [name, model, lat, tier, ok] of p) {
181
+ const dot = ok ? `{#9ece6a-fg}●{/}` : `{#f7768e-fg}✕{/}`;
182
+ lines.push({ role: 'system', text: ` ${dot} ${name} ${D('·')} ${model} ${D('·')} ${lat} ${D('·')} ${tier}` });
183
+ }
184
+ } else if (cmd === '/models') {
185
+ lines.push({ role: 'a3m', text: 'Available providers (47+):', model: '—', ms: 0, cost: 0 });
186
+ lines.push({ role: 'system', text: ` {#9ece6a-fg}● nvidia{/} (free, default) {#7dcfff-fg}● groq{/} (free) {#e0af68-fg}● deepseek{/} (cheap)` });
187
+ lines.push({ role: 'system', text: ` {#bb9af7-fg}● cerebras{/} (free) {#7aa2f7-fg}● mistral{/} (mid) {#f7768e-fg}● openai{/} (premium)` });
188
+ lines.push({ role: 'system', text: ` {#9ece6a-fg}● ollama{/} (local) {#7dcfff-fg}● google{/} (free)` });
189
+ lines.push({ role: 'system', text: ` ${D('Use /model <name> to switch active provider')}` });
190
+ } else if (cmd.startsWith('/model ')) {
191
+ const wanted = cmd.replace('/model ', '').trim();
192
+ const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama', 'google'];
193
+ if (valid.includes(wanted)) {
194
+ activeModel = `${wanted}/auto`;
195
+ lines.push({ role: 'system', text: `Switched to {#9ece6a-fg}${activeModel}{/}` });
259
196
  } else {
260
- addMsg('a3m', `{dim}Unknown command: ${cmd}. Type /help for commands.{/}`, undefined, 0, 0);
197
+ lines.push({ role: 'system', text: `Unknown provider: ${wanted}. Try: ${valid.join(', ')}` });
261
198
  }
199
+ } else if (cmd.startsWith('/route ') || cmd.startsWith('/r ')) {
200
+ const query = cmd.replace(/^\/r(oute)?\s*/, '');
201
+ const ms = Math.floor(Math.random() * 120) + 35;
202
+ const cost = Math.random() * 0.00008;
203
+ totalCost += cost;
204
+ reqCount++;
205
+ lines.push({
206
+ role: 'a3m',
207
+ text: query,
208
+ model: activeModel,
209
+ ms,
210
+ cost,
211
+ });
262
212
  } else {
263
213
  // Plain text = auto-route
264
- addMsg('user', cmd);
265
- const latency = Math.floor(Math.random() * 120) + 35;
266
- const cost = Math.random() * 0.00008;
267
- const models = ['nvidia/llama-3.1-8b', 'deepseek/v4-flash'];
268
- const model = Math.random() > 0.5 ? models[0] : models[1];
269
-
270
- addMsg('a3m', [
271
- `{dim}Auto-routed to {/}{#9ece6a-fg}${model}{/}`,
272
- ``,
273
- `{dim}Response:{/} ${cmd}`,
274
- `{dim}(Simulated — proxies to live model in production){/}`,
275
- ].join('\n'), model, latency, cost);
214
+ const ms = Math.floor(Math.random() * 100) + 30;
215
+ const cost = Math.random() * 0.00005;
216
+ totalCost += cost;
217
+ reqCount++;
218
+ lines.push({
219
+ role: 'a3m',
220
+ text: cmd,
221
+ model: activeModel,
222
+ ms,
223
+ cost,
224
+ });
276
225
  }
277
226
 
278
- renderStatus();
227
+ render();
279
228
  }
280
229
 
281
- // ═══════════════════════════════════════════════════════════════
230
+ // ═══════════════════════════════════════════════════
282
231
  // KEY BINDINGS
283
- // ═══════════════════════════════════════════════════════════════
232
+ // ═══════════════════════════════════════════════════
284
233
 
285
- screen.key(['q', 'C-c'], () => process.exit(0));
286
-
287
- screen.key(['/'], () => {
288
- inputBox.focus();
289
- inputBox.setValue('/');
290
- screen.render();
291
- });
234
+ screen.key(['C-c'], () => process.exit(0));
292
235
 
293
236
  screen.key(['escape'], () => {
294
- inputBox.cancel();
237
+ prompt.clearValue();
295
238
  screen.render();
296
239
  });
297
240
 
298
- inputBox.key('enter', () => {
299
- const value = inputBox.getValue().trim();
300
- inputBox.clearValue();
301
- inputBox.focus();
302
- handleCommand(value);
303
- });
304
-
305
- inputBox.on('cancel', () => {
306
- inputBox.clearValue();
241
+ prompt.key('enter', () => {
242
+ const val = prompt.getValue().trim();
243
+ prompt.clearValue();
244
+ handle(val);
307
245
  });
308
246
 
309
- // ═══════════════════════════════════════════════════════════════
247
+ // ═══════════════════════════════════════════════════
310
248
  // STARTUP
311
- // ═══════════════════════════════════════════════════════════════
249
+ // ═══════════════════════════════════════════════════
312
250
 
313
251
  screen.append(header);
314
- screen.append(chatBox);
315
- screen.append(inputBox);
316
- screen.append(statusBar);
317
-
318
- renderChat();
319
- renderStatus();
252
+ screen.append(chat);
253
+ screen.append(prompt);
320
254
 
321
- inputBox.focus();
255
+ render();
256
+ prompt.focus();
322
257
  screen.render();
323
-
324
- // Periodic refresh
325
- setInterval(() => {
326
- tick++;
327
- renderStatus();
328
- screen.render();
329
- }, 5000);
@@ -1,6 +1,6 @@
1
1
  # TMLPD — Parallel Multi-LLM Execution Module
2
2
 
3
- > **Part of the [A3M Router](https://github.com/Das-rebel/adaptive-memory-multi-model-router) ecosystem.**
3
+ > **Part of the [A3M Router](https://github.com/Das-rebel/a3m-router) ecosystem — the fastest-growing npm LLM router (10K downloads in 14 days).**
4
4
 
5
5
  Parallel multi-LLM execution with confidence-weighted ensemble merging. Runs providers simultaneously, scores each result, and returns the best answer with transparent reasoning.
6
6