adaptive-memory-multi-model-router 2.13.0 → 2.13.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/LANDING.md +23 -26
- package/MANIFESTO.md +21 -34
- package/README.md +136 -199
- package/dist/tui/dashboard.d.ts +5 -12
- package/dist/tui/dashboard.js +470 -270
- package/dist/tui/dashboard.js.map +1 -1
- package/package.json +2 -2
- package/src/tui/dashboard.ts +502 -313
- package/tmlpd-pi-extension/README.md +29 -29
package/dist/tui/dashboard.js
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* A3M Router TUI —
|
|
4
|
+
* A3M Router TUI v2 — 10x UI
|
|
5
5
|
*
|
|
6
|
-
* Inspired by: k9s
|
|
6
|
+
* Inspired by: lazygit panels + k9s pulse + btop graphs + Tokyo Night theme
|
|
7
7
|
* Built with: blessed + blessed-contrib
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* c — Cost breakdown view
|
|
13
|
-
* p — Provider detail view
|
|
14
|
-
* l — Live request log
|
|
15
|
-
* b — Budget alerts
|
|
16
|
-
* q — Quit
|
|
17
|
-
* tab — Switch panel focus
|
|
18
|
-
* ↑↓ — Navigate lists
|
|
9
|
+
* TABS: 1-Dashboard 2-Costs 3-Providers 4-Logs 5-Help
|
|
10
|
+
* F-KEYS: F1 Dash F2 Costs F3 Prov F4 Logs F5 Help F10 Quit
|
|
11
|
+
* vim/hjkl for list nav, mouse for click targets
|
|
19
12
|
*/
|
|
20
13
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
14
|
if (k2 === undefined) k2 = k;
|
|
@@ -53,310 +46,517 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
53
46
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
47
|
const blessed = __importStar(require("blessed"));
|
|
55
48
|
const contrib = __importStar(require("blessed-contrib"));
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
{ timestamp: '10:31:42', model: 'llama-3.1-8b', provider: 'nvidia', latency: 85, tokens: 38, cost: 0, status: 200 },
|
|
77
|
-
{ timestamp: '10:30:11', model: 'llama-3.1-8b', provider: 'nvidia', latency: 92, tokens: 52, cost: 0, status: 200 },
|
|
78
|
-
{ timestamp: '10:29:03', model: 'llama3', provider: 'ollama', latency: 55, tokens: 31, cost: 0, status: 200 },
|
|
79
|
-
];
|
|
80
|
-
// ============================================================
|
|
81
|
-
// COLORS — Elegant Dark Theme
|
|
82
|
-
// ============================================================
|
|
83
|
-
const C = {
|
|
84
|
-
bg: '#0a0e14',
|
|
85
|
-
surface: '#131820',
|
|
86
|
-
border: '#253040',
|
|
87
|
-
accent: '#39bae6',
|
|
88
|
-
accent2: '#ff8f40',
|
|
89
|
-
green: '#7fd962',
|
|
90
|
-
yellow: '#ffcc66',
|
|
91
|
-
red: '#f26d78',
|
|
92
|
-
white: '#bfbab0',
|
|
93
|
-
dim: '#5c6773',
|
|
94
|
-
bright: '#e6e1cf',
|
|
95
|
-
header: '#d4bfff',
|
|
49
|
+
// ═══════════════════════════════════════════════════════════════
|
|
50
|
+
// TOKYO NIGHT THEME
|
|
51
|
+
// ═══════════════════════════════════════════════════════════════
|
|
52
|
+
const T = {
|
|
53
|
+
bg: '#1a1b26',
|
|
54
|
+
bgDark: '#16161e',
|
|
55
|
+
surface: '#24283b',
|
|
56
|
+
border: '#3b4261',
|
|
57
|
+
accent: '#7aa2f7', // blue
|
|
58
|
+
accent2: '#bb9af7', // purple
|
|
59
|
+
green: '#9ece6a',
|
|
60
|
+
yellow: '#e0af68',
|
|
61
|
+
red: '#f7768e',
|
|
62
|
+
cyan: '#7dcfff',
|
|
63
|
+
magenta: '#bb9af7',
|
|
64
|
+
orange: '#ff9e64',
|
|
65
|
+
white: '#c0caf5',
|
|
66
|
+
dim: '#565f89',
|
|
67
|
+
bright: '#a9b1d6',
|
|
68
|
+
pink: '#ff007c',
|
|
96
69
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
//
|
|
70
|
+
// ═══════════════════════════════════════════════════════════════
|
|
71
|
+
// STATE
|
|
72
|
+
// ═══════════════════════════════════════════════════════════════
|
|
73
|
+
let activeTab = 1;
|
|
74
|
+
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
|
+
// ═══════════════════════════════════════════════════════════════
|
|
82
|
+
// SCREEN
|
|
83
|
+
// ═══════════════════════════════════════════════════════════════
|
|
109
84
|
const screen = blessed.screen({
|
|
110
85
|
smartCSR: true,
|
|
111
|
-
title: 'A3M Router',
|
|
112
|
-
dockBorders: false,
|
|
86
|
+
title: 'A3M Router ⚡',
|
|
113
87
|
fullUnicode: true,
|
|
114
|
-
|
|
88
|
+
mouse: true,
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
cursor: { shape: 'line', blink: true },
|
|
115
91
|
});
|
|
116
|
-
const
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
style: { fg: C.bright, bg: C.surface },
|
|
92
|
+
const GRID = new contrib.grid({ rows: 12, cols: 24, screen });
|
|
93
|
+
// ═══════════════════════════════════════════════════════════════
|
|
94
|
+
// TITLE BAR — Tokyo Night Header
|
|
95
|
+
// ═══════════════════════════════════════════════════════════════
|
|
96
|
+
const titleBar = GRID.set(0, 0, 1, 24, blessed.box, {
|
|
97
|
+
style: { fg: T.bright, bg: T.bgDark },
|
|
123
98
|
tags: true,
|
|
124
99
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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 },
|
|
122
|
+
tags: true,
|
|
123
|
+
});
|
|
124
|
+
// --- Provider Health Bars ---
|
|
125
|
+
const providerBars = GRID.set(1, 16, 3, 8, blessed.box, {
|
|
126
|
+
label: ' ▸ Provider Health',
|
|
127
|
+
border: { type: 'line', fg: T.border },
|
|
128
|
+
style: { fg: T.white, bg: T.bg },
|
|
129
|
+
tags: true,
|
|
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, {
|
|
129
163
|
keys: true,
|
|
130
|
-
fg:
|
|
131
|
-
selectedFg:
|
|
132
|
-
selectedBg:
|
|
164
|
+
fg: T.white,
|
|
165
|
+
selectedFg: T.bright,
|
|
166
|
+
selectedBg: T.border,
|
|
133
167
|
interactive: true,
|
|
134
|
-
label: ' ▸
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
columnSpacing: 2,
|
|
139
|
-
columnWidth: [12, 14, 6, 8, 8],
|
|
168
|
+
label: ' ▸ Provider Registry',
|
|
169
|
+
border: { type: 'line', fg: T.border },
|
|
170
|
+
columnSpacing: 3,
|
|
171
|
+
columnWidth: [12, 18, 10, 10, 13, 12, 16],
|
|
140
172
|
});
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
providerTable.setData({
|
|
150
|
-
headers: ['Provider', 'Model', 'Tier', 'Status', 'Req'],
|
|
151
|
-
data: data,
|
|
152
|
-
});
|
|
153
|
-
// Color-code rows
|
|
154
|
-
const rows = providerTable.rows;
|
|
155
|
-
if (rows) {
|
|
156
|
-
providers.forEach((p, i) => {
|
|
157
|
-
if (rows[i]) {
|
|
158
|
-
const color = p.healthy ? colorScheme[p.tier] || C.white : C.red;
|
|
159
|
-
rows[i].style.fg = color;
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// ============================================================
|
|
165
|
-
// COST GAUGE (Top Right 5x4)
|
|
166
|
-
// ============================================================
|
|
167
|
-
const costGauge = grid.set(1, 4, 3, 4, contrib.gauge, {
|
|
168
|
-
label: ' ▸ Cost Tracker',
|
|
169
|
-
stroke: C.accent,
|
|
170
|
-
fill: C.accent + '20',
|
|
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 },
|
|
171
181
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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 },
|
|
176
189
|
tags: true,
|
|
177
190
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
191
|
+
// ═══════════════════════════════════════════════════════════════
|
|
192
|
+
// COMMAND BAR
|
|
193
|
+
// ═══════════════════════════════════════════════════════════════
|
|
194
|
+
const cmdBar = GRID.set(10, 0, 1, 24, blessed.textbox, {
|
|
195
|
+
label: ' ▸ /',
|
|
196
|
+
border: { type: 'line', fg: T.accent2 },
|
|
197
|
+
style: { fg: T.bright, bg: T.surface },
|
|
198
|
+
inputOnFocus: true,
|
|
199
|
+
keys: true,
|
|
200
|
+
tags: true,
|
|
201
|
+
});
|
|
202
|
+
// ═══════════════════════════════════════════════════════════════
|
|
203
|
+
// STATUS LINE
|
|
204
|
+
// ═══════════════════════════════════════════════════════════════
|
|
205
|
+
const statusLine = GRID.set(11, 0, 1, 24, blessed.box, {
|
|
206
|
+
style: { fg: T.dim, bg: T.bgDark },
|
|
207
|
+
tags: true,
|
|
208
|
+
});
|
|
209
|
+
// ═══════════════════════════════════════════════════════════════
|
|
210
|
+
// HELPER: Render a bar chart inline
|
|
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] || '░';
|
|
186
224
|
}
|
|
187
|
-
|
|
188
|
-
lines.push(`{bold}Total Requests: {/bold}${costSnapshot.requestCount}`);
|
|
189
|
-
lines.push(`{bold}Monthly: {/bold}$${Object.values(costSnapshot.monthly)[0]?.toFixed(6) || '0.00'}`);
|
|
190
|
-
costBox.setContent(lines.join('\n'));
|
|
225
|
+
return result;
|
|
191
226
|
}
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
227
|
+
// ═══════════════════════════════════════════════════════════════
|
|
228
|
+
// HELPER: Pulse animation
|
|
229
|
+
// ═══════════════════════════════════════════════════════════════
|
|
230
|
+
function pulse(frame) {
|
|
231
|
+
return Math.sin(frame * 0.3) * 0.5 + 0.5;
|
|
232
|
+
}
|
|
233
|
+
// ═══════════════════════════════════════════════════════════════
|
|
234
|
+
// RENDER: Dashboard
|
|
235
|
+
// ═══════════════════════════════════════════════════════════════
|
|
236
|
+
const providers = [
|
|
237
|
+
{ name: 'nvidia', model: 'llama-3.1-8b', tier: 'free', healthy: true, latency: 85, load: 0.4 },
|
|
238
|
+
{ name: 'deepseek', model: 'v4-flash', tier: 'mid', healthy: true, latency: 210, load: 0.2 },
|
|
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`;
|
|
272
|
+
}
|
|
273
|
+
providerBars.setContent(bars);
|
|
274
|
+
// --- LIVE FEED ---
|
|
275
|
+
if (requestLog.length === 0) {
|
|
276
|
+
for (const prov of providers.filter(p => p.healthy)) {
|
|
277
|
+
addLog(prov.name, prov.model, prov.latency, 200);
|
|
278
|
+
}
|
|
206
279
|
}
|
|
280
|
+
liveFeed.log('');
|
|
281
|
+
const feedSlice = requestLog.slice(-18).reverse();
|
|
282
|
+
for (const line of feedSlice)
|
|
283
|
+
liveFeed.log(line);
|
|
284
|
+
// --- ROUTING MAP ---
|
|
285
|
+
routeMap.setContent([
|
|
286
|
+
` {bold} ╭── Query ──╮{/}`,
|
|
287
|
+
` {bold} ▼ ▼{/}`,
|
|
288
|
+
` ┌─────────────┐ ┌──────────┐`,
|
|
289
|
+
` │ {#7aa2f7-fg}Classifier{/} │ │ {#bb9af7-fg}Semantic{/} │`,
|
|
290
|
+
` │ {#c0caf5-fg}99.5% ±1{/} │ │ {#c0caf5-fg}Cache{/} │`,
|
|
291
|
+
` └──────┬──────┘ └────┬─────┘`,
|
|
292
|
+
` └──────┬───────┘`,
|
|
293
|
+
` ▼`,
|
|
294
|
+
` ┌─────────────┐`,
|
|
295
|
+
` │ {#7dcfff-fg}UCB1 + MCTS{/} │`,
|
|
296
|
+
` │ {#c0caf5-fg}12 Signals{/} │`,
|
|
297
|
+
` └──┬───┬───┬──┘`,
|
|
298
|
+
` {#9ece6a-fg}┌─────┘{/} │ {#f7768e-fg}└─────┐{/}`,
|
|
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{/}`);
|
|
207
321
|
}
|
|
208
|
-
//
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
label: ' ▸ Routing Flow',
|
|
213
|
-
border: { type: 'line', fg: C.border },
|
|
214
|
-
style: { fg: C.white, bg: C.bg },
|
|
215
|
-
tags: true,
|
|
216
|
-
});
|
|
217
|
-
function renderRoutingFlow() {
|
|
322
|
+
// ═══════════════════════════════════════════════════════════════
|
|
323
|
+
// RENDER: Costs Tab
|
|
324
|
+
// ═══════════════════════════════════════════════════════════════
|
|
325
|
+
function renderCosts() {
|
|
218
326
|
const lines = [
|
|
219
|
-
'{
|
|
327
|
+
' {bold}{#7aa2f7-fg}╔══════════════════════════════════════╗{/}',
|
|
328
|
+
' {bold}{#7aa2f7-fg}║ COST ANALYTICS ║{/}',
|
|
329
|
+
' {bold}{#7aa2f7-fg}╚══════════════════════════════════════╝{/}',
|
|
220
330
|
'',
|
|
221
|
-
'
|
|
222
|
-
' │ Query │',
|
|
223
|
-
' └────┬─────┘',
|
|
224
|
-
' ▼',
|
|
225
|
-
' ┌─────────────┐',
|
|
226
|
-
' │ Classifier │',
|
|
227
|
-
' │ 99.5% ±1 │',
|
|
228
|
-
' └─────┬───────┘',
|
|
229
|
-
' ▼',
|
|
230
|
-
' ┌─────────────┐',
|
|
231
|
-
' │ 12 Signals │',
|
|
232
|
-
' │ UCB1 + MCTS │',
|
|
233
|
-
' └──┬──┬──┬───┘',
|
|
234
|
-
' │ │ │',
|
|
235
|
-
' {green-fg}┌──┘ {/} {yellow-fg}┌─┘ {/} {blue-fg}└─{/}',
|
|
236
|
-
' {green-fg}▼{/} {yellow-fg}▼{/} {blue-fg}▼{/}',
|
|
237
|
-
' {green-fg}Free{/} {yellow-fg}Mid{/} {blue-fg}Prem{/}',
|
|
331
|
+
' {bold}Daily Budget: {/}{#9ece6a-fg}$5.00{/} of {#565f89-fg}$150.00{/} monthly',
|
|
238
332
|
'',
|
|
239
|
-
'{
|
|
240
|
-
|
|
333
|
+
' {bold}Today: {/}',
|
|
334
|
+
` {#e0af68-fg}░░░░░░░░░░░░░░░░░░░░░░░░{/} {#565f89-fg}0.00% used{/}`,
|
|
335
|
+
'',
|
|
336
|
+
' {bold}By Provider:{/}',
|
|
241
337
|
];
|
|
242
|
-
|
|
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)}`);
|
|
350
|
+
}
|
|
351
|
+
lines.push('', ' {bold}Projected Monthly: {/}{#e0af68-fg}$0.0026{/}', ' {bold}Savings vs OpenAI: {/}{#9ece6a-fg}99.97%{/}', '', ' {bold}Free Tier Usage:{/}', ' {#9ece6a-fg}NVIDIA NIM:{/} unlimited (free)', ' {#7dcfff-fg}Groq:{/} 14,400 req/day (free)', ' {#bb9af7-fg}DeepSeek:{/} $9.46 remaining');
|
|
352
|
+
costDetail.setContent(lines.join('\n'));
|
|
243
353
|
}
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
+
});
|
|
371
|
+
}
|
|
372
|
+
// ═══════════════════════════════════════════════════════════════
|
|
373
|
+
// RENDER: Logs Tab
|
|
374
|
+
// ═══════════════════════════════════════════════════════════════
|
|
375
|
+
function renderLogs() {
|
|
376
|
+
fullLog.log('');
|
|
377
|
+
for (const line of requestLog.slice(-50))
|
|
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'));
|
|
415
|
+
}
|
|
416
|
+
// ═══════════════════════════════════════════════════════════════
|
|
417
|
+
// TABS: Show/hide panels
|
|
418
|
+
// ═══════════════════════════════════════════════════════════════
|
|
419
|
+
function switchTab(tab) {
|
|
420
|
+
activeTab = tab;
|
|
421
|
+
// Hide all
|
|
422
|
+
[latencySpark, costSpark, providerBars, liveFeed, routeMap, kpiRow,
|
|
423
|
+
costDetail, providerDetail, fullLog, helpPanel].forEach(w => w.hide());
|
|
424
|
+
// Show active
|
|
425
|
+
if (tab === 1) {
|
|
426
|
+
latencySpark.show();
|
|
427
|
+
costSpark.show();
|
|
428
|
+
providerBars.show();
|
|
429
|
+
liveFeed.show();
|
|
430
|
+
routeMap.show();
|
|
431
|
+
kpiRow.show();
|
|
432
|
+
}
|
|
433
|
+
else if (tab === 2) {
|
|
434
|
+
costDetail.show();
|
|
435
|
+
}
|
|
436
|
+
else if (tab === 3) {
|
|
437
|
+
providerDetail.show();
|
|
438
|
+
}
|
|
439
|
+
else if (tab === 4) {
|
|
440
|
+
fullLog.show();
|
|
441
|
+
}
|
|
442
|
+
else if (tab === 5) {
|
|
443
|
+
helpPanel.show();
|
|
444
|
+
}
|
|
445
|
+
renderTitleBar();
|
|
446
|
+
screen.render();
|
|
447
|
+
}
|
|
448
|
+
// ═══════════════════════════════════════════════════════════════
|
|
268
449
|
// RENDER ALL
|
|
269
|
-
//
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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();
|
|
276
462
|
screen.render();
|
|
277
463
|
}
|
|
278
|
-
//
|
|
464
|
+
// ═══════════════════════════════════════════════════════════════
|
|
279
465
|
// KEY BINDINGS
|
|
280
|
-
//
|
|
281
|
-
let activePanel = 'providers';
|
|
466
|
+
// ═══════════════════════════════════════════════════════════════
|
|
282
467
|
screen.key(['q', 'C-c'], () => process.exit(0));
|
|
283
|
-
screen.key(['
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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));
|
|
291
479
|
screen.key(['/'], () => {
|
|
292
|
-
activePanel = 'cmd';
|
|
293
480
|
cmdBar.focus();
|
|
481
|
+
cmdBar.clearValue();
|
|
294
482
|
cmdBar.readInput();
|
|
295
483
|
screen.render();
|
|
296
484
|
});
|
|
297
485
|
screen.key(['escape'], () => {
|
|
298
|
-
|
|
299
|
-
|
|
486
|
+
if (activeTab === 1)
|
|
487
|
+
switchTab(1);
|
|
300
488
|
cmdBar.clearValue();
|
|
301
489
|
screen.render();
|
|
302
490
|
});
|
|
303
|
-
screen.key(['
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
});
|
|
311
|
-
screen.key(['c'], () => {
|
|
312
|
-
const pct = Math.min((costSnapshot.total / 5) * 100, 100);
|
|
313
|
-
costGauge.setPercent(pct + 0.1);
|
|
314
|
-
renderAll();
|
|
491
|
+
screen.key(['r'], () => {
|
|
492
|
+
providers.forEach(p => {
|
|
493
|
+
if (p.healthy)
|
|
494
|
+
p.latency = Math.floor(Math.random() * 200) + 30;
|
|
495
|
+
});
|
|
496
|
+
addLog('nvidia', 'llama-3.1-8b', Math.floor(Math.random() * 100) + 40, 200);
|
|
497
|
+
fullRender();
|
|
315
498
|
});
|
|
316
|
-
//
|
|
499
|
+
// Command handler
|
|
317
500
|
cmdBar.on('submit', (value) => {
|
|
318
501
|
const cmd = value.trim();
|
|
502
|
+
if (cmd)
|
|
503
|
+
addLog('a3m', 'command', 0, 200);
|
|
319
504
|
if (cmd.startsWith('/route') || cmd.startsWith('/r ')) {
|
|
320
505
|
const query = cmd.replace(/^\/r(oute)?\s*/, '');
|
|
321
|
-
|
|
322
|
-
timestamp: new Date().toLocaleTimeString(),
|
|
323
|
-
model: 'auto',
|
|
324
|
-
provider: 'nvidia',
|
|
325
|
-
latency: Math.floor(Math.random() * 150) + 30,
|
|
326
|
-
tokens: Math.floor(Math.random() * 100),
|
|
327
|
-
cost: 0,
|
|
328
|
-
status: 200,
|
|
329
|
-
});
|
|
330
|
-
costSnapshot.requestCount++;
|
|
331
|
-
renderAll();
|
|
506
|
+
addLog('nvidia', 'auto-routed', Math.floor(Math.random() * 150) + 30, 200);
|
|
332
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);
|
|
333
516
|
cmdBar.clearValue();
|
|
334
|
-
|
|
335
|
-
|
|
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);
|
|
336
526
|
});
|
|
337
|
-
//
|
|
527
|
+
// ═══════════════════════════════════════════════════════════════
|
|
338
528
|
// STARTUP
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
529
|
+
// ═══════════════════════════════════════════════════════════════
|
|
530
|
+
switchTab(1);
|
|
531
|
+
// Initial data
|
|
532
|
+
for (let i = 0; i < 3; i++) {
|
|
533
|
+
const p = providers.filter(x => x.healthy)[Math.floor(Math.random() * 4)];
|
|
534
|
+
addLog(p.name, p.model, Math.floor(Math.random() * 100) + 40, 200);
|
|
535
|
+
costHistory.push(Math.random() * 0.03);
|
|
536
|
+
latencyHistory.push(30 + Math.random() * 200);
|
|
537
|
+
}
|
|
538
|
+
fullRender();
|
|
539
|
+
// Live tick
|
|
345
540
|
setInterval(() => {
|
|
346
|
-
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
tokens: Math.floor(Math.random() * 100),
|
|
354
|
-
cost: Math.random() * 0.0001,
|
|
355
|
-
status: Math.random() > 0.1 ? 200 : 500,
|
|
541
|
+
tick++;
|
|
542
|
+
if (tick % 15 === 0 && tick > 0) {
|
|
543
|
+
providers.forEach(p => {
|
|
544
|
+
if (p.healthy) {
|
|
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
|
+
}
|
|
356
548
|
});
|
|
357
|
-
costSnapshot.requestCount++;
|
|
358
549
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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);
|
|
362
562
|
//# sourceMappingURL=dashboard.js.map
|