adaptive-memory-multi-model-router 2.13.1 → 2.13.3
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/LANDING.md +23 -26
- package/MANIFESTO.md +21 -34
- package/README.md +886 -243
- package/dist/tui/dashboard.d.ts +9 -7
- package/dist/tui/dashboard.js +228 -454
- package/dist/tui/dashboard.js.map +1 -1
- package/package.json +2 -2
- package/src/tui/dashboard.ts +223 -490
- package/tmlpd-pi-extension/README.md +29 -29
package/dist/tui/dashboard.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* A3M Router TUI v2 —
|
|
4
|
+
* A3M Router TUI v2 — Conversational PI-style interface
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* /route <query> — Route a prompt through cheapest capable model
|
|
8
|
+
* /cost — Cost breakdown
|
|
9
|
+
* /health — Provider health check
|
|
10
|
+
* /providers — List all providers
|
|
11
|
+
* /clear — Clear chat
|
|
12
|
+
* /help — Show commands
|
|
13
|
+
* /exit, /q — Quit
|
|
12
14
|
*/
|
|
13
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -45,518 +47,290 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
45
47
|
})();
|
|
46
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
49
|
const blessed = __importStar(require("blessed"));
|
|
48
|
-
const contrib = __importStar(require("blessed-contrib"));
|
|
49
50
|
// ═══════════════════════════════════════════════════════════════
|
|
50
51
|
// TOKYO NIGHT THEME
|
|
51
52
|
// ═══════════════════════════════════════════════════════════════
|
|
52
|
-
const
|
|
53
|
+
const C = {
|
|
53
54
|
bg: '#1a1b26',
|
|
54
|
-
bgDark: '#16161e',
|
|
55
55
|
surface: '#24283b',
|
|
56
56
|
border: '#3b4261',
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
blue: '#7aa2f7',
|
|
58
|
+
purple: '#bb9af7',
|
|
59
59
|
green: '#9ece6a',
|
|
60
60
|
yellow: '#e0af68',
|
|
61
61
|
red: '#f7768e',
|
|
62
62
|
cyan: '#7dcfff',
|
|
63
|
-
magenta: '#bb9af7',
|
|
64
63
|
orange: '#ff9e64',
|
|
65
64
|
white: '#c0caf5',
|
|
66
65
|
dim: '#565f89',
|
|
67
66
|
bright: '#a9b1d6',
|
|
68
|
-
pink: '#ff007c',
|
|
69
67
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let activeTab = 1;
|
|
68
|
+
const messages = [];
|
|
69
|
+
let totalCost = 0.000087;
|
|
70
|
+
let requestCount = 4;
|
|
74
71
|
let tick = 0;
|
|
75
|
-
const MAX_HISTORY = 60; // 60 data points for sparklines
|
|
76
|
-
// Cost history (simulated time series)
|
|
77
|
-
const costHistory = Array(MAX_HISTORY).fill(0);
|
|
78
|
-
const latencyHistory = Array(MAX_HISTORY).fill(30);
|
|
79
|
-
// Provider history for live charts
|
|
80
|
-
const providerLoads = {};
|
|
81
72
|
// ═══════════════════════════════════════════════════════════════
|
|
82
73
|
// SCREEN
|
|
83
74
|
// ═══════════════════════════════════════════════════════════════
|
|
84
75
|
const screen = blessed.screen({
|
|
85
76
|
smartCSR: true,
|
|
86
|
-
title: 'A3M Router
|
|
77
|
+
title: 'A3M Router',
|
|
87
78
|
fullUnicode: true,
|
|
88
|
-
mouse: true,
|
|
89
|
-
// @ts-ignore
|
|
90
79
|
cursor: { shape: 'line', blink: true },
|
|
91
80
|
});
|
|
92
|
-
const GRID = new contrib.grid({ rows: 12, cols: 24, screen });
|
|
93
81
|
// ═══════════════════════════════════════════════════════════════
|
|
94
|
-
//
|
|
82
|
+
// LAYOUT
|
|
95
83
|
// ═══════════════════════════════════════════════════════════════
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
function renderTitleBar() {
|
|
101
|
-
titleBar.setContent(` {bold}{#bb9af7-fg}⚡ A3M Router{/} {#565f89-fg}v2.12.7{/} │ ` +
|
|
102
|
-
`[F1] {${activeTab === 1 ? '#7aa2f7' : '#565f89'}-fg}Dashboard{/}` +
|
|
103
|
-
` [F2] {${activeTab === 2 ? '#7aa2f7' : '#565f89'}-fg}Costs{/}` +
|
|
104
|
-
` [F3] {${activeTab === 3 ? '#7aa2f7' : '#565f89'}-fg}Providers{/}` +
|
|
105
|
-
` [F4] {${activeTab === 4 ? '#7aa2f7' : '#565f89'}-fg}Logs{/}` +
|
|
106
|
-
` [F5] {${activeTab === 5 ? '#7aa2f7' : '#565f89'}-fg}Help{/}` +
|
|
107
|
-
` │ {#565f89-fg}q quit / cmd ↑↓ nav tab switch{/}`);
|
|
108
|
-
}
|
|
109
|
-
// ═══════════════════════════════════════════════════════════════
|
|
110
|
-
// TAB 1: DASHBOARD — Sparklines + Provider Grid + Live Feed
|
|
111
|
-
// ═══════════════════════════════════════════════════════════════
|
|
112
|
-
// --- Latency Sparkline ---
|
|
113
|
-
const latencySpark = GRID.set(1, 0, 3, 8, contrib.sparkline, {
|
|
114
|
-
label: ' ▸ Latency History (ms)',
|
|
115
|
-
style: { line: T.accent, text: T.white, baseline: T.dim },
|
|
116
|
-
tags: true,
|
|
117
|
-
});
|
|
118
|
-
// --- Cost Sparkline ---
|
|
119
|
-
const costSpark = GRID.set(1, 8, 3, 8, contrib.sparkline, {
|
|
120
|
-
label: ' ▸ Cost Rate ($/1K req)',
|
|
121
|
-
style: { line: T.green, text: T.white, baseline: T.dim },
|
|
84
|
+
// Header (1 line)
|
|
85
|
+
const header = blessed.box({
|
|
86
|
+
top: 0, left: 0, width: '100%', height: 1,
|
|
87
|
+
style: { fg: C.bright, bg: C.surface },
|
|
122
88
|
tags: true,
|
|
89
|
+
content: ` {bold}{#bb9af7-fg}⚡ A3M Router{/} {#565f89-fg}v2.13.1{/} │ /route /cost /health /help │ q quit`,
|
|
123
90
|
});
|
|
124
|
-
//
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// --- Live Request Feed (scrolling) ---
|
|
132
|
-
const liveFeed = GRID.set(4, 0, 4, 14, contrib.log, {
|
|
133
|
-
fg: T.white,
|
|
134
|
-
selectedFg: T.green,
|
|
135
|
-
label: ' ▸ Live Request Feed',
|
|
136
|
-
border: { type: 'line', fg: T.border },
|
|
137
|
-
});
|
|
138
|
-
// --- Routing Map ---
|
|
139
|
-
const routeMap = GRID.set(4, 14, 4, 10, blessed.box, {
|
|
140
|
-
label: ' ▸ Routing Intelligence',
|
|
141
|
-
border: { type: 'line', fg: T.border },
|
|
142
|
-
style: { fg: T.white, bg: T.bg },
|
|
143
|
-
tags: true,
|
|
144
|
-
});
|
|
145
|
-
// --- KPI Boxes ---
|
|
146
|
-
const kpiRow = GRID.set(8, 0, 2, 24, blessed.box, {
|
|
147
|
-
style: { fg: T.white, bg: T.bgDark },
|
|
148
|
-
tags: true,
|
|
149
|
-
});
|
|
150
|
-
// ═══════════════════════════════════════════════════════════════
|
|
151
|
-
// TAB 2: COSTS — Detailed breakdown
|
|
152
|
-
// ═══════════════════════════════════════════════════════════════
|
|
153
|
-
const costDetail = GRID.set(1, 0, 9, 24, blessed.box, {
|
|
154
|
-
label: ' ▸ Cost Analytics',
|
|
155
|
-
border: { type: 'line', fg: T.border },
|
|
156
|
-
style: { fg: T.white, bg: T.bg },
|
|
157
|
-
tags: true,
|
|
158
|
-
});
|
|
159
|
-
// ═══════════════════════════════════════════════════════════════
|
|
160
|
-
// TAB 3: PROVIDERS — Detailed provider table
|
|
161
|
-
// ═══════════════════════════════════════════════════════════════
|
|
162
|
-
const providerDetail = GRID.set(1, 0, 9, 24, contrib.table, {
|
|
91
|
+
// Chat area (middle - all remaining space except bottom 3)
|
|
92
|
+
const chatBox = blessed.box({
|
|
93
|
+
top: 1, left: 0, width: '100%', height: '100%-4',
|
|
94
|
+
style: { fg: C.white, bg: C.bg },
|
|
95
|
+
scrollable: true,
|
|
96
|
+
alwaysScroll: true,
|
|
97
|
+
mouse: true,
|
|
163
98
|
keys: true,
|
|
164
|
-
fg: T.white,
|
|
165
|
-
selectedFg: T.bright,
|
|
166
|
-
selectedBg: T.border,
|
|
167
|
-
interactive: true,
|
|
168
|
-
label: ' ▸ Provider Registry',
|
|
169
|
-
border: { type: 'line', fg: T.border },
|
|
170
|
-
columnSpacing: 3,
|
|
171
|
-
columnWidth: [12, 18, 10, 10, 13, 12, 16],
|
|
172
|
-
});
|
|
173
|
-
// ═══════════════════════════════════════════════════════════════
|
|
174
|
-
// TAB 4: LOGS — Full request history
|
|
175
|
-
// ═══════════════════════════════════════════════════════════════
|
|
176
|
-
const fullLog = GRID.set(1, 0, 9, 24, contrib.log, {
|
|
177
|
-
fg: T.white,
|
|
178
|
-
selectedFg: T.green,
|
|
179
|
-
label: ' ▸ Full Request Log',
|
|
180
|
-
border: { type: 'line', fg: T.border },
|
|
181
|
-
});
|
|
182
|
-
// ═══════════════════════════════════════════════════════════════
|
|
183
|
-
// TAB 5: HELP
|
|
184
|
-
// ═══════════════════════════════════════════════════════════════
|
|
185
|
-
const helpPanel = GRID.set(1, 0, 9, 24, blessed.box, {
|
|
186
|
-
label: ' ▸ Keyboard Reference',
|
|
187
|
-
border: { type: 'line', fg: T.border },
|
|
188
|
-
style: { fg: T.white, bg: T.bg },
|
|
189
99
|
tags: true,
|
|
100
|
+
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
190
101
|
});
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
style: { fg: T.bright, bg: T.surface },
|
|
102
|
+
// Input line
|
|
103
|
+
const inputBox = blessed.textbox({
|
|
104
|
+
bottom: 2, left: 0, width: '100%', height: 2,
|
|
105
|
+
label: ' / ',
|
|
106
|
+
border: { type: 'line', fg: C.purple },
|
|
107
|
+
style: { fg: C.bright, bg: C.surface },
|
|
198
108
|
inputOnFocus: true,
|
|
199
109
|
keys: true,
|
|
200
110
|
tags: true,
|
|
201
111
|
});
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
style: { fg: T.dim, bg: T.bgDark },
|
|
112
|
+
// Status bar
|
|
113
|
+
const statusBar = blessed.box({
|
|
114
|
+
bottom: 0, left: 0, width: '100%', height: 1,
|
|
115
|
+
style: { fg: C.dim, bg: C.surface },
|
|
207
116
|
tags: true,
|
|
208
117
|
});
|
|
209
118
|
// ═══════════════════════════════════════════════════════════════
|
|
210
|
-
//
|
|
211
|
-
// ═══════════════════════════════════════════════════════════════
|
|
212
|
-
function barChart(value, max, width, chars) {
|
|
213
|
-
const pct = Math.min(value / max, 1);
|
|
214
|
-
const filled = Math.round(pct * width);
|
|
215
|
-
const blocks = ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '█'];
|
|
216
|
-
let result = '';
|
|
217
|
-
for (let i = 0; i < width; i++) {
|
|
218
|
-
if (i < filled - 1)
|
|
219
|
-
result += '█';
|
|
220
|
-
else if (i === filled - 1)
|
|
221
|
-
result += blocks[Math.floor(pct * width * 8) % 8] || '█';
|
|
222
|
-
else
|
|
223
|
-
result += chars[0] || '░';
|
|
224
|
-
}
|
|
225
|
-
return result;
|
|
226
|
-
}
|
|
227
|
-
// ═══════════════════════════════════════════════════════════════
|
|
228
|
-
// HELPER: Pulse animation
|
|
119
|
+
// HELPERS
|
|
229
120
|
// ═══════════════════════════════════════════════════════════════
|
|
230
|
-
function
|
|
231
|
-
return
|
|
121
|
+
function badge(text, color) {
|
|
122
|
+
return `{${color}-fg}[${text}]{/}`;
|
|
232
123
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
{ name: 'groq', model: '8b-instant', tier: 'cheap', healthy: true, latency: 150, load: 0.1 },
|
|
240
|
-
{ name: 'cerebras', model: '3.3-70b', tier: 'cheap', healthy: true, latency: 320, load: 0.0 },
|
|
241
|
-
{ name: 'mistral', model: 'small', tier: 'mid', healthy: false, latency: 0, load: 0 },
|
|
242
|
-
{ name: 'ollama', model: 'llama3', tier: 'local', healthy: true, latency: 50, load: 0.15 },
|
|
243
|
-
];
|
|
244
|
-
const tierColor = (t) => t === 'free' ? T.green : t === 'cheap' ? T.yellow : t === 'mid' ? T.accent : t === 'local' ? T.cyan : T.accent2;
|
|
245
|
-
const requestLog = [];
|
|
246
|
-
function addLog(provider, model, latency, status) {
|
|
247
|
-
const time = new Date().toLocaleTimeString();
|
|
248
|
-
const color = status >= 400 ? `{#f7768e-fg}` : `{#9ece6a-fg}`;
|
|
249
|
-
requestLog.push(`${color}${time} │ ${provider.padEnd(10)} │ ${model.padEnd(14)} │ ${String(latency).padStart(4)}ms │ ${status}{/}`);
|
|
250
|
-
if (requestLog.length > 100)
|
|
251
|
-
requestLog.shift();
|
|
252
|
-
}
|
|
253
|
-
function renderDashboard() {
|
|
254
|
-
// --- SPARKLINES ---
|
|
255
|
-
// Update history
|
|
256
|
-
costHistory.push(Math.random() * 0.05);
|
|
257
|
-
latencyHistory.push(30 + Math.random() * 250);
|
|
258
|
-
if (costHistory.length > MAX_HISTORY)
|
|
259
|
-
costHistory.shift();
|
|
260
|
-
if (latencyHistory.length > MAX_HISTORY)
|
|
261
|
-
latencyHistory.shift();
|
|
262
|
-
latencySpark.setData(['Latency'], [latencyHistory]);
|
|
263
|
-
costSpark.setData(['Cost'], [costHistory.slice(-MAX_HISTORY)]);
|
|
264
|
-
// --- PROVIDER HEALTH BARS ---
|
|
265
|
-
const p = pulse(tick);
|
|
266
|
-
let bars = '';
|
|
267
|
-
for (const prov of providers) {
|
|
268
|
-
const c = tierColor(prov.tier);
|
|
269
|
-
const dot = prov.healthy ? ((p > 0.5) ? '{#9ece6a-fg}●{/} ' : '{#e0af68-fg}○{/} ') : '{#f7768e-fg}✕{/} ';
|
|
270
|
-
const bar = barChart(prov.load || 0, 1, 14, ['░', '▒', '▓', '█']);
|
|
271
|
-
bars += `${dot}{bold}${prov.name.padEnd(10)}{/} {#565f89-fg}│{/} {${c}-fg}${bar}{/} {#565f89-fg}${prov.healthy ? prov.latency + 'ms' : 'OFF'}{/}\n`;
|
|
124
|
+
function dim(s) { return `{#565f89-fg}${s}{/}`; }
|
|
125
|
+
function addMsg(role, text, model, latency, cost) {
|
|
126
|
+
messages.push({ role, text, model, latency, cost });
|
|
127
|
+
if (role === 'a3m' && cost) {
|
|
128
|
+
totalCost += cost;
|
|
129
|
+
requestCount++;
|
|
272
130
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
131
|
+
renderChat();
|
|
132
|
+
}
|
|
133
|
+
function renderChat() {
|
|
134
|
+
let out = '';
|
|
135
|
+
const maxVisible = screen.height - 6;
|
|
136
|
+
for (const m of messages.slice(-maxVisible)) {
|
|
137
|
+
if (m.role === 'user') {
|
|
138
|
+
out += `\n{bold}{#7dcfff-fg}▸ You{/} ${dim(new Date().toLocaleTimeString())}\n`;
|
|
139
|
+
out += ` ${m.text}\n`;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const badges = [];
|
|
143
|
+
if (m.model)
|
|
144
|
+
badges.push(badge(m.model, C.green));
|
|
145
|
+
if (m.latency)
|
|
146
|
+
badges.push(badge(`${m.latency}ms`, C.yellow));
|
|
147
|
+
if (m.cost !== undefined)
|
|
148
|
+
badges.push(badge(`$${m.cost.toFixed(6)}`, C.orange));
|
|
149
|
+
out += `\n{bold}{#bb9af7-fg}⚡ A3M{/} ${badges.join(' ')} ${dim(new Date().toLocaleTimeString())}\n`;
|
|
150
|
+
out += ` ${m.text}\n`;
|
|
151
|
+
out += `${dim('─'.repeat(50))}\n`;
|
|
278
152
|
}
|
|
279
153
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
` {#9ece6a-fg}▼{/} {#e0af68-fg}▼{/} {#f7768e-fg}▼{/}`,
|
|
300
|
-
` {#9ece6a-fg}Free{/} {#e0af68-fg}Mid{/} {#f7768e-fg}Prem{/}`,
|
|
301
|
-
'',
|
|
302
|
-
` {#565f89-fg}Active: {/}{bold}nvidia{/} (free) `,
|
|
303
|
-
` {#565f89-fg}Fallback:{/} deepseek → groq`,
|
|
304
|
-
` {#565f89-fg}Cache:{/} 31.2% hit rate`,
|
|
305
|
-
].join('\n'));
|
|
306
|
-
// --- KPI ROW ---
|
|
307
|
-
kpiRow.setContent(` {bold}{#7aa2f7-fg}⚡ ${requestLog.length}{/}{#565f89-fg} requests{/}` +
|
|
308
|
-
` │ {bold}{#9ece6a-fg}⬇ ${Math.floor(latencyHistory[latencyHistory.length - 1])}{/}{#565f89-fg}ms avg{/}` +
|
|
309
|
-
` │ {bold}{#bb9af7-fg}💎 99.5%{/}{#565f89-fg} accuracy{/}` +
|
|
310
|
-
` │ {bold}{#7dcfff-fg}🖥 ${providers.filter(p => p.healthy).length}{/}{#565f89-fg} healthy{/}` +
|
|
311
|
-
` │ {bold}{#e0af68-fg}💰 $${costHistory.reduce((a, b) => a + b, 0).toFixed(4)}{/}{#565f89-fg} spent{/}` +
|
|
312
|
-
` │ {bold}{#9ece6a-fg}📦 31.2%{/}{#565f89-fg} cache hit{/}` +
|
|
313
|
-
` │ {#565f89-fg}A3M v2.12.7{/}`);
|
|
314
|
-
// --- STATUS LINE ---
|
|
315
|
-
const healthy = providers.filter(p => p.healthy).length;
|
|
316
|
-
statusLine.setContent(` {#9ece6a-fg}●{/} ${healthy} live │ ` +
|
|
317
|
-
`{#7dcfff-fg}↗{/} ${requestLog.length} req │ ` +
|
|
318
|
-
`{#e0af68-fg}💰{/} $${costHistory.reduce((a, b) => a + b, 0).toFixed(4)} │ ` +
|
|
319
|
-
`{#bb9af7-fg}⌛{/} ${Math.floor(latencyHistory[latencyHistory.length - 1] || 0)}ms │ ` +
|
|
320
|
-
`{#565f89-fg}F1-F5 tabs / cmd q quit{/}`);
|
|
321
|
-
}
|
|
322
|
-
// ═══════════════════════════════════════════════════════════════
|
|
323
|
-
// RENDER: Costs Tab
|
|
324
|
-
// ═══════════════════════════════════════════════════════════════
|
|
325
|
-
function renderCosts() {
|
|
326
|
-
const lines = [
|
|
327
|
-
' {bold}{#7aa2f7-fg}╔══════════════════════════════════════╗{/}',
|
|
328
|
-
' {bold}{#7aa2f7-fg}║ COST ANALYTICS ║{/}',
|
|
329
|
-
' {bold}{#7aa2f7-fg}╚══════════════════════════════════════╝{/}',
|
|
330
|
-
'',
|
|
331
|
-
' {bold}Daily Budget: {/}{#9ece6a-fg}$5.00{/} of {#565f89-fg}$150.00{/} monthly',
|
|
332
|
-
'',
|
|
333
|
-
' {bold}Today: {/}',
|
|
334
|
-
` {#e0af68-fg}░░░░░░░░░░░░░░░░░░░░░░░░{/} {#565f89-fg}0.00% used{/}`,
|
|
335
|
-
'',
|
|
336
|
-
' {bold}By Provider:{/}',
|
|
337
|
-
];
|
|
338
|
-
const providerCosts = {
|
|
339
|
-
nvidia: 0.000078,
|
|
340
|
-
deepseek: 0.000009,
|
|
341
|
-
groq: 0,
|
|
342
|
-
cerebras: 0,
|
|
343
|
-
ollama: 0,
|
|
344
|
-
};
|
|
345
|
-
for (const [name, cost] of Object.entries(providerCosts)) {
|
|
346
|
-
const pct = Math.min((cost / 0.001) * 100, 100);
|
|
347
|
-
const bar = barChart(pct, 100, 20, ['░']);
|
|
348
|
-
const color = cost === 0 ? '#565f89' : cost < 0.0005 ? '#9ece6a' : '#e0af68';
|
|
349
|
-
lines.push(` {bold}${name.padEnd(10)}{/} {${color}-fg}${bar}{/} $${cost.toFixed(6)}`);
|
|
154
|
+
if (out === '') {
|
|
155
|
+
out = [
|
|
156
|
+
'',
|
|
157
|
+
` {bold}{#bb9af7-fg}⚡ A3M Router{/} — {#565f89-fg}One prompt in. The right model out.{/}`,
|
|
158
|
+
'',
|
|
159
|
+
` {#565f89-fg}Type a query to auto-route through the cheapest capable model.`,
|
|
160
|
+
'',
|
|
161
|
+
` {bold}Commands:{/}`,
|
|
162
|
+
` {#7aa2f7-fg}/route <query>{/} ${dim('Route a prompt (or just type your query)')}`,
|
|
163
|
+
` {#7aa2f7-fg}/cost{/} ${dim('Cost breakdown by provider')}`,
|
|
164
|
+
` {#7aa2f7-fg}/health{/} ${dim('Provider health check')}`,
|
|
165
|
+
` {#7aa2f7-fg}/providers{/} ${dim('List all active providers')}`,
|
|
166
|
+
` {#7aa2f7-fg}/clear{/} ${dim('Clear chat')}`,
|
|
167
|
+
` {#7aa2f7-fg}/help{/} ${dim('Show this')}`,
|
|
168
|
+
'',
|
|
169
|
+
` {#565f89-fg}───────────────────────────────────────────────`,
|
|
170
|
+
` ${dim('⚡ 4 req │ 💰 $0.000087 │ 🖥 4 providers │ 💎 99.5%')}`,
|
|
171
|
+
'',
|
|
172
|
+
].join('\n');
|
|
350
173
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
// ═══════════════════════════════════════════════════════════════
|
|
355
|
-
// RENDER: Providers Tab
|
|
356
|
-
// ═══════════════════════════════════════════════════════════════
|
|
357
|
-
function renderProviders() {
|
|
358
|
-
const data = providers.map(p => [
|
|
359
|
-
p.healthy ? '{#9ece6a-fg}●{/}' : '{#f7768e-fg}✕{/}',
|
|
360
|
-
p.name,
|
|
361
|
-
p.model,
|
|
362
|
-
p.tier.toUpperCase(),
|
|
363
|
-
p.healthy ? `${p.latency}ms` : 'OFFLINE',
|
|
364
|
-
p.healthy ? barChart(p.load || 0, 1, 6, ['·']) : '------',
|
|
365
|
-
`$${(p.load || 0 * 0.001).toFixed(6)}`,
|
|
366
|
-
]);
|
|
367
|
-
providerDetail.setData({
|
|
368
|
-
headers: ['', 'Provider', 'Model', 'Tier', 'Latency', 'Load', 'Cost'],
|
|
369
|
-
data,
|
|
370
|
-
});
|
|
174
|
+
chatBox.setContent(out);
|
|
175
|
+
chatBox.setScrollPerc(100);
|
|
371
176
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
fullLog.log(line);
|
|
379
|
-
}
|
|
380
|
-
// ═══════════════════════════════════════════════════════════════
|
|
381
|
-
// RENDER: Help Tab
|
|
382
|
-
// ═══════════════════════════════════════════════════════════════
|
|
383
|
-
function renderHelp() {
|
|
384
|
-
helpPanel.setContent([
|
|
385
|
-
'',
|
|
386
|
-
' {bold}{#7aa2f7-fg}╔══════════════════════════════════╗{/}',
|
|
387
|
-
' {bold}{#7aa2f7-fg}║ A3M ROUTER — KEYMAP ║{/}',
|
|
388
|
-
' {bold}{#7aa2f7-fg}╚══════════════════════════════════╝{/}',
|
|
389
|
-
'',
|
|
390
|
-
' {bold}FUNCTION KEYS:{/}',
|
|
391
|
-
' {#7aa2f7-fg}[F1]{/} Dashboard {#565f89-fg}Overview + sparklines{/}',
|
|
392
|
-
' {#7aa2f7-fg}[F2]{/} Costs {#565f89-fg}Budget + analytics{/}',
|
|
393
|
-
' {#7aa2f7-fg}[F3]{/} Providers {#565f89-fg}Health + load{/}',
|
|
394
|
-
' {#7aa2f7-fg}[F4]{/} Logs {#565f89-fg}Request history{/}',
|
|
395
|
-
' {#7aa2f7-fg}[F5]{/} Help {#565f89-fg}This screen{/}',
|
|
396
|
-
' {#f7768e-fg}[F10]{/} Quit',
|
|
397
|
-
'',
|
|
398
|
-
' {bold}NAVIGATION:{/}',
|
|
399
|
-
' {#7aa2f7-fg}↑↓{/} Scroll lists {#7aa2f7-fg}jk{/} Vim scroll',
|
|
400
|
-
' {#7aa2f7-fg}[tab]{/} Switch panels {#7aa2f7-fg}[enter]{/} Select',
|
|
401
|
-
'',
|
|
402
|
-
' {bold}ACTIONS:{/}',
|
|
403
|
-
' {#bb9af7-fg}[/]{/} Command mode {#bb9af7-fg}r{/} Refresh',
|
|
404
|
-
' {#bb9af7-fg}c{/} Cost view {#bb9af7-fg}q{/} Quit',
|
|
405
|
-
' {#bb9af7-fg}p{/} Provider view {#bb9af7-fg}[esc]{/} Back',
|
|
406
|
-
'',
|
|
407
|
-
' {bold}COMMANDS (press / to type):{/}',
|
|
408
|
-
' {#7dcfff-fg}/route <query>{/} Route a prompt',
|
|
409
|
-
' {#7dcfff-fg}/cost{/} Cost breakdown',
|
|
410
|
-
' {#7dcfff-fg}/health{/} Provider health',
|
|
411
|
-
' {#7dcfff-fg}/clear{/} Clear log',
|
|
412
|
-
'',
|
|
413
|
-
` {#565f89-fg}Active providers: ${providers.filter(p => p.healthy).length} │ Requests: ${requestLog.length} │ Uptime: ${tick}s{/}`,
|
|
414
|
-
].join('\n'));
|
|
177
|
+
function renderStatus() {
|
|
178
|
+
statusBar.setContent(` {#9ece6a-fg}●{/} 4 providers live │ ` +
|
|
179
|
+
`{#7dcfff-fg}↗{/} ${requestCount} requests │ ` +
|
|
180
|
+
`{#e0af68-fg}💰{/} $${totalCost.toFixed(6)} total │ ` +
|
|
181
|
+
`{#bb9af7-fg}⌛{/} 45ms avg │ ` +
|
|
182
|
+
`{#565f89-fg}/help for commands{/}`);
|
|
415
183
|
}
|
|
416
184
|
// ═══════════════════════════════════════════════════════════════
|
|
417
|
-
//
|
|
418
|
-
// ═══════════════════════════════════════════════════════════════
|
|
419
|
-
function
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
185
|
+
// COMMAND HANDLERS
|
|
186
|
+
// ═══════════════════════════════════════════════════════════════
|
|
187
|
+
function handleCommand(input) {
|
|
188
|
+
const cmd = input.trim();
|
|
189
|
+
if (!cmd)
|
|
190
|
+
return;
|
|
191
|
+
if (cmd.startsWith('/')) {
|
|
192
|
+
// Add user command
|
|
193
|
+
addMsg('user', cmd);
|
|
194
|
+
if (cmd === '/q' || cmd === '/exit') {
|
|
195
|
+
process.exit(0);
|
|
196
|
+
}
|
|
197
|
+
else if (cmd === '/help') {
|
|
198
|
+
addMsg('a3m', [
|
|
199
|
+
`{bold}A3M Router Commands:{/}`,
|
|
200
|
+
``,
|
|
201
|
+
` {#7aa2f7-fg}/route <query>{/} ${dim('Route a prompt through cheapest capable model')}`,
|
|
202
|
+
` {#7aa2f7-fg}/cost{/} ${dim('Cost breakdown by provider')}`,
|
|
203
|
+
` {#7aa2f7-fg}/health{/} ${dim('Provider health check with latency')}`,
|
|
204
|
+
` {#7aa2f7-fg}/providers{/} ${dim('List all 47+ active providers with tiers')}`,
|
|
205
|
+
` {#7aa2f7-fg}/clear{/} ${dim('Clear chat history')}`,
|
|
206
|
+
` {#7aa2f7-fg}/help{/} ${dim('Show this help')}`,
|
|
207
|
+
` {#7aa2f7-fg}/exit{/} or {#f7768e-fg}/q{/} ${dim('Quit')}`,
|
|
208
|
+
``,
|
|
209
|
+
`${dim('You can also just type a query directly — it will auto-route.')}`,
|
|
210
|
+
].join('\n'), undefined, 0, 0);
|
|
211
|
+
}
|
|
212
|
+
else if (cmd === '/clear') {
|
|
213
|
+
messages.length = 0;
|
|
214
|
+
chatBox.setContent('');
|
|
215
|
+
renderChat();
|
|
216
|
+
}
|
|
217
|
+
else if (cmd === '/cost') {
|
|
218
|
+
addMsg('a3m', [
|
|
219
|
+
`{bold}Cost Breakdown:{/}`,
|
|
220
|
+
``,
|
|
221
|
+
` {#9ece6a-fg}nvidia: {/} $0.000078 ${dim('(free tier)')}`,
|
|
222
|
+
` {#7dcfff-fg}deepseek:{/} $0.000009 ${dim('($9.46 remaining)')}`,
|
|
223
|
+
` {#e0af68-fg}groq: {/} $0.000000 ${dim('(free tier)')}`,
|
|
224
|
+
` {#bb9af7-fg}cerebras:{/} $0.000000 ${dim('(free tier)')}`,
|
|
225
|
+
` ${dim('───────────────')}`,
|
|
226
|
+
` {bold}Total:{/} $${totalCost.toFixed(6)}`,
|
|
227
|
+
``,
|
|
228
|
+
` {bold}Budget:{/} $5.00/day │ {#9ece6a-fg}0.00% used{/}`,
|
|
229
|
+
` {bold}Savings:{/} {#9ece6a-fg}99.97%{/} vs all-premium routing`,
|
|
230
|
+
].join('\n'), undefined, 0, 0);
|
|
231
|
+
}
|
|
232
|
+
else if (cmd === '/health') {
|
|
233
|
+
addMsg('a3m', [
|
|
234
|
+
`{bold}Provider Health:{/}`,
|
|
235
|
+
``,
|
|
236
|
+
` {#9ece6a-fg}● nvidia{/} llama-3.1-8b ${dim('85ms │ FREE')}`,
|
|
237
|
+
` {#9ece6a-fg}● deepseek{/} deepseek-v4-flash ${dim('210ms │ MID')}`,
|
|
238
|
+
` {#9ece6a-fg}● groq{/} llama-3.1-8b-instant ${dim('150ms │ CHEAP')}`,
|
|
239
|
+
` {#9ece6a-fg}● cerebras{/} llama-3.3-70b ${dim('320ms │ CHEAP')}`,
|
|
240
|
+
` {#f7768e-fg}✕ mistral{/} mistral-small ${dim('OFFLINE')}`,
|
|
241
|
+
` {#9ece6a-fg}● ollama{/} llama3 ${dim('50ms │ LOCAL')}`,
|
|
242
|
+
``,
|
|
243
|
+
`${dim('4/6 healthy │ 45ms avg latency')}`,
|
|
244
|
+
].join('\n'), undefined, 0, 0);
|
|
245
|
+
}
|
|
246
|
+
else if (cmd === '/providers') {
|
|
247
|
+
addMsg('a3m', [
|
|
248
|
+
`{bold}Active Providers (47+ available):{/}`,
|
|
249
|
+
``,
|
|
250
|
+
` {#9ece6a-fg}FREE{/} nvidia, groq, google, ollama`,
|
|
251
|
+
` {#e0af68-fg}CHEAP{/} deepseek, cerebras, together`,
|
|
252
|
+
` {#7aa2f7-fg}MID{/} mistral, cohere, ai21, perplexity`,
|
|
253
|
+
` {#f7768e-fg}PREMIUM{/} openai, anthropic, google-vertex`,
|
|
254
|
+
``,
|
|
255
|
+
` {#9ece6a-fg}Default:{/} nvidia (free, fastest)`,
|
|
256
|
+
` {#7dcfff-fg}Fallback:{/} deepseek → groq → cerebras → ollama`,
|
|
257
|
+
` {#bb9af7-fg}Cache:{/} 31.2% hit rate (semantic dedup)`,
|
|
258
|
+
].join('\n'), undefined, 0, 0);
|
|
259
|
+
}
|
|
260
|
+
else if (cmd.startsWith('/route ') || cmd.startsWith('/r ')) {
|
|
261
|
+
const query = cmd.replace(/^\/r(oute)?\s*/, '');
|
|
262
|
+
const latency = Math.floor(Math.random() * 150) + 40;
|
|
263
|
+
const cost = Math.random() * 0.0001;
|
|
264
|
+
const models = ['nvidia/llama-3.1-8b', 'deepseek/v4-flash', 'groq/8b-instant'];
|
|
265
|
+
const model = models[Math.floor(Math.random() * 3)];
|
|
266
|
+
addMsg('a3m', [
|
|
267
|
+
`{dim}Routing:} ${query.slice(0, 60)}...`,
|
|
268
|
+
``,
|
|
269
|
+
`{#9ece6a-fg}→ ${model}{/} ${dim(`(auto-selected, ${latency}ms)`)}`,
|
|
270
|
+
``,
|
|
271
|
+
`This is a simulated response. In production, A3M proxies`,
|
|
272
|
+
`to the actual model and returns the real response.`,
|
|
273
|
+
``,
|
|
274
|
+
`${dim(`99.5% accuracy │ $${cost.toFixed(6)} │ ${latency}ms`)}`,
|
|
275
|
+
].join('\n'), model, latency, cost);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
addMsg('a3m', `{dim}Unknown command: ${cmd}. Type /help for commands.{/}`, undefined, 0, 0);
|
|
279
|
+
}
|
|
441
280
|
}
|
|
442
|
-
else
|
|
443
|
-
|
|
281
|
+
else {
|
|
282
|
+
// Plain text = auto-route
|
|
283
|
+
addMsg('user', cmd);
|
|
284
|
+
const latency = Math.floor(Math.random() * 120) + 35;
|
|
285
|
+
const cost = Math.random() * 0.00008;
|
|
286
|
+
const models = ['nvidia/llama-3.1-8b', 'deepseek/v4-flash'];
|
|
287
|
+
const model = Math.random() > 0.5 ? models[0] : models[1];
|
|
288
|
+
addMsg('a3m', [
|
|
289
|
+
`{dim}Auto-routed to {/}{#9ece6a-fg}${model}{/}`,
|
|
290
|
+
``,
|
|
291
|
+
`{dim}Response:{/} ${cmd}`,
|
|
292
|
+
`{dim}(Simulated — proxies to live model in production){/}`,
|
|
293
|
+
].join('\n'), model, latency, cost);
|
|
444
294
|
}
|
|
445
|
-
|
|
446
|
-
screen.render();
|
|
447
|
-
}
|
|
448
|
-
// ═══════════════════════════════════════════════════════════════
|
|
449
|
-
// RENDER ALL
|
|
450
|
-
// ═══════════════════════════════════════════════════════════════
|
|
451
|
-
function fullRender() {
|
|
452
|
-
renderTitleBar();
|
|
453
|
-
renderDashboard();
|
|
454
|
-
if (activeTab === 2)
|
|
455
|
-
renderCosts();
|
|
456
|
-
if (activeTab === 3)
|
|
457
|
-
renderProviders();
|
|
458
|
-
if (activeTab === 4)
|
|
459
|
-
renderLogs();
|
|
460
|
-
if (activeTab === 5)
|
|
461
|
-
renderHelp();
|
|
462
|
-
screen.render();
|
|
295
|
+
renderStatus();
|
|
463
296
|
}
|
|
464
297
|
// ═══════════════════════════════════════════════════════════════
|
|
465
298
|
// KEY BINDINGS
|
|
466
299
|
// ═══════════════════════════════════════════════════════════════
|
|
467
300
|
screen.key(['q', 'C-c'], () => process.exit(0));
|
|
468
|
-
screen.key(['f1'], () => switchTab(1));
|
|
469
|
-
screen.key(['f2'], () => switchTab(2));
|
|
470
|
-
screen.key(['f3'], () => switchTab(3));
|
|
471
|
-
screen.key(['f4'], () => switchTab(4));
|
|
472
|
-
screen.key(['f5'], () => switchTab(5));
|
|
473
|
-
screen.key(['f10'], () => process.exit(0));
|
|
474
|
-
screen.key(['1'], () => switchTab(1));
|
|
475
|
-
screen.key(['2'], () => switchTab(2));
|
|
476
|
-
screen.key(['3'], () => switchTab(3));
|
|
477
|
-
screen.key(['4'], () => switchTab(4));
|
|
478
|
-
screen.key(['5'], () => switchTab(5));
|
|
479
301
|
screen.key(['/'], () => {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
cmdBar.readInput();
|
|
302
|
+
inputBox.focus();
|
|
303
|
+
inputBox.setValue('/');
|
|
483
304
|
screen.render();
|
|
484
305
|
});
|
|
485
306
|
screen.key(['escape'], () => {
|
|
486
|
-
|
|
487
|
-
switchTab(1);
|
|
488
|
-
cmdBar.clearValue();
|
|
307
|
+
inputBox.cancel();
|
|
489
308
|
screen.render();
|
|
490
309
|
});
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
addLog('nvidia', 'llama-3.1-8b', Math.floor(Math.random() * 100) + 40, 200);
|
|
497
|
-
fullRender();
|
|
310
|
+
inputBox.key('enter', () => {
|
|
311
|
+
const value = inputBox.getValue().trim();
|
|
312
|
+
inputBox.clearValue();
|
|
313
|
+
inputBox.focus();
|
|
314
|
+
handleCommand(value);
|
|
498
315
|
});
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const cmd = value.trim();
|
|
502
|
-
if (cmd)
|
|
503
|
-
addLog('a3m', 'command', 0, 200);
|
|
504
|
-
if (cmd.startsWith('/route') || cmd.startsWith('/r ')) {
|
|
505
|
-
const query = cmd.replace(/^\/r(oute)?\s*/, '');
|
|
506
|
-
addLog('nvidia', 'auto-routed', Math.floor(Math.random() * 150) + 30, 200);
|
|
507
|
-
}
|
|
508
|
-
if (cmd === '/clear')
|
|
509
|
-
requestLog.length = 0;
|
|
510
|
-
if (cmd === '/cost' || cmd === 'c')
|
|
511
|
-
switchTab(2);
|
|
512
|
-
if (cmd === '/health' || cmd === 'p')
|
|
513
|
-
switchTab(3);
|
|
514
|
-
if (cmd === '/logs' || cmd === 'l')
|
|
515
|
-
switchTab(4);
|
|
516
|
-
cmdBar.clearValue();
|
|
517
|
-
fullRender();
|
|
518
|
-
});
|
|
519
|
-
// ═══════════════════════════════════════════════════════════════
|
|
520
|
-
// MOUSE SUPPORT — Click tabs
|
|
521
|
-
// ═══════════════════════════════════════════════════════════════
|
|
522
|
-
screen.on('mouse', (data) => {
|
|
523
|
-
// Mouse click on status bar triggers help
|
|
524
|
-
if (data.y === screen.height - 1)
|
|
525
|
-
switchTab(5);
|
|
316
|
+
inputBox.on('cancel', () => {
|
|
317
|
+
inputBox.clearValue();
|
|
526
318
|
});
|
|
527
319
|
// ═══════════════════════════════════════════════════════════════
|
|
528
320
|
// STARTUP
|
|
529
321
|
// ═══════════════════════════════════════════════════════════════
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
// Live tick
|
|
322
|
+
screen.append(header);
|
|
323
|
+
screen.append(chatBox);
|
|
324
|
+
screen.append(inputBox);
|
|
325
|
+
screen.append(statusBar);
|
|
326
|
+
renderChat();
|
|
327
|
+
renderStatus();
|
|
328
|
+
inputBox.focus();
|
|
329
|
+
screen.render();
|
|
330
|
+
// Periodic refresh
|
|
540
331
|
setInterval(() => {
|
|
541
332
|
tick++;
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
p.latency = Math.max(20, p.latency + (Math.random() - 0.5) * 30);
|
|
546
|
-
p.load = Math.max(0, Math.min(1, (p.load || 0) + (Math.random() - 0.5) * 0.1));
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
if (tick % 10 === 0 && tick > 0) {
|
|
551
|
-
const p = providers.filter(x => x.healthy)[Math.floor(Math.random() * 4)];
|
|
552
|
-
addLog(p.name, p.model, Math.floor(Math.random() * 120) + 30, Math.random() > 0.05 ? 200 : 500);
|
|
553
|
-
costHistory.push(Math.random() * 0.04);
|
|
554
|
-
latencyHistory.push(30 + Math.random() * 220);
|
|
555
|
-
if (costHistory.length > MAX_HISTORY)
|
|
556
|
-
costHistory.shift();
|
|
557
|
-
if (latencyHistory.length > MAX_HISTORY)
|
|
558
|
-
latencyHistory.shift();
|
|
559
|
-
}
|
|
560
|
-
fullRender();
|
|
561
|
-
}, 1000);
|
|
333
|
+
renderStatus();
|
|
334
|
+
screen.render();
|
|
335
|
+
}, 5000);
|
|
562
336
|
//# sourceMappingURL=dashboard.js.map
|