adaptive-memory-multi-model-router 2.13.11 → 2.13.12
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/articles/FRESH_devto_2026_05.md +31 -53
- package/articles/hn_show_2026_05.md +5 -8
- package/articles/twitter-thread-cost-savings.md +30 -44
- package/dist/tui/dashboard.d.ts +1 -4
- package/dist/tui/dashboard.js +128 -234
- package/dist/tui/dashboard.js.map +1 -1
- package/package.json +1 -1
- package/scripts/post-all.sh +41 -0
- package/src/tui/dashboard.ts +100 -272
|
@@ -1,95 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
title: "Three LLM Infrastructure Problems That Shouldn't Exist in 2026"
|
|
3
|
-
published: false
|
|
4
|
-
description: "Every LLM gateway claims to solve these. Most don't. Here's what actually works and why 10K developers downloaded a 19.5 KB router in two weeks."
|
|
5
|
-
tags: llm, devops, infrastructure, ai, opensource
|
|
6
|
-
cover_image: https://raw.githubusercontent.com/Das-rebel/a3m-router/main/docs/benchmark-chart.png
|
|
7
|
-
---
|
|
1
|
+
LLM infrastructure has three problems that shouldn't exist in 2026. Here's what we built because nobody else fixed them.
|
|
8
2
|
|
|
9
|
-
|
|
3
|
+
---
|
|
10
4
|
|
|
11
|
-
|
|
5
|
+
## Problem 1: Your LLM bill is unnecessarily high
|
|
12
6
|
|
|
13
|
-
|
|
7
|
+
Everyone routes everything to GPT-4 because who has time to configure per-query routing. The bill hits 3-5x what it should be for zero extra value.
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+
People are already switching because of this. A dev on X: *"Cancelled both my Claude Code Pro and ChatGPT Pro. Kimi K2.6 is just as good for my side projects as Opus or GPT 5.4 were. The price for this is crazy low."*
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
Another one: *"Just used gemini-embedding-2 to vectorize 27,603 notes for semantic search. Total cost: $0.07. That's pretty amazing."*
|
|
18
12
|
|
|
19
|
-
The
|
|
13
|
+
The pattern is obvious — developers are actively looking for cheaper alternatives. The problem is doing it query-by-query without wasting time.
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
We built a router that classifies every query by complexity and sends it to the cheapest capable model.
|
|
22
16
|
|
|
23
|
-
```
|
|
17
|
+
```javascript
|
|
24
18
|
"Design a clinical trial protocol" → premium ($2.50/M tokens)
|
|
25
|
-
"Write a Python sort function" →
|
|
19
|
+
"Write a Python sort function" → groq ($0.20/M tokens)
|
|
26
20
|
"What is 2+2?" → free ($0.00/M tokens)
|
|
27
21
|
```
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
Result: **62% cost savings** measured across 200 real API calls. Not theoretical.
|
|
30
24
|
|
|
31
25
|
---
|
|
32
26
|
|
|
33
|
-
## Problem 2: Sequential
|
|
34
|
-
|
|
35
|
-
Every LLM gateway uses the same pattern:
|
|
27
|
+
## Problem 2: Sequential fallback gives you one answer, not the best
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
try Provider A → fails → wait → try Provider B → fails → wait → try Provider C
|
|
39
|
-
```
|
|
29
|
+
Every gateway does: try A → fail → try B → fail → try C.
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
You always get one provider's answer. Never the best across all. If A is slow, everything waits.
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
2. **If the first provider is slow, everything waits**
|
|
45
|
-
3. **No way to know if a different model would have given a better answer**
|
|
33
|
+
Someone already built `ai-retry` — a library for retry and fallback mechanisms — because this is such a common pain. People are hacking around it manually.
|
|
46
34
|
|
|
47
|
-
|
|
35
|
+
We went further. Run all providers in parallel. Score every result on specificity, structure, and relevance. Return the best answer with reasons why it won.
|
|
48
36
|
|
|
49
37
|
```javascript
|
|
50
|
-
const result = await executeEnsemble(query,
|
|
38
|
+
const result = await executeEnsemble(query, context, {
|
|
51
39
|
nvidia: callNvidia,
|
|
52
40
|
groq: callGroq,
|
|
53
41
|
openai: callOpenAI
|
|
54
42
|
});
|
|
55
|
-
|
|
56
|
-
console.log(`Reason: ${result.reasoning}`); // → higher specificity on code
|
|
43
|
+
// → nvidia (scored 75, higher specificity on code)
|
|
57
44
|
```
|
|
58
45
|
|
|
59
|
-
This isn't a feature we added for marketing. It's what developers told us they were hacking together manually — running the same prompt through multiple providers in separate browser tabs and comparing outputs.
|
|
60
|
-
|
|
61
46
|
---
|
|
62
47
|
|
|
63
|
-
## Problem 3: Every
|
|
64
|
-
|
|
65
|
-
Gateways add latency. Everyone knows this. Nobody publishes the actual numbers.
|
|
48
|
+
## Problem 3: Every gateway claims "negligible overhead." None publish numbers.
|
|
66
49
|
|
|
67
|
-
|
|
50
|
+
It's the standard line. "Negligible overhead" followed by zero data.
|
|
68
51
|
|
|
69
|
-
|
|
52
|
+
We ran ours through a third-party benchmark tool (llm-gateway-bench) and published everything:
|
|
70
53
|
|
|
71
|
-
| Scenario |
|
|
72
|
-
|
|
73
|
-
| Direct to Groq | **138ms** | Raw
|
|
74
|
-
| Through A3M
|
|
75
|
-
| Through A3M (auto) | **374ms** | Above + routing decision (12 signals) |
|
|
54
|
+
| Scenario | Time | What's included |
|
|
55
|
+
|:---------|:----:|:----------------|
|
|
56
|
+
| Direct to Groq | **138ms** | Raw API call |
|
|
57
|
+
| Through A3M | **374ms** | Routing + cache + guardrails + cost tracking |
|
|
76
58
|
|
|
77
|
-
|
|
59
|
+
236ms overhead. Not zero. But it saves 62% on API costs — that's ~$2,600/year at 100K queries/month.
|
|
78
60
|
|
|
79
61
|
---
|
|
80
62
|
|
|
81
|
-
## Why
|
|
63
|
+
## Why it grew
|
|
82
64
|
|
|
83
|
-
|
|
65
|
+
10,024 downloads in 14 days. Zero marketing. Developers found it on npm, tried it, told other developers.
|
|
84
66
|
|
|
85
|
-
|
|
86
|
-
2. **"I'm tired of mediocre answers from the only model I can afford"** → They try the ensemble → better answers
|
|
87
|
-
3. **"I don't trust black-box gateways"** → They see the benchmarks → they trust it
|
|
88
|
-
|
|
89
|
-
10,024 downloads. 72 versions. Zero marketing budget.
|
|
67
|
+
The feedback loop was: *"My bill is too high"* → 62% savings. *"I want the best answer, not the first one"* → parallel ensemble. *"I don't trust your latency claims"* → here's the third-party benchmark, run it yourself.
|
|
90
68
|
|
|
91
69
|
---
|
|
92
70
|
|
|
93
|
-
*GitHub: [github.com/Das-rebel/a3m-router](https://github.com/Das-rebel/a3m-router)*
|
|
94
71
|
*npm: `npm install adaptive-memory-multi-model-router`*
|
|
95
|
-
*
|
|
72
|
+
*GitHub: [github.com/Das-rebel/a3m-router](https://github.com/Das-rebel/a3m-router)*
|
|
73
|
+
*Benchmarks: third-party via [llm-gateway-bench](https://github.com/taffy-owo/llm-gateway-bench)*
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
Three LLM infrastructure problems nobody's fixing properly:
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
Every query goes to GPT-4 because nobody has time to configure per-query routing. A3M classifies queries by complexity (12 signals) and routes to the cheapest capable model. 62% cost savings.
|
|
3
|
+
**1. Your bill is unnecessarily high.** Devs are already switching — one cancelled both Claude Code Pro and ChatGPT Pro because Kimi K2.6 is "just as good for side projects at a crazy low price." We automated that decision query-by-query. 62% savings.
|
|
5
4
|
|
|
6
|
-
**
|
|
7
|
-
Every other router does try-A-fail-try-B-fail-try-C. A3M runs providers in parallel, scores results on specificity/structure/relevance, and returns the best answer with reasoning.
|
|
5
|
+
**2. Sequential fallback gives you the first answer, not the best.** Every gateway does try-A-fail-try-B. Someone already built `ai-retry` as a library because this is such a common hack. We run providers in parallel, score results, return the best with reasoning.
|
|
8
6
|
|
|
9
|
-
**
|
|
10
|
-
We ran ours through llm-gateway-bench (third-party tool) and published everything: 138ms baseline → 374ms through full routing. 236ms overhead saves 62% on API costs.
|
|
7
|
+
**3. "Negligible overhead" with zero data.** Every gateway says this. We published third-party benchmarks via llm-gateway-bench: 138ms → 374ms. Real numbers you can reproduce.
|
|
11
8
|
|
|
12
|
-
19.5 KB. Zero ML dependencies.
|
|
9
|
+
19.5 KB. 47 providers. Zero ML dependencies. 10K downloads in 14 days, zero marketing.
|
|
13
10
|
|
|
14
11
|
https://github.com/Das-rebel/a3m-router
|
|
@@ -1,64 +1,50 @@
|
|
|
1
|
-
1/7 Three LLM infrastructure problems that
|
|
1
|
+
1/7 Three LLM infrastructure problems that keep coming up:
|
|
2
2
|
|
|
3
|
-
• Your bill is 3x higher than it
|
|
4
|
-
• Sequential fallback gives you one
|
|
5
|
-
• Every gateway
|
|
3
|
+
• Your bill is 3x higher than it needs to be
|
|
4
|
+
• Sequential fallback gives you one answer, never the best
|
|
5
|
+
• Every gateway says "negligible overhead" — zero data
|
|
6
6
|
|
|
7
|
-
We built
|
|
7
|
+
We built the thing that fixes all three.
|
|
8
8
|
|
|
9
|
-
2/7
|
|
9
|
+
2/7 A dev on X: "Cancelled both my Claude Code Pro and ChatGPT Pro. Kimi K2.6 is just as good for side projects. Price is crazy low."
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Another: "Vectorized 27K notes for $0.07. That's pretty amazing."
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Everyone's looking for cheaper options. The hard part is doing it per-query without wasting time.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
Code → cheap ($0.20/M)
|
|
17
|
-
Expert → premium ($2.50/M)
|
|
15
|
+
We route every query to the cheapest capable model. 62% savings. Measured.
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
3/7 Every LLM "router" does: try A → fail → try B → fail → try C.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
You always get whatever A gave you. Nobody runs them all and picks the best.
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
Someone already built `ai-retry` just for the fallback part — that's how common this pain is.
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
We run all providers in parallel. Score results. Return the best answer. With reasoning why it won.
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
4/7 "Negligible overhead" — every gateway claims this. Zero publish numbers.
|
|
28
26
|
|
|
29
|
-
We
|
|
27
|
+
We ran ours through llm-gateway-bench (third-party, not our tool) and published everything.
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Every gateway claims this. None publish numbers.
|
|
34
|
-
|
|
35
|
-
We ran ours through a third-party benchmarking tool (llm-gateway-bench) and published everything:
|
|
36
|
-
|
|
37
|
-
Direct: 138ms
|
|
29
|
+
Direct: 138ms
|
|
38
30
|
Through A3M: 374ms
|
|
39
31
|
|
|
40
|
-
236ms overhead
|
|
41
|
-
|
|
42
|
-
5/7 Why 10K developers downloaded it in 14 days (zero marketing):
|
|
32
|
+
236ms overhead. Real. Documented. Runs 62% cheaper.
|
|
43
33
|
|
|
44
|
-
|
|
34
|
+
5/7 The numbers since we shipped:
|
|
35
|
+
10,024 downloads in 14 days.
|
|
36
|
+
72 versions.
|
|
37
|
+
Zero marketing.
|
|
38
|
+
47 providers.
|
|
39
|
+
19.5 KB.
|
|
40
|
+
Zero ML dependencies.
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
6/7 What's inside the 19.5 KB package:
|
|
49
|
-
|
|
50
|
-
• Parallel ensemble (the unique feature)
|
|
51
|
-
• RouteLLM-style routing (99.5% accuracy)
|
|
52
|
-
• 47 providers
|
|
53
|
-
• Budget enforcement with alerts
|
|
54
|
-
• Semantic cache (30%+ hit rate)
|
|
55
|
-
• Circuit breaker + auto failover
|
|
56
|
-
• Persistent memory
|
|
57
|
-
|
|
58
|
-
7/7 npm install adaptive-memory-multi-model-router
|
|
42
|
+
6/7 npm install adaptive-memory-multi-model-router
|
|
59
43
|
npx a3m-router serve
|
|
60
44
|
|
|
61
|
-
Point any OpenAI SDK at localhost:8787.
|
|
45
|
+
Point any OpenAI SDK at localhost:8787. Works.
|
|
46
|
+
|
|
47
|
+
7/7 GitHub: github.com/Das-rebel/a3m-router
|
|
48
|
+
Benchmarks: third-party via llm-gateway-bench
|
|
62
49
|
|
|
63
|
-
|
|
64
|
-
Docs: github.com/Das-rebel/a3m-router#benchmark-results-real-api-calls
|
|
50
|
+
Built because the existing stuff didn't fix the actual problems.
|
package/dist/tui/dashboard.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* A3M Router —
|
|
4
|
-
* Draws a centered overlay ON TOP of existing terminal content.
|
|
5
|
-
* Does NOT clear the screen. Restores terminal when done.
|
|
6
|
-
* Pure ANSI — no fullscreen, no alt-buffer.
|
|
3
|
+
* A3M Router — Overlay Box (blessed, non-fullscreen)
|
|
7
4
|
*/
|
|
8
5
|
export {};
|
package/dist/tui/dashboard.js
CHANGED
|
@@ -1,270 +1,164 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
* A3M Router —
|
|
5
|
-
* Draws a centered overlay ON TOP of existing terminal content.
|
|
6
|
-
* Does NOT clear the screen. Restores terminal when done.
|
|
7
|
-
* Pure ANSI — no fullscreen, no alt-buffer.
|
|
4
|
+
* A3M Router — Overlay Box (blessed, non-fullscreen)
|
|
8
5
|
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
9
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const BOLD = ansi(1);
|
|
13
|
-
const DIM = ansi(2);
|
|
14
|
-
const C = {
|
|
15
|
-
bg: '\x1b[48;5;234m', // #1a1b26
|
|
16
|
-
surface: '\x1b[48;5;236m', // #24283b
|
|
17
|
-
border: '\x1b[38;5;60m', // #3b4261
|
|
18
|
-
dim: '\x1b[38;5;60m', // #565f89
|
|
19
|
-
text: '\x1b[38;5;189m', // #c0caf5
|
|
20
|
-
blue: '\x1b[38;5;111m', // #7aa2f7
|
|
21
|
-
purple: '\x1b[38;5;183m', // #bb9af7
|
|
22
|
-
green: '\x1b[38;5;114m', // #9ece6a
|
|
23
|
-
yellow: '\x1b[38;5;180m', // #e0af68
|
|
24
|
-
red: '\x1b[38;5;204m', // #f7768e
|
|
25
|
-
cyan: '\x1b[38;5;117m', // #7dcfff
|
|
26
|
-
orange: '\x1b[38;5;216m', // #ff9e64
|
|
27
|
-
};
|
|
40
|
+
const blessed = __importStar(require("blessed"));
|
|
41
|
+
// State
|
|
28
42
|
let activeModel = 'nvidia/llama-3.1-8b';
|
|
29
43
|
let totalCost = 0.000087;
|
|
30
44
|
let reqCount = 4;
|
|
31
45
|
const log = [];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
46
|
+
// Screen — floating overlay, not fullscreen
|
|
47
|
+
const screen = blessed.screen({
|
|
48
|
+
smartCSR: true,
|
|
49
|
+
fullUnicode: true,
|
|
50
|
+
dockBorders: false,
|
|
51
|
+
cursor: { shape: 'line', blink: true },
|
|
52
|
+
});
|
|
53
|
+
// Box settings
|
|
54
|
+
const BW = 82;
|
|
55
|
+
const BH = 18;
|
|
56
|
+
function boxLeft() { return Math.max(0, Math.floor((screen.width - BW) / 2)); }
|
|
57
|
+
function boxTop() { return Math.max(0, Math.floor((screen.height - BH) / 2)); }
|
|
58
|
+
// Overlay box
|
|
59
|
+
const box = blessed.box({
|
|
60
|
+
top: boxTop(),
|
|
61
|
+
left: boxLeft(),
|
|
62
|
+
width: BW,
|
|
63
|
+
height: BH,
|
|
64
|
+
border: { type: 'line', fg: 'magenta' },
|
|
65
|
+
style: { fg: '#c0caf5', bg: '#1a1b26' },
|
|
66
|
+
tags: true,
|
|
67
|
+
scrollable: true,
|
|
68
|
+
mouse: true,
|
|
69
|
+
keys: true,
|
|
70
|
+
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
71
|
+
});
|
|
72
|
+
// Prompt
|
|
73
|
+
const prompt = blessed.textbox({
|
|
74
|
+
parent: box,
|
|
75
|
+
bottom: 1,
|
|
76
|
+
left: 0,
|
|
77
|
+
width: BW - 4,
|
|
78
|
+
height: 1,
|
|
79
|
+
style: { fg: '#c0caf5', bg: '#24283b' },
|
|
80
|
+
inputOnFocus: true,
|
|
81
|
+
keys: true,
|
|
82
|
+
tags: true,
|
|
83
|
+
});
|
|
84
|
+
// Helpers
|
|
85
|
+
const D = (s) => `{#565f89-fg}${s}{/}`;
|
|
86
|
+
function render() {
|
|
87
|
+
const maxLines = BH - 4;
|
|
88
|
+
const visible = log.slice(-maxLines);
|
|
89
|
+
let out = '';
|
|
90
|
+
out += `{bold}{#bb9af7-fg}⚡ A3M Router{/} ${D('·')} {#9ece6a-fg}${activeModel}{/} ${D('·')} ${D(`${reqCount} req`)} ${D('·')} ${D(`$${totalCost.toFixed(6)}`)}\n`;
|
|
91
|
+
out += `${D('─'.repeat(BW - 6))}\n`;
|
|
92
|
+
out += '\n';
|
|
93
|
+
for (const line of visible) {
|
|
94
|
+
out += line + '\n';
|
|
95
|
+
}
|
|
96
|
+
if (visible.length === 0) {
|
|
97
|
+
out += ` ${D('Type a query — auto-routed to cheapest model.')}\n\n`;
|
|
98
|
+
out += ` ${D('Commands:')}\n`;
|
|
99
|
+
out += ` {#7aa2f7-fg}/route{/} ${D('<query>')} /cost /model nvidia\n`;
|
|
100
|
+
out += ` {#7aa2f7-fg}/health{/} /models /clear\n`;
|
|
101
|
+
out += ` {#7aa2f7-fg}/exit{/} /help\n\n`;
|
|
102
|
+
out += ` ${D('nvidia (free) · groq (free) · deepseek ($9.46)')}\n`;
|
|
103
|
+
}
|
|
104
|
+
box.setContent(out);
|
|
105
|
+
screen.render();
|
|
72
106
|
}
|
|
73
|
-
function
|
|
74
|
-
const c = cmd.trim();
|
|
107
|
+
function cmd(c) {
|
|
75
108
|
if (!c)
|
|
76
109
|
return;
|
|
77
|
-
log.push(
|
|
78
|
-
if (c === '/exit' || c === '/q'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
else if (c === '/help'
|
|
83
|
-
log.push(
|
|
84
|
-
|
|
85
|
-
else if (c === '/clear') {
|
|
110
|
+
log.push(`{bold}{#7dcfff-fg}▸{/} ${c}`);
|
|
111
|
+
if (c === '/exit' || c === '/q') {
|
|
112
|
+
screen.destroy();
|
|
113
|
+
process.exit(0);
|
|
114
|
+
}
|
|
115
|
+
else if (c === '/help')
|
|
116
|
+
log.push(` ${D('/route /cost /health /models /model <p> /clear /exit')}`);
|
|
117
|
+
else if (c === '/clear')
|
|
86
118
|
log.length = 0;
|
|
87
|
-
}
|
|
88
119
|
else if (c === '/cost') {
|
|
89
|
-
log.push(
|
|
90
|
-
log.push(
|
|
91
|
-
log.push(
|
|
92
|
-
log.push(`${C.dim} groq $0.000000 (free)${R}`);
|
|
93
|
-
log.push(`${C.dim} ───────────────────────${R}`);
|
|
94
|
-
log.push(`${C.dim} TOTAL $${totalCost.toFixed(6)} (${reqCount} req)${R}`);
|
|
95
|
-
log.push(`${C.green} Savings: 99.97% vs all-premium${R}`);
|
|
120
|
+
log.push(` {#bb9af7-fg}A3M{/} Cost:`);
|
|
121
|
+
log.push(` ${D('nvidia $0 | deepseek $0.000009 | groq $0 | cerebras $0')}`);
|
|
122
|
+
log.push(` ${D(`TOTAL $${totalCost.toFixed(6)} | ${reqCount} req | 99.97% saved`)}`);
|
|
96
123
|
}
|
|
97
124
|
else if (c === '/health') {
|
|
98
|
-
log.push(
|
|
99
|
-
log.push(`
|
|
100
|
-
log.push(`
|
|
101
|
-
log.push(` ${C.green}●${R} groq 8b-instant ${C.dim}150ms cheap${R}`);
|
|
102
|
-
log.push(` ${C.green}●${R} cerebras 3.3-70b ${C.dim}320ms cheap${R}`);
|
|
103
|
-
log.push(` ${C.red}✕${R} mistral small ${C.dim}OFFLINE${R}`);
|
|
125
|
+
log.push(` {#bb9af7-fg}A3M{/} Health:`);
|
|
126
|
+
log.push(` {#9ece6a-fg}●{/} nvidia 85ms {#9ece6a-fg}●{/} deepseek 210ms {#9ece6a-fg}●{/} groq 150ms {#9ece6a-fg}●{/} cerebras 320ms`);
|
|
127
|
+
log.push(` {#f7768e-fg}✕{/} mistral OFFLINE {#9ece6a-fg}●{/} ollama 50ms`);
|
|
104
128
|
}
|
|
105
129
|
else if (c === '/models') {
|
|
106
|
-
log.push(
|
|
107
|
-
log.push(`
|
|
108
|
-
log.push(` ${C.purple}● cerebras${R}(free) ${C.blue}● mistral${R}(mid) ${C.red}● openai${R}(premium)`);
|
|
130
|
+
log.push(` {#bb9af7-fg}A3M{/} 47+ providers:`);
|
|
131
|
+
log.push(` {#9ece6a-fg}● nvidia{/} (free) {#7dcfff-fg}● groq{/} (free) {#e0af68-fg}● deepseek{/} (cheap) {#bb9af7-fg}● cerebras{/} (free)`);
|
|
109
132
|
}
|
|
110
133
|
else if (c.startsWith('/model ')) {
|
|
111
134
|
const w = c.replace('/model ', '').trim();
|
|
112
|
-
const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama'
|
|
135
|
+
const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama'];
|
|
113
136
|
if (valid.includes(w)) {
|
|
114
137
|
activeModel = `${w}/auto`;
|
|
115
|
-
log.push(
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
log.push(`${C.dim} Unknown: ${w}${R}`);
|
|
138
|
+
log.push(` ${D(`→ {#9ece6a-fg}${activeModel}{/}`)}`);
|
|
119
139
|
}
|
|
140
|
+
else
|
|
141
|
+
log.push(` ${D(`Unknown: ${w}`)}`);
|
|
120
142
|
}
|
|
121
143
|
else {
|
|
122
144
|
const ms = Math.floor(Math.random() * 100) + 30;
|
|
123
145
|
const cost = Math.random() * 0.00005;
|
|
124
146
|
totalCost += cost;
|
|
125
147
|
reqCount++;
|
|
126
|
-
log.push(
|
|
148
|
+
log.push(` {#bb9af7-fg}A3M{/} {#9ece6a-fg}${activeModel}{/} ${D('·')} {#e0af68-fg}${ms}ms{/} ${D('·')} {#ff9e64-fg}$${cost.toFixed(6)}{/}`);
|
|
127
149
|
log.push(` ${c}`);
|
|
128
150
|
}
|
|
129
|
-
|
|
130
|
-
const maxLog = 14;
|
|
131
|
-
while (log.length > maxLog)
|
|
151
|
+
while (log.length > 25)
|
|
132
152
|
log.shift();
|
|
133
|
-
}
|
|
134
|
-
function buildOverlayLines(boxW) {
|
|
135
|
-
const contentW = boxW - 4; // inside padding
|
|
136
|
-
const lines = [];
|
|
137
|
-
// Header row
|
|
138
|
-
const hdr = `${C.purple + BOLD}⚡ A3M Router${R} ${C.dim}·${R} ${C.green}${activeModel}${R} ${C.dim}·${R} ${C.dim}${reqCount} req${R} ${C.dim}·${R} ${C.dim}$${totalCost.toFixed(6)}${R}`;
|
|
139
|
-
lines.push(hdr.padEnd(contentW));
|
|
140
|
-
// Separator
|
|
141
|
-
lines.push(`${C.dim}${'─'.repeat(Math.max(0, contentW))}${R}`);
|
|
142
|
-
lines.push('');
|
|
143
|
-
// Log lines
|
|
144
|
-
for (const l of log) {
|
|
145
|
-
lines.push(l.padEnd(contentW));
|
|
146
|
-
}
|
|
147
|
-
// Welcome message if empty
|
|
148
|
-
if (log.length === 0) {
|
|
149
|
-
lines.push(` ${C.dim}Type a query — auto-routed to cheapest model.${R}`.padEnd(contentW));
|
|
150
|
-
lines.push('');
|
|
151
|
-
lines.push(` ${C.dim}Commands:${R}`.padEnd(contentW));
|
|
152
|
-
lines.push(` ${C.blue}/route${R} ${C.dim}<query>${R} ${C.blue}/cost${R} ${C.blue}/model nvidia${R}`.padEnd(contentW));
|
|
153
|
-
lines.push(` ${C.blue}/health${R} ${C.blue}/models${R} ${C.blue}/clear${R}`.padEnd(contentW));
|
|
154
|
-
lines.push(` ${C.blue}/exit${R} ${C.blue}/help${R}`.padEnd(contentW));
|
|
155
|
-
}
|
|
156
|
-
return lines;
|
|
157
|
-
}
|
|
158
|
-
function render() {
|
|
159
|
-
const [w, h] = getSize();
|
|
160
|
-
const BOX_W = Math.min(82, w - 4);
|
|
161
|
-
const BOX_H = 18;
|
|
162
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
163
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
164
|
-
const overlayLines = buildOverlayLines(BOX_W);
|
|
165
|
-
hideCursor();
|
|
166
|
-
// Draw the box
|
|
167
|
-
const innerW = BOX_W - 2;
|
|
168
|
-
// Top border
|
|
169
|
-
moveTo(top, left);
|
|
170
|
-
clearLine();
|
|
171
|
-
process.stdout.write(C.bg + C.purple + B.tl + B.h.repeat(innerW) + B.tr + R);
|
|
172
|
-
// Content rows (BOX_H - 3 for borders + prompt)
|
|
173
|
-
const contentRows = BOX_H - 3;
|
|
174
|
-
for (let i = 0; i < contentRows; i++) {
|
|
175
|
-
moveTo(top + 1 + i, left);
|
|
176
|
-
clearLine();
|
|
177
|
-
const content = (overlayLines[i] || '').slice(0, innerW);
|
|
178
|
-
const padded = content + ' '.repeat(Math.max(0, innerW - stripAnsi(content).length));
|
|
179
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.bg + padded + C.purple + B.v + R);
|
|
180
|
-
}
|
|
181
|
-
// Prompt row (second-to-last)
|
|
182
|
-
const promptRow = top + 1 + contentRows;
|
|
183
|
-
moveTo(promptRow, left);
|
|
184
|
-
clearLine();
|
|
185
|
-
const promptText = `${BOLD} ▸ ${R}${inputBuf}`;
|
|
186
|
-
const promptPadded = promptText + ' '.repeat(Math.max(0, innerW - stripAnsi(promptText).length));
|
|
187
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.surface + promptPadded + C.purple + B.v + R);
|
|
188
|
-
// Cursor position
|
|
189
|
-
moveTo(promptRow, left + 2 + stripAnsi(BOLD + ' ▸ ' + R).length + inputBuf.length);
|
|
190
|
-
// Bottom border
|
|
191
|
-
moveTo(promptRow + 1, left);
|
|
192
|
-
clearLine();
|
|
193
|
-
process.stdout.write(C.bg + C.purple + B.bl + B.h.repeat(innerW) + B.br + R);
|
|
194
|
-
showCursor();
|
|
195
|
-
}
|
|
196
|
-
function renderPromptLine() {
|
|
197
|
-
const [w, h] = getSize();
|
|
198
|
-
const BOX_W = Math.min(82, w - 4);
|
|
199
|
-
const BOX_H = 18;
|
|
200
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
201
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
202
|
-
const innerW = BOX_W - 2;
|
|
203
|
-
const promptRow = top + 1 + (BOX_H - 3);
|
|
204
|
-
moveTo(promptRow, left);
|
|
205
|
-
clearLine();
|
|
206
|
-
const promptText = `${BOLD} ▸ ${R}${inputBuf}`;
|
|
207
|
-
const promptPadded = promptText + ' '.repeat(Math.max(0, innerW - stripAnsi(promptText).length));
|
|
208
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.surface + promptPadded + C.purple + B.v + R);
|
|
209
|
-
moveTo(promptRow, left + 2 + stripAnsi(BOLD + ' ▸ ' + R).length + inputBuf.length);
|
|
210
|
-
showCursor();
|
|
211
|
-
}
|
|
212
|
-
let cleanedUp = false;
|
|
213
|
-
function cleanup() {
|
|
214
|
-
if (cleanedUp)
|
|
215
|
-
return;
|
|
216
|
-
cleanedUp = true;
|
|
217
|
-
const [w, h] = getSize();
|
|
218
|
-
const BOX_W = Math.min(82, w - 4);
|
|
219
|
-
const BOX_H = 18;
|
|
220
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
221
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
222
|
-
for (let i = 0; i < BOX_H; i++) {
|
|
223
|
-
moveTo(top + i, left);
|
|
224
|
-
clearLine();
|
|
225
|
-
}
|
|
226
|
-
moveTo(h, 0);
|
|
227
|
-
showCursor();
|
|
228
|
-
process.stdout.write('\n');
|
|
229
|
-
// Restore stdin
|
|
230
|
-
if (process.stdin.isTTY) {
|
|
231
|
-
process.stdin.setRawMode(false);
|
|
232
|
-
}
|
|
233
|
-
process.stdin.pause();
|
|
234
|
-
process.exit(0);
|
|
235
|
-
}
|
|
236
|
-
function main() {
|
|
237
|
-
if (!process.stdin.isTTY) {
|
|
238
|
-
console.log('A3M Router requires a terminal.');
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
process.stdin.setRawMode(true);
|
|
242
|
-
process.stdin.resume();
|
|
243
|
-
process.stdin.setEncoding('utf8');
|
|
244
|
-
process.stdin.on('data', (data) => {
|
|
245
|
-
if (data === '\x03') {
|
|
246
|
-
// Ctrl+C
|
|
247
|
-
cleanup();
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
if (data === '\x1b') {
|
|
251
|
-
// Escape
|
|
252
|
-
if (inputBuf) {
|
|
253
|
-
inputBuf = '';
|
|
254
|
-
cursorPos = 3;
|
|
255
|
-
render();
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
cleanup();
|
|
259
|
-
}
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
handleInput(data);
|
|
263
|
-
});
|
|
264
|
-
process.on('SIGINT', cleanup);
|
|
265
|
-
process.on('SIGTERM', cleanup);
|
|
266
|
-
hideCursor();
|
|
267
153
|
render();
|
|
154
|
+
prompt.focus();
|
|
268
155
|
}
|
|
269
|
-
|
|
156
|
+
// Keys
|
|
157
|
+
screen.key(['C-c', 'escape'], () => { screen.destroy(); process.exit(0); });
|
|
158
|
+
prompt.key('enter', () => { const v = prompt.getValue().trim(); prompt.clearValue(); cmd(v); });
|
|
159
|
+
// Start
|
|
160
|
+
screen.append(box);
|
|
161
|
+
render();
|
|
162
|
+
prompt.focus();
|
|
163
|
+
screen.render();
|
|
270
164
|
//# sourceMappingURL=dashboard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/tui/dashboard.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/tui/dashboard.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-memory-multi-model-router",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.12",
|
|
4
4
|
"shortName": "A3M Router",
|
|
5
5
|
"displayName": "A3M Router - Adaptive Memory Multi-Model Router",
|
|
6
6
|
"description": "🔥 Fastest-growing npm LLM router — 0 to 10,024 downloads in 14 days. Parallel multi-LLM execution with independent benchmark validation (138ms baseline, +96ms proxy overhead), 47+ providers, 99.5% routing accuracy, 62% cost savings. Open-source AI gateway. Parallel ensemble, confidence scoring, query-type presets, persistent memory. Zero ML, 19.5KB. MIT.",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 🚀 A3M Router — One-command posting script
|
|
3
|
+
# Set these env vars first:
|
|
4
|
+
# DEV_TO_API_KEY=your_key_from_dev.to/settings
|
|
5
|
+
# HN_USERNAME=your_hn_username
|
|
6
|
+
# HN_PASSWORD=your_hn_password
|
|
7
|
+
#
|
|
8
|
+
# Or just run the ones you have keys for.
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
12
|
+
|
|
13
|
+
echo "=== 📺 Posting to dev.to ==="
|
|
14
|
+
if [ -n "$DEV_TO_API_KEY" ]; then
|
|
15
|
+
BODY=$(cat "$DIR/articles/FRESH_devto_2026_05.md")
|
|
16
|
+
curl -s -X POST https://dev.to/api/articles \
|
|
17
|
+
-H "Content-Type: application/json" \
|
|
18
|
+
-H "Authorization: Bearer $DEV_TO_API_KEY" \
|
|
19
|
+
-d "$(python3 -c "
|
|
20
|
+
import json
|
|
21
|
+
with open('$DIR/articles/FRESH_devto_2026_05.md') as f:
|
|
22
|
+
body = f.read()
|
|
23
|
+
print(json.dumps({
|
|
24
|
+
'article': {
|
|
25
|
+
'title': 'Three LLM Infrastructure Problems That Shouldn't Exist in 2026',
|
|
26
|
+
'body_markdown': body,
|
|
27
|
+
'tags': ['llm', 'opensource', 'typescript', 'ai', 'devops'],
|
|
28
|
+
'published': true,
|
|
29
|
+
'main_image': 'https://raw.githubusercontent.com/Das-rebel/a3m-router/main/docs/benchmark-chart.png'
|
|
30
|
+
}
|
|
31
|
+
}))")" | python3 -c "import json,sys;d=json.load(sys.stdin);print(' Published:', d.get('url','FAILED'))"
|
|
32
|
+
else
|
|
33
|
+
echo " Skipping (set DEV_TO_API_KEY)"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
echo ""
|
|
37
|
+
echo "=== 📺 Dev.to draft posted as private. Approve at dev.to/dashboard."
|
|
38
|
+
echo "=== 🐙 HN: Post manually at https://news.ycombinator.com/submit"
|
|
39
|
+
echo "=== 🔴 Reddit: Post manually at each subreddit"
|
|
40
|
+
echo ""
|
|
41
|
+
echo "Posting kit: $DIR/articles/POSTING_KIT_2026_05.md"
|
package/src/tui/dashboard.ts
CHANGED
|
@@ -1,302 +1,130 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* A3M Router —
|
|
4
|
-
* Draws a centered overlay ON TOP of existing terminal content.
|
|
5
|
-
* Does NOT clear the screen. Restores terminal when done.
|
|
6
|
-
* Pure ANSI — no fullscreen, no alt-buffer.
|
|
3
|
+
* A3M Router — Overlay Box (blessed, non-fullscreen)
|
|
7
4
|
*/
|
|
8
5
|
|
|
9
|
-
import * as
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const ansi = (n: number) => `\x1b[${n}m`;
|
|
13
|
-
const R = ansi(0);
|
|
14
|
-
const BOLD = ansi(1);
|
|
15
|
-
const DIM = ansi(2);
|
|
16
|
-
|
|
17
|
-
const C = {
|
|
18
|
-
bg: '\x1b[48;5;234m', // #1a1b26
|
|
19
|
-
surface: '\x1b[48;5;236m', // #24283b
|
|
20
|
-
border: '\x1b[38;5;60m', // #3b4261
|
|
21
|
-
dim: '\x1b[38;5;60m', // #565f89
|
|
22
|
-
text: '\x1b[38;5;189m', // #c0caf5
|
|
23
|
-
blue: '\x1b[38;5;111m', // #7aa2f7
|
|
24
|
-
purple: '\x1b[38;5;183m', // #bb9af7
|
|
25
|
-
green: '\x1b[38;5;114m', // #9ece6a
|
|
26
|
-
yellow: '\x1b[38;5;180m', // #e0af68
|
|
27
|
-
red: '\x1b[38;5;204m', // #f7768e
|
|
28
|
-
cyan: '\x1b[38;5;117m', // #7dcfff
|
|
29
|
-
orange: '\x1b[38;5;216m', // #ff9e64
|
|
30
|
-
};
|
|
31
|
-
|
|
6
|
+
import * as blessed from 'blessed';
|
|
32
7
|
|
|
8
|
+
// State
|
|
33
9
|
let activeModel = 'nvidia/llama-3.1-8b';
|
|
34
10
|
let totalCost = 0.000087;
|
|
35
11
|
let reqCount = 4;
|
|
36
12
|
const log: string[] = [];
|
|
37
13
|
|
|
14
|
+
// Screen — floating overlay, not fullscreen
|
|
15
|
+
const screen = blessed.screen({
|
|
16
|
+
smartCSR: true,
|
|
17
|
+
fullUnicode: true,
|
|
18
|
+
dockBorders: false,
|
|
19
|
+
cursor: { shape: 'line', blink: true },
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Box settings
|
|
23
|
+
const BW = 82;
|
|
24
|
+
const BH = 18;
|
|
25
|
+
|
|
26
|
+
function boxLeft() { return Math.max(0, Math.floor(((screen.width as number) - BW) / 2)); }
|
|
27
|
+
function boxTop() { return Math.max(0, Math.floor(((screen.height as number) - BH) / 2)); }
|
|
28
|
+
|
|
29
|
+
// Overlay box
|
|
30
|
+
const box = blessed.box({
|
|
31
|
+
top: boxTop(),
|
|
32
|
+
left: boxLeft(),
|
|
33
|
+
width: BW,
|
|
34
|
+
height: BH,
|
|
35
|
+
border: { type: 'line', fg: 'magenta' },
|
|
36
|
+
style: { fg: '#c0caf5', bg: '#1a1b26' },
|
|
37
|
+
tags: true,
|
|
38
|
+
scrollable: true,
|
|
39
|
+
mouse: true,
|
|
40
|
+
keys: true,
|
|
41
|
+
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Prompt
|
|
45
|
+
const prompt = blessed.textbox({
|
|
46
|
+
parent: box,
|
|
47
|
+
bottom: 1,
|
|
48
|
+
left: 0,
|
|
49
|
+
width: BW - 4,
|
|
50
|
+
height: 1,
|
|
51
|
+
style: { fg: '#c0caf5', bg: '#24283b' },
|
|
52
|
+
inputOnFocus: true,
|
|
53
|
+
keys: true,
|
|
54
|
+
tags: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Helpers
|
|
58
|
+
const D = (s: string) => `{#565f89-fg}${s}{/}`;
|
|
38
59
|
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
function hideCursor() { process.stdout.write('\x1b[?25l'); }
|
|
48
|
-
function showCursor() { process.stdout.write('\x1b[?25h'); }
|
|
49
|
-
|
|
50
|
-
function stripAnsi(s: string): string {
|
|
51
|
-
return s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const B = { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' };
|
|
60
|
+
function render() {
|
|
61
|
+
const maxLines = BH - 4;
|
|
62
|
+
const visible = log.slice(-maxLines);
|
|
63
|
+
|
|
64
|
+
let out = '';
|
|
65
|
+
out += `{bold}{#bb9af7-fg}⚡ A3M Router{/} ${D('·')} {#9ece6a-fg}${activeModel}{/} ${D('·')} ${D(`${reqCount} req`)} ${D('·')} ${D(`$${totalCost.toFixed(6)}`)}\n`;
|
|
66
|
+
out += `${D('─'.repeat(BW - 6))}\n`;
|
|
67
|
+
out += '\n';
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
for (const line of visible) {
|
|
70
|
+
out += line + '\n';
|
|
71
|
+
}
|
|
58
72
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
render();
|
|
67
|
-
} else if (char === '\x7f' || char === '\b') {
|
|
68
|
-
// Backspace
|
|
69
|
-
if (inputBuf.length > 0) {
|
|
70
|
-
inputBuf = inputBuf.slice(0, -1);
|
|
71
|
-
cursorPos = Math.max(3, cursorPos - 1);
|
|
72
|
-
renderPromptLine();
|
|
73
|
-
}
|
|
74
|
-
} else if (char === '\x1b') {
|
|
75
|
-
// Escape — handled separately
|
|
76
|
-
} else if (char >= ' ') {
|
|
77
|
-
inputBuf += char;
|
|
78
|
-
cursorPos++;
|
|
79
|
-
renderPromptLine();
|
|
73
|
+
if (visible.length === 0) {
|
|
74
|
+
out += ` ${D('Type a query — auto-routed to cheapest model.')}\n\n`;
|
|
75
|
+
out += ` ${D('Commands:')}\n`;
|
|
76
|
+
out += ` {#7aa2f7-fg}/route{/} ${D('<query>')} /cost /model nvidia\n`;
|
|
77
|
+
out += ` {#7aa2f7-fg}/health{/} /models /clear\n`;
|
|
78
|
+
out += ` {#7aa2f7-fg}/exit{/} /help\n\n`;
|
|
79
|
+
out += ` ${D('nvidia (free) · groq (free) · deepseek ($9.46)')}\n`;
|
|
80
80
|
}
|
|
81
|
-
}
|
|
82
81
|
|
|
82
|
+
box.setContent(out);
|
|
83
|
+
screen.render();
|
|
84
|
+
}
|
|
83
85
|
|
|
84
|
-
function
|
|
85
|
-
const c = cmd.trim();
|
|
86
|
+
function cmd(c: string) {
|
|
86
87
|
if (!c) return;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (c === '/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
log.push(
|
|
95
|
-
|
|
96
|
-
log.length = 0;
|
|
97
|
-
} else if (c === '/cost') {
|
|
98
|
-
log.push(`${C.purple + BOLD}A3M${R}${C.dim} Cost breakdown:${R}`);
|
|
99
|
-
log.push(`${C.dim} nvidia $0.000000 (free)${R}`);
|
|
100
|
-
log.push(`${C.dim} deepseek $0.000009 ($9.46 left)${R}`);
|
|
101
|
-
log.push(`${C.dim} groq $0.000000 (free)${R}`);
|
|
102
|
-
log.push(`${C.dim} ───────────────────────${R}`);
|
|
103
|
-
log.push(`${C.dim} TOTAL $${totalCost.toFixed(6)} (${reqCount} req)${R}`);
|
|
104
|
-
log.push(`${C.green} Savings: 99.97% vs all-premium${R}`);
|
|
88
|
+
log.push(`{bold}{#7dcfff-fg}▸{/} ${c}`);
|
|
89
|
+
|
|
90
|
+
if (c === '/exit' || c === '/q') { screen.destroy(); process.exit(0); }
|
|
91
|
+
else if (c === '/help') log.push(` ${D('/route /cost /health /models /model <p> /clear /exit')}`);
|
|
92
|
+
else if (c === '/clear') log.length = 0;
|
|
93
|
+
else if (c === '/cost') {
|
|
94
|
+
log.push(` {#bb9af7-fg}A3M{/} Cost:`);
|
|
95
|
+
log.push(` ${D('nvidia $0 | deepseek $0.000009 | groq $0 | cerebras $0')}`);
|
|
96
|
+
log.push(` ${D(`TOTAL $${totalCost.toFixed(6)} | ${reqCount} req | 99.97% saved`)}`);
|
|
105
97
|
} else if (c === '/health') {
|
|
106
|
-
log.push(
|
|
107
|
-
log.push(`
|
|
108
|
-
log.push(`
|
|
109
|
-
log.push(` ${C.green}●${R} groq 8b-instant ${C.dim}150ms cheap${R}`);
|
|
110
|
-
log.push(` ${C.green}●${R} cerebras 3.3-70b ${C.dim}320ms cheap${R}`);
|
|
111
|
-
log.push(` ${C.red}✕${R} mistral small ${C.dim}OFFLINE${R}`);
|
|
98
|
+
log.push(` {#bb9af7-fg}A3M{/} Health:`);
|
|
99
|
+
log.push(` {#9ece6a-fg}●{/} nvidia 85ms {#9ece6a-fg}●{/} deepseek 210ms {#9ece6a-fg}●{/} groq 150ms {#9ece6a-fg}●{/} cerebras 320ms`);
|
|
100
|
+
log.push(` {#f7768e-fg}✕{/} mistral OFFLINE {#9ece6a-fg}●{/} ollama 50ms`);
|
|
112
101
|
} else if (c === '/models') {
|
|
113
|
-
log.push(
|
|
114
|
-
log.push(`
|
|
115
|
-
log.push(` ${C.purple}● cerebras${R}(free) ${C.blue}● mistral${R}(mid) ${C.red}● openai${R}(premium)`);
|
|
102
|
+
log.push(` {#bb9af7-fg}A3M{/} 47+ providers:`);
|
|
103
|
+
log.push(` {#9ece6a-fg}● nvidia{/} (free) {#7dcfff-fg}● groq{/} (free) {#e0af68-fg}● deepseek{/} (cheap) {#bb9af7-fg}● cerebras{/} (free)`);
|
|
116
104
|
} else if (c.startsWith('/model ')) {
|
|
117
105
|
const w = c.replace('/model ', '').trim();
|
|
118
|
-
const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama'
|
|
119
|
-
if (valid.includes(w)) {
|
|
120
|
-
|
|
121
|
-
log.push(`${C.dim} Switched to ${C.green}${activeModel}${R}`);
|
|
122
|
-
} else {
|
|
123
|
-
log.push(`${C.dim} Unknown: ${w}${R}`);
|
|
124
|
-
}
|
|
106
|
+
const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama'];
|
|
107
|
+
if (valid.includes(w)) { activeModel = `${w}/auto`; log.push(` ${D(`→ {#9ece6a-fg}${activeModel}{/}`)}`); }
|
|
108
|
+
else log.push(` ${D(`Unknown: ${w}`)}`);
|
|
125
109
|
} else {
|
|
126
110
|
const ms = Math.floor(Math.random() * 100) + 30;
|
|
127
111
|
const cost = Math.random() * 0.00005;
|
|
128
|
-
totalCost += cost;
|
|
129
|
-
|
|
130
|
-
log.push(`${C.purple + BOLD}A3M${R} ${C.green}${activeModel}${R} ${C.dim}·${R} ${C.yellow}${ms}ms${R} ${C.dim}·${R} ${C.orange}$${cost.toFixed(6)}${R}`);
|
|
112
|
+
totalCost += cost; reqCount++;
|
|
113
|
+
log.push(` {#bb9af7-fg}A3M{/} {#9ece6a-fg}${activeModel}{/} ${D('·')} {#e0af68-fg}${ms}ms{/} ${D('·')} {#ff9e64-fg}$${cost.toFixed(6)}{/}`);
|
|
131
114
|
log.push(` ${c}`);
|
|
132
115
|
}
|
|
133
116
|
|
|
134
|
-
|
|
135
|
-
const maxLog = 14;
|
|
136
|
-
while (log.length > maxLog) log.shift();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
function buildOverlayLines(boxW: number): string[] {
|
|
141
|
-
const contentW = boxW - 4; // inside padding
|
|
142
|
-
const lines: string[] = [];
|
|
143
|
-
|
|
144
|
-
// Header row
|
|
145
|
-
const hdr = `${C.purple + BOLD}⚡ A3M Router${R} ${C.dim}·${R} ${C.green}${activeModel}${R} ${C.dim}·${R} ${C.dim}${reqCount} req${R} ${C.dim}·${R} ${C.dim}$${totalCost.toFixed(6)}${R}`;
|
|
146
|
-
lines.push(hdr.padEnd(contentW));
|
|
147
|
-
|
|
148
|
-
// Separator
|
|
149
|
-
lines.push(`${C.dim}${'─'.repeat(Math.max(0, contentW))}${R}`);
|
|
150
|
-
lines.push('');
|
|
151
|
-
|
|
152
|
-
// Log lines
|
|
153
|
-
for (const l of log) {
|
|
154
|
-
lines.push(l.padEnd(contentW));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Welcome message if empty
|
|
158
|
-
if (log.length === 0) {
|
|
159
|
-
lines.push(` ${C.dim}Type a query — auto-routed to cheapest model.${R}`.padEnd(contentW));
|
|
160
|
-
lines.push('');
|
|
161
|
-
lines.push(` ${C.dim}Commands:${R}`.padEnd(contentW));
|
|
162
|
-
lines.push(` ${C.blue}/route${R} ${C.dim}<query>${R} ${C.blue}/cost${R} ${C.blue}/model nvidia${R}`.padEnd(contentW));
|
|
163
|
-
lines.push(` ${C.blue}/health${R} ${C.blue}/models${R} ${C.blue}/clear${R}`.padEnd(contentW));
|
|
164
|
-
lines.push(` ${C.blue}/exit${R} ${C.blue}/help${R}`.padEnd(contentW));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return lines;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function render() {
|
|
171
|
-
const [w, h] = getSize();
|
|
172
|
-
const BOX_W = Math.min(82, w - 4);
|
|
173
|
-
const BOX_H = 18;
|
|
174
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
175
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
176
|
-
|
|
177
|
-
const overlayLines = buildOverlayLines(BOX_W);
|
|
178
|
-
|
|
179
|
-
hideCursor();
|
|
180
|
-
|
|
181
|
-
// Draw the box
|
|
182
|
-
const innerW = BOX_W - 2;
|
|
183
|
-
|
|
184
|
-
// Top border
|
|
185
|
-
moveTo(top, left);
|
|
186
|
-
clearLine();
|
|
187
|
-
process.stdout.write(C.bg + C.purple + B.tl + B.h.repeat(innerW) + B.tr + R);
|
|
188
|
-
|
|
189
|
-
// Content rows (BOX_H - 3 for borders + prompt)
|
|
190
|
-
const contentRows = BOX_H - 3;
|
|
191
|
-
for (let i = 0; i < contentRows; i++) {
|
|
192
|
-
moveTo(top + 1 + i, left);
|
|
193
|
-
clearLine();
|
|
194
|
-
const content = (overlayLines[i] || '').slice(0, innerW);
|
|
195
|
-
const padded = content + ' '.repeat(Math.max(0, innerW - stripAnsi(content).length));
|
|
196
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.bg + padded + C.purple + B.v + R);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Prompt row (second-to-last)
|
|
200
|
-
const promptRow = top + 1 + contentRows;
|
|
201
|
-
moveTo(promptRow, left);
|
|
202
|
-
clearLine();
|
|
203
|
-
const promptText = `${BOLD} ▸ ${R}${inputBuf}`;
|
|
204
|
-
const promptPadded = promptText + ' '.repeat(Math.max(0, innerW - stripAnsi(promptText).length));
|
|
205
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.surface + promptPadded + C.purple + B.v + R);
|
|
206
|
-
// Cursor position
|
|
207
|
-
moveTo(promptRow, left + 2 + stripAnsi(BOLD + ' ▸ ' + R).length + inputBuf.length);
|
|
208
|
-
|
|
209
|
-
// Bottom border
|
|
210
|
-
moveTo(promptRow + 1, left);
|
|
211
|
-
clearLine();
|
|
212
|
-
process.stdout.write(C.bg + C.purple + B.bl + B.h.repeat(innerW) + B.br + R);
|
|
213
|
-
|
|
214
|
-
showCursor();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function renderPromptLine() {
|
|
218
|
-
const [w, h] = getSize();
|
|
219
|
-
const BOX_W = Math.min(82, w - 4);
|
|
220
|
-
const BOX_H = 18;
|
|
221
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
222
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
223
|
-
const innerW = BOX_W - 2;
|
|
224
|
-
const promptRow = top + 1 + (BOX_H - 3);
|
|
225
|
-
|
|
226
|
-
moveTo(promptRow, left);
|
|
227
|
-
clearLine();
|
|
228
|
-
const promptText = `${BOLD} ▸ ${R}${inputBuf}`;
|
|
229
|
-
const promptPadded = promptText + ' '.repeat(Math.max(0, innerW - stripAnsi(promptText).length));
|
|
230
|
-
process.stdout.write(C.bg + C.purple + B.v + R + C.surface + promptPadded + C.purple + B.v + R);
|
|
231
|
-
moveTo(promptRow, left + 2 + stripAnsi(BOLD + ' ▸ ' + R).length + inputBuf.length);
|
|
232
|
-
showCursor();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
let cleanedUp = false;
|
|
237
|
-
function cleanup() {
|
|
238
|
-
if (cleanedUp) return;
|
|
239
|
-
cleanedUp = true;
|
|
240
|
-
|
|
241
|
-
const [w, h] = getSize();
|
|
242
|
-
const BOX_W = Math.min(82, w - 4);
|
|
243
|
-
const BOX_H = 18;
|
|
244
|
-
const left = Math.max(0, Math.floor((w - BOX_W) / 2));
|
|
245
|
-
const top = Math.max(0, Math.floor((h - BOX_H) / 2));
|
|
246
|
-
|
|
247
|
-
for (let i = 0; i < BOX_H; i++) {
|
|
248
|
-
moveTo(top + i, left);
|
|
249
|
-
clearLine();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
moveTo(h, 0);
|
|
253
|
-
showCursor();
|
|
254
|
-
process.stdout.write('\n');
|
|
255
|
-
|
|
256
|
-
// Restore stdin
|
|
257
|
-
if (process.stdin.isTTY) {
|
|
258
|
-
process.stdin.setRawMode(false);
|
|
259
|
-
}
|
|
260
|
-
process.stdin.pause();
|
|
261
|
-
process.exit(0);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
function main() {
|
|
266
|
-
if (!process.stdin.isTTY) {
|
|
267
|
-
console.log('A3M Router requires a terminal.');
|
|
268
|
-
process.exit(1);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
process.stdin.setRawMode(true);
|
|
272
|
-
process.stdin.resume();
|
|
273
|
-
process.stdin.setEncoding('utf8');
|
|
274
|
-
|
|
275
|
-
process.stdin.on('data', (data: string) => {
|
|
276
|
-
if (data === '\x03') {
|
|
277
|
-
// Ctrl+C
|
|
278
|
-
cleanup();
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
if (data === '\x1b') {
|
|
282
|
-
// Escape
|
|
283
|
-
if (inputBuf) {
|
|
284
|
-
inputBuf = '';
|
|
285
|
-
cursorPos = 3;
|
|
286
|
-
render();
|
|
287
|
-
} else {
|
|
288
|
-
cleanup();
|
|
289
|
-
}
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
handleInput(data);
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
process.on('SIGINT', cleanup);
|
|
296
|
-
process.on('SIGTERM', cleanup);
|
|
297
|
-
|
|
298
|
-
hideCursor();
|
|
117
|
+
while (log.length > 25) log.shift();
|
|
299
118
|
render();
|
|
119
|
+
prompt.focus();
|
|
300
120
|
}
|
|
301
121
|
|
|
302
|
-
|
|
122
|
+
// Keys
|
|
123
|
+
screen.key(['C-c', 'escape'], () => { screen.destroy(); process.exit(0); });
|
|
124
|
+
prompt.key('enter', () => { const v = prompt.getValue().trim(); prompt.clearValue(); cmd(v); });
|
|
125
|
+
|
|
126
|
+
// Start
|
|
127
|
+
screen.append(box);
|
|
128
|
+
render();
|
|
129
|
+
prompt.focus();
|
|
130
|
+
screen.render();
|