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.
@@ -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
- LLM infrastructure has a dirty secret: most "solutions" solve imaginary problems while ignoring the real ones.
3
+ ---
10
4
 
11
- After building and shipping an open-source LLM router that hit 10K downloads in two weeks with zero marketing, here are the three actual problems developers told us they were trying to solve.
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
- ## Problem 1: Your LLM Bill Is 3x Higher Than It Should Be
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
- Most teams route every query to GPT-4. Not because every query needs GPT-4 because nobody has time to configure per-query routing.
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 result is predictable: monthly bills that are 3-5x higher than they need to be, with zero visibility into which team or query type is driving costs.
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
- **What we built:** A router that classifies every query by complexity (12 signals across 5 dimensions) and routes it to the cheapest capable model.
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" → cheap ($0.20/M tokens)
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
- The result: **62% cost savings**. Not theoretical — measured across 200 real API calls in our benchmark suite.
23
+ Result: **62% cost savings** measured across 200 real API calls. Not theoretical.
30
24
 
31
25
  ---
32
26
 
33
- ## Problem 2: Sequential Fallback Is a Design Flaw
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
- This is sequential fallback. It's the default. And it's wrong for three reasons:
31
+ You always get one provider's answer. Never the best across all. If A is slow, everything waits.
42
32
 
43
- 1. **You always get one provider's answer**never the best across all
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
- **What we built:** Parallel ensemble execution. Fire all providers at once. Score every result on specificity, structure, and relevance. Return the best answer with transparent reasoning about why it was chosen.
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, systemPrompt, context, {
38
+ const result = await executeEnsemble(query, context, {
51
39
  nvidia: callNvidia,
52
40
  groq: callGroq,
53
41
  openai: callOpenAI
54
42
  });
55
- console.log(`Winner: ${result.winner}`); // → nvidia (scored 75)
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 Gateway Claims "Negligible Overhead" None Publish Numbers
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
- The standard line is "negligible overhead" followed by zero data. When we started building A3M, we couldn't find a single competitor that published independent latency benchmarks for their own proxy.
50
+ It's the standard line. "Negligible overhead" followed by zero data.
68
51
 
69
- **What we did:** Ran our proxy through [llm-gateway-bench](https://github.com/taffy-owo/llm-gateway-bench) — a third-party benchmarking tool — and published every number.
52
+ We ran ours through a third-party benchmark tool (llm-gateway-bench) and published everything:
70
53
 
71
- | Scenario | TTFT | What happens |
72
- |:---------|:----:|:-------------|
73
- | Direct to Groq | **138ms** | Raw provider call |
74
- | Through A3M (forced) | **234ms** | Guardrails + cache + cost tracking |
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
- The overhead is real. It's also documented, reproducible, and pays for itself 236ms saves 62% on API costs.
59
+ 236ms overhead. Not zero. But it saves 62% on API coststhat's ~$2,600/year at 100K queries/month.
78
60
 
79
61
  ---
80
62
 
81
- ## Why Developers Switched
63
+ ## Why it grew
82
64
 
83
- The three pain points above keep coming up in the same pattern:
65
+ 10,024 downloads in 14 days. Zero marketing. Developers found it on npm, tried it, told other developers.
84
66
 
85
- 1. **"My bill is out of control"**They try the routing62% savings
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
- *Benchmark methodology: [docs/BENCHMARK.md](https://github.com/Das-rebel/a3m-router/blob/main/docs/BENCHMARK.md)*
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
- We built an open-source LLM router that solves three real problems developers keep hitting:
1
+ Three LLM infrastructure problems nobody's fixing properly:
2
2
 
3
- **Problem 1 LLM bills are 3x higher than they should be.**
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
- **Problem 2 Sequential fallback gives you one provider's answer, not the best one.**
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
- **Problem 3 Every gateway claims "negligible overhead" without publishing numbers.**
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. 47 providers. 10K downloads in 14 days.
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 shouldn't exist in 2026:
1
+ 1/7 Three LLM infrastructure problems that keep coming up:
2
2
 
3
- • Your bill is 3x higher than it should be
4
- • Sequential fallback gives you one provider's answer, not the best one
5
- • Every gateway claims "negligible overhead" without publishing numbers
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 something that fixes all three.
7
+ We built the thing that fixes all three.
8
8
 
9
- 2/7 Problem 1: Your LLM bill is 3x higher than it should be.
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
- Every query goes to GPT-4 because configuring per-query routing is a pain.
11
+ Another: "Vectorized 27K notes for $0.07. That's pretty amazing."
12
12
 
13
- A3M classifies every query by complexity (12 signals) and routes to the cheapest capable model.
13
+ Everyone's looking for cheaper options. The hard part is doing it per-query without wasting time.
14
14
 
15
- Simple Q&A free ($0)
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
- 62% cost savings.
17
+ 3/7 Every LLM "router" does: try A → fail → try B → fail → try C.
20
18
 
21
- 3/7 Problem 2: Sequential fallback is a design flaw.
19
+ You always get whatever A gave you. Nobody runs them all and picks the best.
22
20
 
23
- Every gateway does: try A fail try B fail try C.
21
+ Someone already built `ai-retry` just for the fallback part that's how common this pain is.
24
22
 
25
- You always get one provider's answer. Never the best across all.
23
+ We run all providers in parallel. Score results. Return the best answer. With reasoning why it won.
26
24
 
27
- A3M runs ALL providers in parallel, scores every result, and returns the best answer with reasoning.
25
+ 4/7 "Negligible overhead" every gateway claims this. Zero publish numbers.
28
26
 
29
- We call it parallel ensemble. No other router does this.
27
+ We ran ours through llm-gateway-bench (third-party, not our tool) and published everything.
30
28
 
31
- 4/7 Problem 3: "Negligible overhead" with zero data.
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 saves 62% on API costs. Reproducible by anyone.
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
- They told us they were hacking these solutions together manually — running prompts through multiple providers in separate browser tabs, comparing outputs by hand.
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
- We automated what they were already doing.
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
- GitHub: github.com/Das-rebel/a3m-router
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.
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * A3M Router — Terminal Overlay Box
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 {};
@@ -1,270 +1,164 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /**
4
- * A3M Router — Terminal Overlay Box
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 ansi = (n) => `\x1b[${n}m`;
11
- const R = ansi(0);
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
- function getSize() {
33
- return [process.stdout.columns || 80, process.stdout.rows || 24];
34
- }
35
- function saveCursor() { process.stdout.write('\x1b[s'); }
36
- function restoreCursor() { process.stdout.write('\x1b[u'); }
37
- function moveTo(row, col) { process.stdout.write(`\x1b[${row};${col}H`); }
38
- function clearLine() { process.stdout.write('\x1b[2K'); }
39
- function hideCursor() { process.stdout.write('\x1b[?25l'); }
40
- function showCursor() { process.stdout.write('\x1b[?25h'); }
41
- function stripAnsi(s) {
42
- return s.replace(/\x1b\[[0-9;]*m/g, '');
43
- }
44
- const B = { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' };
45
- let inputBuf = '';
46
- let cursorPos = 3;
47
- function handleInput(char) {
48
- if (char === '\r' || char === '\n') {
49
- // Submit
50
- const cmd = inputBuf.trim();
51
- processCommand(cmd);
52
- inputBuf = '';
53
- cursorPos = 3;
54
- render();
55
- }
56
- else if (char === '\x7f' || char === '\b') {
57
- // Backspace
58
- if (inputBuf.length > 0) {
59
- inputBuf = inputBuf.slice(0, -1);
60
- cursorPos = Math.max(3, cursorPos - 1);
61
- renderPromptLine();
62
- }
63
- }
64
- else if (char === '\x1b') {
65
- // Escape handled separately
66
- }
67
- else if (char >= ' ') {
68
- inputBuf += char;
69
- cursorPos++;
70
- renderPromptLine();
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 processCommand(cmd) {
74
- const c = cmd.trim();
107
+ function cmd(c) {
75
108
  if (!c)
76
109
  return;
77
- log.push(`${C.cyan + BOLD}▸${R} ${c}`);
78
- if (c === '/exit' || c === '/q' || c === ':q') {
79
- cleanup();
80
- return;
81
- }
82
- else if (c === '/help' || c === '/h') {
83
- log.push(`${C.dim} /route /cost /health /models /model <p> /clear /exit${R}`);
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(`${C.purple + BOLD}A3M${R}${C.dim} Cost breakdown:${R}`);
90
- log.push(`${C.dim} nvidia $0.000000 (free)${R}`);
91
- log.push(`${C.dim} deepseek $0.000009 ($9.46 left)${R}`);
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(`${C.purple + BOLD}A3M${R}${C.dim} Provider health:${R}`);
99
- log.push(` ${C.green}●${R} nvidia llama-3.1-8b ${C.dim}85ms free${R}`);
100
- log.push(` ${C.green}●${R} deepseek v4-flash ${C.dim}210ms mid${R}`);
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(`${C.purple + BOLD}A3M${R}${C.dim} Available (47+):${R}`);
107
- log.push(` ${C.green}● nvidia${R}(free) ${C.cyan}● groq${R}(free) ${C.yellow}● deepseek${R}(cheap)`);
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', 'google'];
135
+ const valid = ['nvidia', 'deepseek', 'groq', 'cerebras', 'mistral', 'openai', 'ollama'];
113
136
  if (valid.includes(w)) {
114
137
  activeModel = `${w}/auto`;
115
- log.push(`${C.dim} Switched to ${C.green}${activeModel}${R}`);
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(`${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}`);
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
- // Trim log if too long
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
- main();
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":";;AACA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,iDAAmC;AAEnC,QAAQ;AACR,IAAI,WAAW,GAAG,qBAAqB,CAAC;AACxC,IAAI,SAAS,GAAG,QAAQ,CAAC;AACzB,IAAI,QAAQ,GAAG,CAAC,CAAC;AACjB,MAAM,GAAG,GAAa,EAAE,CAAC;AAEzB,4CAA4C;AAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC5B,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,KAAK;IAClB,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;CACvC,CAAC,CAAC;AAEH,eAAe;AACf,MAAM,EAAE,GAAG,EAAE,CAAC;AACd,MAAM,EAAE,GAAG,EAAE,CAAC;AAEd,SAAS,OAAO,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAE,MAAM,CAAC,KAAgB,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F,SAAS,MAAM,KAAM,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAE,MAAM,CAAC,MAAiB,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5F,cAAc;AACd,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,GAAG,EAAE,MAAM,EAAE;IACb,IAAI,EAAE,OAAO,EAAE;IACf,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE;IACvC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE;IACvC,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;CAClD,CAAC,CAAC;AAEH,SAAS;AACT,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAC7B,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,CAAC;IACT,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE;IACvC,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;CACX,CAAC,CAAC;AAEH,UAAU;AACV,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;AAE/C,SAAS,MAAM;IACb,MAAM,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,GAAG,IAAI,sCAAsC,CAAC,CAAC,GAAG,CAAC,iBAAiB,WAAW,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;IACxK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,GAAG,IAAI,IAAI,CAAC;IAEZ,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,IAAI,KAAK,CAAC,CAAC,+CAA+C,CAAC,MAAM,CAAC;QACrE,GAAG,IAAI,KAAK,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;QAC/B,GAAG,IAAI,2BAA2B,CAAC,CAAC,SAAS,CAAC,2CAA2C,CAAC;QAC1F,GAAG,IAAI,mEAAmE,CAAC;QAC3E,GAAG,IAAI,iDAAiD,CAAC;QACzD,GAAG,IAAI,KAAK,CAAC,CAAC,oDAAoD,CAAC,IAAI,CAAC;IAC1E,CAAC;IAED,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,IAAI,CAAC,CAAC;QAAE,OAAO;IACf,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;IAExC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;SAClE,IAAI,CAAC,KAAK,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,sDAAsD,CAAC,EAAE,CAAC,CAAC;SAC9F,IAAI,CAAC,KAAK,QAAQ;QAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;SACnC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;QACvB,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,8DAA8D,CAAC,EAAE,CAAC,CAAC;QACnF,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,QAAQ,uBAAuB,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;SAAM,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,+HAA+H,CAAC,CAAC;QAC1I,GAAG,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC/E,CAAC;SAAM,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,qIAAqI,CAAC,CAAC;IAClJ,CAAC;SAAM,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxF,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,iBAAiB,WAAW,KAAK,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;;YACvG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;QACrC,SAAS,IAAI,IAAI,CAAC;QAAC,QAAQ,EAAE,CAAC;QAC9B,GAAG,CAAC,IAAI,CAAC,qCAAqC,WAAW,QAAQ,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClJ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE;QAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IACpC,MAAM,EAAE,CAAC;IACT,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,OAAO;AACP,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5E,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhG,QAAQ;AACR,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACnB,MAAM,EAAE,CAAC;AACT,MAAM,CAAC,KAAK,EAAE,CAAC;AACf,MAAM,CAAC,MAAM,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adaptive-memory-multi-model-router",
3
- "version": "2.13.11",
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"
@@ -1,302 +1,130 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * A3M Router — Terminal Overlay Box
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 readline from 'readline';
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 getSize(): [number, number] {
40
- return [process.stdout.columns || 80, process.stdout.rows || 24];
41
- }
42
-
43
- function saveCursor() { process.stdout.write('\x1b[s'); }
44
- function restoreCursor() { process.stdout.write('\x1b[u'); }
45
- function moveTo(row: number, col: number) { process.stdout.write(`\x1b[${row};${col}H`); }
46
- function clearLine() { process.stdout.write('\x1b[2K'); }
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
- let inputBuf = '';
57
- let cursorPos = 3;
69
+ for (const line of visible) {
70
+ out += line + '\n';
71
+ }
58
72
 
59
- function handleInput(char: string) {
60
- if (char === '\r' || char === '\n') {
61
- // Submit
62
- const cmd = inputBuf.trim();
63
- processCommand(cmd);
64
- inputBuf = '';
65
- cursorPos = 3;
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 processCommand(cmd: string) {
85
- const c = cmd.trim();
86
+ function cmd(c: string) {
86
87
  if (!c) return;
87
-
88
- log.push(`${C.cyan + BOLD}▸${R} ${c}`);
89
-
90
- if (c === '/exit' || c === '/q' || c === ':q') {
91
- cleanup();
92
- return;
93
- } else if (c === '/help' || c === '/h') {
94
- log.push(`${C.dim} /route /cost /health /models /model <p> /clear /exit${R}`);
95
- } else if (c === '/clear') {
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(`${C.purple + BOLD}A3M${R}${C.dim} Provider health:${R}`);
107
- log.push(` ${C.green}●${R} nvidia llama-3.1-8b ${C.dim}85ms free${R}`);
108
- log.push(` ${C.green}●${R} deepseek v4-flash ${C.dim}210ms mid${R}`);
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(`${C.purple + BOLD}A3M${R}${C.dim} Available (47+):${R}`);
114
- log.push(` ${C.green}● nvidia${R}(free) ${C.cyan}● groq${R}(free) ${C.yellow}● deepseek${R}(cheap)`);
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', 'google'];
119
- if (valid.includes(w)) {
120
- activeModel = `${w}/auto`;
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
- reqCount++;
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
- // Trim log if too long
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
- main();
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();