adaptive-memory-multi-model-router 2.0.5 → 2.0.7

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/README.md CHANGED
@@ -165,17 +165,32 @@ Track every request. Export savings reports. Set daily budget limits.
165
165
 
166
166
  ## Comparison
167
167
 
168
- | Feature | A3M Router | Portkey | LiteLLM |
169
- |---------|:----------:|:-------:|:-------:|
170
- | OpenAI-compatible proxy | | | |
171
- | Intelligent routing | ✅ | ✅ | ✅ |
172
- | Real-time dashboard | | | |
173
- | LangChain adapter | | | |
174
- | Guardrails built-in | | | |
175
- | Semantic cache | | | |
176
- | Adaptive memory | ✅ | | ❌ |
177
- | **Price** | **Free** | **Paid tiers** | **Free** |
178
- | **Setup** | **30 seconds** | **Account required** | **Library only** |
168
+ > **How we stack up against the ecosystem.** We're the new kid — [LiteLLM](https://github.com/BerriAI/litellm) (47K ⭐) and [Portkey](https://github.com/Portkey-AI/gateway) (12K ⭐) are more mature. We differentiate on adaptive memory, zero-config proxy, and cost guardrails.
169
+
170
+ | Feature | A3M Router | [LiteLLM](https://github.com/BerriAI/litellm) | [Portkey](https://github.com/Portkey-AI/gateway) | [RouteLLM](https://github.com/lm-sys/RouteLLM) | [OpenRouter](https://openrouter.ai) |
171
+ |---------|:----------:|:-------:|:-------:|:-------:|:-------:|
172
+ | **GitHub Stars** | 0 (3 days old) | 47.4K | 11.8K | 4.9K | API only |
173
+ | **Language** | Node.js + Python | Python | TypeScript | Python | API only |
174
+ | **License** | MIT | Custom | MIT | Apache 2.0 | Proprietary |
175
+ | **Providers** | 40 | 100+ | 1,600+ | Custom endpoints | 200+ |
176
+ | **Self-hosted** | | ✅ | | ✅ | ❌ |
177
+ | OpenAI proxy | | | | | ✅ |
178
+ | Cost routing | | | | | |
179
+ | **Adaptive memory** | ✅ | ❌ | ❌ | ❌ | ❌ |
180
+ | **Cost guardrails** | ✅ | ✅ | ❌ | ❌ | ❌ |
181
+ | Semantic cache | ✅ | ✅ | ✅ | ❌ | ❌ |
182
+ | Guardrails | ✅ | ✅ | ✅ (50+) | ❌ | ❌ |
183
+ | Dashboard | ✅ | ✅ | ✅ | ❌ | ✅ |
184
+ | **Zero config** | ✅ | ❌ | ❌ | ❌ | ❌ |
185
+ | **Price** | **Free** | **Free + Paid** | **Free + Paid** | **Free** | **Usage-based** |
186
+
187
+ ### Other projects worth watching
188
+
189
+ - [9router](https://github.com/decolua/9router) (12K ⭐) — Free AI coding router for Claude Code / Cursor / Copilot
190
+ - [ClawRouter](https://github.com/BlockRunAI/ClawRouter) (6.5K ⭐) — Agent-native LLM router with USDC payments
191
+ - [Plano](https://github.com/katanemo/plano) (6.5K ⭐) — AI-native proxy in Rust, built-in orchestration
192
+ - [Helicone](https://github.com/Helicone/helicone) (5.7K ⭐) — LLM observability platform (logging/analytics)
193
+ - [semantic-router](https://github.com/vllm-project/semantic-router) (4.2K ⭐) — System-level router for MoM at datacenter scale
179
194
 
180
195
  ---
181
196
 
@@ -190,9 +205,35 @@ Track every request. Export savings reports. Set daily budget limits.
190
205
 
191
206
  ## Benchmarks
192
207
 
193
- Run your own:
208
+ > Routing accuracy benchmark (RouteLLM methodology). 200 queries across 4 difficulty tiers.
209
+
210
+ ```
211
+ ╔═══════════════════════════════════════════════════════════╗
212
+ ║ A3M Router — Classification Benchmark Results ║
213
+ ╚═══════════════════════════════════════════════════════════╝
214
+
215
+ Queries: 200 (50 simple, 60 medium, 50 complex, 40 expert)
216
+ Exact tier match: 24.0%
217
+ ±1 Tier accuracy: 82.5% ← the meaningful metric
218
+ Cost savings vs premium: 63.7%
219
+ Over-routing (wasteful): 36.5%
220
+ Under-routing (risky): 39.5%
221
+
222
+ Confusion Matrix:
223
+ → free → cheap → mid → premium
224
+ simple 0 46 4 0
225
+ medium 0 39✓ 20 1
226
+ complex 0 42 6✓ 2
227
+ expert 0 30 7 3✓
228
+ ```
229
+
230
+ **Honest assessment:** The classifier correctly identifies simple queries for cheap/free routing (92% land in free/cheap). Expert queries are the weakest — most get routed to cheap/mid instead of premium. The adaptive memory feature improves this over time by learning from circuit breaker feedback.
231
+
232
+ For comparison, [RouteLLM](https://github.com/lm-sys/RouteLLM) reports ~85% routing accuracy on their benchmark with a BERT-based classifier (ours is keyword-based). We accept the lower accuracy for zero-dependency, instant routing.
233
+
234
+ Run the benchmark yourself:
194
235
  ```bash
195
- bash scripts/benchmark.sh
236
+ node scripts/routing-benchmark-v2.js
196
237
  ```
197
238
 
198
239
  ---
@@ -1,14 +1,46 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 640" width="1280" height="640">
2
2
  <defs>
3
- <linearGradient id="spBg" x1="0%" y1="0%" x2="100%" y2="100%">
4
- <stop offset="0%" style="stop-color:#0f172a"/>
5
- <stop offset="100%" style="stop-color:#1e1b4b"/>
3
+ <!-- Background gradient -->
4
+ <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" style="stop-color:#0d1117"/>
6
+ <stop offset="50%" style="stop-color:#111820"/>
7
+ <stop offset="100%" style="stop-color:#0d1117"/>
6
8
  </linearGradient>
7
- <linearGradient id="spAccent" x1="0%" y1="0%" x2="100%" y2="0%">
8
- <stop offset="0%" style="stop-color:#6366f1"/>
9
- <stop offset="100%" style="stop-color:#06b6d4"/>
9
+ <!-- Green accent gradient -->
10
+ <linearGradient id="greenGrad" x1="0%" y1="0%" x2="100%" y2="0%">
11
+ <stop offset="0%" style="stop-color:#238636"/>
12
+ <stop offset="100%" style="stop-color:#2ea043"/>
10
13
  </linearGradient>
11
- <filter id="spGlow">
14
+ <!-- Blue accent gradient -->
15
+ <linearGradient id="blueGrad" x1="0%" y1="0%" x2="100%" y2="0%">
16
+ <stop offset="0%" style="stop-color:#1f6feb"/>
17
+ <stop offset="100%" style="stop-color:#58a6ff"/>
18
+ </linearGradient>
19
+ <!-- Purple accent gradient -->
20
+ <linearGradient id="purpleGrad" x1="0%" y1="0%" x2="100%" y2="0%">
21
+ <stop offset="0%" style="stop-color:#8b5cf6"/>
22
+ <stop offset="100%" style="stop-color:#a78bfa"/>
23
+ </linearGradient>
24
+ <!-- Title gradient -->
25
+ <linearGradient id="titleGrad" x1="0%" y1="0%" x2="100%" y2="0%">
26
+ <stop offset="0%" style="stop-color:#58a6ff"/>
27
+ <stop offset="40%" style="stop-color:#a78bfa"/>
28
+ <stop offset="100%" style="stop-color:#2ea043"/>
29
+ </linearGradient>
30
+ <!-- Glow filter -->
31
+ <filter id="glow">
32
+ <feGaussianBlur stdDeviation="3" result="blur"/>
33
+ <feMerge>
34
+ <feMergeNode in="blur"/>
35
+ <feMergeNode in="SourceGraphic"/>
36
+ </feMerge>
37
+ </filter>
38
+ <!-- Subtle shadow for cards -->
39
+ <filter id="cardShadow" x="-5%" y="-5%" width="110%" height="115%">
40
+ <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000000" flood-opacity="0.3"/>
41
+ </filter>
42
+ <!-- Emoji glow -->
43
+ <filter id="emojiGlow" x="-20%" y="-20%" width="140%" height="140%">
12
44
  <feGaussianBlur stdDeviation="6" result="blur"/>
13
45
  <feMerge>
14
46
  <feMergeNode in="blur"/>
@@ -16,49 +48,147 @@
16
48
  </feMerge>
17
49
  </filter>
18
50
  </defs>
19
-
51
+
20
52
  <!-- Background -->
21
- <rect width="1280" height="640" fill="url(#spBg)"/>
22
-
23
- <!-- Grid Pattern -->
24
- <pattern id="spGrid" width="60" height="60" patternUnits="userSpaceOnUse">
25
- <path d="M 60 0 L 0 0 0 60" fill="none" stroke="rgba(99,102,241,0.08)" stroke-width="1"/>
26
- </pattern>
27
- <rect width="1280" height="640" fill="url(#spGrid)"/>
28
-
29
- <!-- Central Logo -->
30
- <g transform="translate(640, 280)">
31
- <!-- Outer Rings -->
32
- <circle cx="0" cy="0" r="180" fill="none" stroke="url(#spAccent)" stroke-width="2" opacity="0.2"/>
33
- <circle cx="0" cy="0" r="150" fill="none" stroke="url(#spAccent)" stroke-width="1" opacity="0.15" stroke-dasharray="10 5"/>
34
-
35
- <!-- Main Circle -->
36
- <circle cx="0" cy="0" r="80" fill="url(#spAccent)" opacity="0.1"/>
37
- <circle cx="0" cy="0" r="60" fill="url(#spAccent)" filter="url(#spGlow)"/>
38
-
39
- <!-- Orbiting Dots -->
40
- <circle cx="0" cy="-120" r="15" fill="#6366f1"/>
41
- <circle cx="104" cy="60" r="12" fill="#10b981"/>
42
- <circle cx="-104" cy="60" r="12" fill="#f59e0b"/>
43
-
44
- <!-- Connection Lines -->
45
- <line x1="0" y1="0" x2="0" y2="-120" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
46
- <line x1="0" y1="0" x2="104" y2="60" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
47
- <line x1="0" y1="0" x2="-104" y2="60" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
48
-
49
- <!-- Text -->
50
- <text x="0" y="20" font-family="system-ui, -apple-system, sans-serif" font-size="48" font-weight="bold" fill="white" text-anchor="middle">A3M</text>
53
+ <rect width="1280" height="640" fill="url(#bgGrad)" rx="0"/>
54
+
55
+ <!-- Subtle grid pattern -->
56
+ <g opacity="0.03">
57
+ <line x1="0" y1="0" x2="1280" y2="640" stroke="#58a6ff" stroke-width="1"/>
58
+ <line x1="1280" y1="0" x2="0" y2="640" stroke="#58a6ff" stroke-width="1"/>
59
+ <line x1="640" y1="0" x2="640" y2="640" stroke="#58a6ff" stroke-width="0.5"/>
60
+ <line x1="0" y1="320" x2="1280" y2="320" stroke="#58a6ff" stroke-width="0.5"/>
61
+ <circle cx="640" cy="320" r="200" fill="none" stroke="#58a6ff" stroke-width="0.5"/>
62
+ <circle cx="640" cy="320" r="350" fill="none" stroke="#58a6ff" stroke-width="0.5"/>
51
63
  </g>
52
-
53
- <!-- Title -->
54
- <text x="640" y="520" font-family="system-ui, -apple-system, sans-serif" font-size="56" font-weight="bold" fill="white" text-anchor="middle">A3M Router</text>
55
-
64
+
65
+ <!-- Decorative accent lines -->
66
+ <rect x="0" y="0" width="6" height="640" fill="url(#titleGrad)" opacity="0.8"/>
67
+ <rect x="1274" y="0" width="6" height="640" fill="url(#titleGrad)" opacity="0.4"/>
68
+
69
+ <!-- Top decorative bar -->
70
+ <rect x="80" y="28" width="1120" height="2" fill="url(#titleGrad)" opacity="0.3" rx="1"/>
71
+
72
+ <!-- Emoji shuffle icon -->
73
+ <text x="120" y="130" font-size="72" filter="url(#emojiGlow)" opacity="0.9">🔀</text>
74
+
75
+ <!-- Main title -->
76
+ <text x="200" y="122" font-family="'SF Pro Display', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="72" font-weight="800" fill="url(#titleGrad)" filter="url(#glow)">
77
+ A3M Router
78
+ </text>
79
+
56
80
  <!-- Subtitle -->
57
- <text x="640" y="580" font-family="system-ui, -apple-system, sans-serif" font-size="28" fill="#94a3b8" text-anchor="middle">Adaptive Memory Multi-Model Router</text>
58
-
59
- <!-- NPM Badge -->
60
- <g transform="translate(640, 620)">
61
- <rect x="-120" y="-15" width="240" height="30" rx="15" fill="rgba(255,255,255,0.1)"/>
62
- <text x="0" y="5" font-family="system-ui, -apple-system, sans-serif" font-size="14" fill="#cbd5e1" text-anchor="middle">872+ Weekly Downloads on NPM</text>
81
+ <text x="120" y="170" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="24" fill="#8b949e" font-weight="400">
82
+ Drop-in OpenAI proxy · 39 providers · 245% growth in 3 days
83
+ </text>
84
+
85
+ <!-- Stat cards row -->
86
+ <!-- Card 1: Downloads -->
87
+ <g filter="url(#cardShadow)">
88
+ <rect x="120" y="210" width="320" height="160" rx="16" fill="#161b22" stroke="#238636" stroke-width="2" opacity="0.95"/>
89
+ <rect x="120" y="210" width="320" height="4" rx="2" fill="url(#greenGrad)"/>
90
+ <text x="280" y="268" font-family="'SF Mono', 'Fira Code', 'Consolas', monospace" font-size="52" font-weight="800" fill="#2ea043" text-anchor="middle">
91
+ 2,775
92
+ </text>
93
+ <text x="280" y="305" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="16" fill="#8b949e" text-anchor="middle" font-weight="500">
94
+ npm downloads
95
+ </text>
96
+ <text x="280" y="340" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="13" fill="#484f58" text-anchor="middle">
97
+ in first 3 days
98
+ </text>
99
+ </g>
100
+
101
+ <!-- Card 2: Growth -->
102
+ <g filter="url(#cardShadow)">
103
+ <rect x="480" y="210" width="320" height="160" rx="16" fill="#161b22" stroke="#1f6feb" stroke-width="2" opacity="0.95"/>
104
+ <rect x="480" y="210" width="320" height="4" rx="2" fill="url(#blueGrad)"/>
105
+ <text x="640" y="268" font-family="'SF Mono', 'Fira Code', 'Consolas', monospace" font-size="52" font-weight="800" fill="#58a6ff" text-anchor="middle">
106
+ 245%
107
+ </text>
108
+ <text x="640" y="305" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="16" fill="#8b949e" text-anchor="middle" font-weight="500">
109
+ day-over-day growth
110
+ </text>
111
+ <text x="640" y="340" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="13" fill="#484f58" text-anchor="middle">
112
+ organic, no marketing
113
+ </text>
114
+ </g>
115
+
116
+ <!-- Card 3: Budget -->
117
+ <g filter="url(#cardShadow)">
118
+ <rect x="840" y="210" width="320" height="160" rx="16" fill="#161b22" stroke="#8b5cf6" stroke-width="2" opacity="0.95"/>
119
+ <rect x="840" y="210" width="320" height="4" rx="2" fill="url(#purpleGrad)"/>
120
+ <text x="1000" y="268" font-family="'SF Mono', 'Fira Code', 'Consolas', monospace" font-size="52" font-weight="800" fill="#a78bfa" text-anchor="middle">
121
+ $0
122
+ </text>
123
+ <text x="1000" y="305" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="16" fill="#8b949e" text-anchor="middle" font-weight="500">
124
+ marketing budget
125
+ </text>
126
+ <text x="1000" y="340" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="13" fill="#484f58" text-anchor="middle">
127
+ 100% community driven
128
+ </text>
129
+ </g>
130
+
131
+ <!-- Provider logos row -->
132
+ <g transform="translate(0, 420)">
133
+ <text x="640" y="10" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" fill="#484f58" text-anchor="middle" letter-spacing="3" font-weight="600">
134
+ SUPPORTED PROVIDERS
135
+ </text>
136
+
137
+ <!-- Provider pills -->
138
+ <!-- OpenAI -->
139
+ <rect x="68" y="26" width="130" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
140
+ <circle cx="95" cy="45" r="8" fill="#10a37f"/>
141
+ <text x="108" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">OpenAI</text>
142
+
143
+ <!-- Anthropic -->
144
+ <rect x="218" y="26" width="140" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
145
+ <circle cx="248" cy="45" r="8" fill="#d4a574"/>
146
+ <text x="262" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">Anthropic</text>
147
+
148
+ <!-- Groq -->
149
+ <rect x="378" y="26" width="110" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
150
+ <circle cx="405" cy="45" r="8" fill="#f55036"/>
151
+ <text x="418" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">Groq</text>
152
+
153
+ <!-- Cerebras -->
154
+ <rect x="508" y="26" width="130" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
155
+ <circle cx="538" cy="45" r="8" fill="#7c3aed"/>
156
+ <text x="552" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">Cerebras</text>
157
+
158
+ <!-- Mistral -->
159
+ <rect x="658" y="26" width="120" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
160
+ <circle cx="685" cy="45" r="8" fill="#ff7000"/>
161
+ <text x="698" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">Mistral</text>
162
+
163
+ <!-- DeepSeek -->
164
+ <rect x="798" y="26" width="140" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
165
+ <circle cx="828" cy="45" r="8" fill="#4d6bfe"/>
166
+ <text x="842" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">DeepSeek</text>
167
+
168
+ <!-- Ollama -->
169
+ <rect x="958" y="26" width="120" height="38" rx="19" fill="#1a1f27" stroke="#30363d" stroke-width="1"/>
170
+ <circle cx="985" cy="45" r="8" fill="#6366f1"/>
171
+ <text x="998" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="14" fill="#c9d1d9" font-weight="600">Ollama</text>
172
+
173
+ <!-- +32 more -->
174
+ <rect x="1098" y="26" width="110" height="38" rx="19" fill="none" stroke="#30363d" stroke-width="1" stroke-dasharray="4 3"/>
175
+ <text x="1153" y="51" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="13" fill="#484f58" text-anchor="middle" font-weight="500">+32 more</text>
63
176
  </g>
177
+
178
+ <!-- Bottom bar -->
179
+ <rect x="80" y="530" width="1120" height="1" fill="#21262d" rx="0.5"/>
180
+
181
+ <!-- Bottom tagline -->
182
+ <text x="640" y="570" font-family="'SF Mono', 'Fira Code', 'Consolas', monospace" font-size="15" fill="#484f58" text-anchor="middle">
183
+ $ npx adaptive-memory-router --provider auto
184
+ </text>
185
+
186
+ <!-- Bottom right badge -->
187
+ <rect x="1020" y="585" width="180" height="30" rx="15" fill="#161b22" stroke="#30363d" stroke-width="1"/>
188
+ <text x="1110" y="605" font-family="'SF Pro Text', -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" fill="#8b949e" text-anchor="middle" font-weight="500">
189
+ github.com/Das-rebel
190
+ </text>
191
+
192
+ <!-- Bottom decorative bar -->
193
+ <rect x="80" y="610" width="1120" height="2" fill="url(#titleGrad)" opacity="0.3" rx="1"/>
64
194
  </svg>
@@ -0,0 +1,54 @@
1
+ {
2
+ "timestamp": "2026-05-18T14:07:41.985Z",
3
+ "version": "2.0.6",
4
+ "queries": 200,
5
+ "exact_accuracy": 24,
6
+ "adjacent_accuracy": 82.5,
7
+ "over_routed": 73,
8
+ "under_routed": 79,
9
+ "cost_savings_vs_premium": 63.7,
10
+ "by_tier": {
11
+ "free": {
12
+ "correct": 0,
13
+ "total": 50
14
+ },
15
+ "cheap": {
16
+ "correct": 39,
17
+ "total": 60
18
+ },
19
+ "mid": {
20
+ "correct": 6,
21
+ "total": 50
22
+ },
23
+ "premium": {
24
+ "correct": 3,
25
+ "total": 40
26
+ }
27
+ },
28
+ "confusion": {
29
+ "free": {
30
+ "free": 0,
31
+ "cheap": 46,
32
+ "mid": 4,
33
+ "premium": 0
34
+ },
35
+ "cheap": {
36
+ "free": 0,
37
+ "cheap": 39,
38
+ "mid": 20,
39
+ "premium": 1
40
+ },
41
+ "mid": {
42
+ "free": 0,
43
+ "cheap": 42,
44
+ "mid": 6,
45
+ "premium": 2
46
+ },
47
+ "premium": {
48
+ "free": 0,
49
+ "cheap": 30,
50
+ "mid": 7,
51
+ "premium": 3
52
+ }
53
+ }
54
+ }
package/dist/cli.js CHANGED
@@ -54,10 +54,43 @@ function formatRoute(result) {
54
54
  }
55
55
  if (result.reasoning) {
56
56
  console.log(' Reason: ' + result.reasoning);
57
+ showStarPrompt();
57
58
  }
58
59
  console.log('');
59
60
  }
60
61
 
62
+
63
+ // ============================================================
64
+ // STAR PROMPT (shown once per user)
65
+ // ============================================================
66
+ function showStarPrompt() {
67
+ const fs = require('fs');
68
+ const path = require('path');
69
+ const home = process.env.HOME || process.env.USERPROFILE || '/tmp';
70
+ const marker = path.join(home, '.a3m-router', '.star-prompt-shown');
71
+
72
+ try {
73
+ // Only show once
74
+ if (fs.existsSync(marker)) return;
75
+
76
+ // Create directory if needed
77
+ const dir = path.dirname(marker);
78
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
79
+
80
+ console.log('');
81
+ console.log(' \x1b[2m── ────────────────────────────────────────\x1b[0m');
82
+ console.log(' \x1b[2m⭐ Found this useful? Star us on GitHub:\x1b[0m');
83
+ console.log(' \x1b[1m\x1b[36m https://github.com/Das-rebel/adaptive-memory-multi-model-router\x1b[0m');
84
+ console.log(' \x1b[2m── ────────────────────────────────────────\x1b[0m');
85
+ console.log('');
86
+
87
+ // Mark as shown
88
+ fs.writeFileSync(marker, new Date().toISOString());
89
+ } catch (e) {
90
+ // Silently fail - don't break CLI for this
91
+ }
92
+ }
93
+
61
94
  async function callProvider(providerId, model, prompt, maxTokens) {
62
95
  providerId = providerId || 'groq';
63
96
  model = model || 'llama-3.3-70b-versatile';
@@ -0,0 +1,134 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="780" height="520" viewBox="0 0 780 520">
2
+ <defs>
3
+ <linearGradient id="gpt4bar" x1="0" y1="0" x2="1" y2="0">
4
+ <stop offset="0%" stop-color="#f85149"/>
5
+ <stop offset="100%" stop-color="#da3633"/>
6
+ </linearGradient>
7
+ <linearGradient id="a3mbar" x1="0" y1="0" x2="1" y2="0">
8
+ <stop offset="0%" stop-color="#3fb950"/>
9
+ <stop offset="100%" stop-color="#238636"/>
10
+ </linearGradient>
11
+ <linearGradient id="header" x1="0" y1="0" x2="0" y2="1">
12
+ <stop offset="0%" stop-color="#161b22"/>
13
+ <stop offset="100%" stop-color="#0d1117"/>
14
+ </linearGradient>
15
+ </defs>
16
+
17
+ <!-- Background -->
18
+ <rect width="780" height="520" rx="12" fill="#0d1117" stroke="#30363d" stroke-width="1"/>
19
+
20
+ <!-- Header -->
21
+ <rect width="780" height="56" rx="12" fill="url(#header)"/>
22
+ <rect y="44" width="780" height="12" fill="url(#header)"/>
23
+ <text x="24" y="28" font-family="-apple-system,system-ui,sans-serif" font-size="18" fill="#c9d1d9" font-weight="700">💰 Cost Comparison</text>
24
+ <text x="24" y="46" font-family="-apple-system,system-ui,sans-serif" font-size="12" fill="#8b949e">10,000 queries/month · Real provider pricing · Mixed query complexity</text>
25
+
26
+ <!-- Legend -->
27
+ <rect x="580" y="16" width="14" height="14" rx="3" fill="url(#gpt4bar)"/>
28
+ <text x="600" y="27" font-family="-apple-system,system-ui,sans-serif" font-size="12" fill="#f85149">All → GPT-4o</text>
29
+ <rect x="680" y="16" width="14" height="14" rx="3" fill="url(#a3mbar)"/>
30
+ <text x="700" y="27" font-family="-apple-system,system-ui,sans-serif" font-size="12" fill="#3fb950">A3M Routed</text>
31
+
32
+ <!-- Chart rows -->
33
+ <g font-family="'SF Mono','Fira Code',monospace" font-size="12">
34
+
35
+ <!-- Row 1: Simple Q&A -->
36
+ <text x="24" y="82" fill="#8b949e">Simple Q&A</text>
37
+ <text x="24" y="96" fill="#484f58" font-size="10">47% of traffic · "What is 2+2?"</text>
38
+ <rect x="140" y="78" width="200" height="20" rx="4" fill="url(#gpt4bar)" opacity="0.9">
39
+ <animate attributeName="width" from="0" to="200" dur="0.6s" fill="freeze"/>
40
+ </rect>
41
+ <text x="346" y="93" fill="#f85149" font-size="11">$4.94</text>
42
+ <rect x="140" y="100" width="2" height="14" rx="2" fill="url(#a3mbar)">
43
+ <animate attributeName="width" from="0" to="2" dur="0.4s" fill="freeze"/>
44
+ </rect>
45
+ <text x="148" y="112" fill="#3fb950" font-size="11">$0.00 → CommandCode (FREE)</text>
46
+ <text x="720" y="96" fill="#3fb950" font-weight="bold" font-size="13">100% ✓</text>
47
+
48
+ <!-- Row 2: Code generation -->
49
+ <text x="24" y="148" fill="#8b949e">Code generation</text>
50
+ <text x="24" y="162" fill="#484f58" font-size="10">15% of traffic · "Write Python sort"</text>
51
+ <rect x="140" y="144" width="198" height="20" rx="4" fill="url(#gpt4bar)" opacity="0.9">
52
+ <animate attributeName="width" from="0" to="198" dur="0.6s" begin="0.15s" fill="freeze"/>
53
+ </rect>
54
+ <text x="344" y="159" fill="#f85149" font-size="11">$4.88</text>
55
+ <rect x="140" y="166" width="7" height="14" rx="2" fill="url(#a3mbar)">
56
+ <animate attributeName="width" from="0" to="7" dur="0.4s" begin="0.15s" fill="freeze"/>
57
+ </rect>
58
+ <text x="153" y="178" fill="#3fb950" font-size="11">$0.17 → DeepSeek v3</text>
59
+ <text x="720" y="162" fill="#3fb950" font-weight="bold" font-size="13">97% ✓</text>
60
+
61
+ <!-- Row 3: Summarization -->
62
+ <text x="24" y="214" fill="#8b949e">Summarization</text>
63
+ <text x="24" y="228" fill="#484f58" font-size="10">18% of traffic · "Summarize this doc"</text>
64
+ <rect x="140" y="210" width="292" height="20" rx="4" fill="url(#gpt4bar)" opacity="0.9">
65
+ <animate attributeName="width" from="0" to="292" dur="0.6s" begin="0.3s" fill="freeze"/>
66
+ </rect>
67
+ <text x="438" y="225" fill="#f85149" font-size="11">$7.20</text>
68
+ <rect x="140" y="232" width="17" height="14" rx="2" fill="url(#a3mbar)">
69
+ <animate attributeName="width" from="0" to="17" dur="0.4s" begin="0.3s" fill="freeze"/>
70
+ </rect>
71
+ <text x="163" y="244" fill="#3fb950" font-size="11">$0.43 → GPT-4o-mini</text>
72
+ <text x="720" y="228" fill="#3fb950" font-weight="bold" font-size="13">94% ✓</text>
73
+
74
+ <!-- Row 4: Complex reasoning -->
75
+ <text x="24" y="280" fill="#8b949e">Complex reasoning</text>
76
+ <text x="24" y="294" fill="#484f58" font-size="10">12% of traffic · "Analyze economics of..."</text>
77
+ <rect x="140" y="276" width="352" height="20" rx="4" fill="url(#gpt4bar)" opacity="0.9">
78
+ <animate attributeName="width" from="0" to="352" dur="0.6s" begin="0.45s" fill="freeze"/>
79
+ </rect>
80
+ <text x="498" y="291" fill="#f85149" font-size="11">$8.70</text>
81
+ <rect x="140" y="298" width="136" height="14" rx="2" fill="url(#a3mbar)">
82
+ <animate attributeName="width" from="0" to="136" dur="0.4s" begin="0.45s" fill="freeze"/>
83
+ </rect>
84
+ <text x="282" y="310" fill="#3fb950" font-size="11">$3.36 → Claude Haiku</text>
85
+ <text x="720" y="294" fill="#ffa657" font-weight="bold" font-size="13">61% ✓</text>
86
+
87
+ <!-- Row 5: Expert analysis -->
88
+ <text x="24" y="346" fill="#8b949e">Expert analysis</text>
89
+ <text x="24" y="360" fill="#484f58" font-size="10">8% of traffic · "Legal contract review"</text>
90
+ <rect x="140" y="342" width="340" height="20" rx="4" fill="url(#gpt4bar)" opacity="0.9">
91
+ <animate attributeName="width" from="0" to="340" dur="0.6s" begin="0.6s" fill="freeze"/>
92
+ </rect>
93
+ <text x="486" y="357" fill="#f85149" font-size="11">$8.40</text>
94
+ <rect x="140" y="364" width="340" height="14" rx="2" fill="url(#a3mbar)" opacity="0.5">
95
+ <animate attributeName="width" from="0" to="340" dur="0.4s" begin="0.6s" fill="freeze"/>
96
+ </rect>
97
+ <text x="486" y="376" fill="#8b949e" font-size="11">$8.40 → GPT-4o (no shortcut)</text>
98
+ <text x="720" y="360" fill="#8b949e" font-weight="bold" font-size="13">0%</text>
99
+ </g>
100
+
101
+ <!-- Divider -->
102
+ <line x1="24" y1="396" x2="756" y2="396" stroke="#30363d" stroke-width="1"/>
103
+
104
+ <!-- Total -->
105
+ <g font-family="-apple-system,system-ui,sans-serif">
106
+ <text x="24" y="418" fill="#c9d1d9" font-size="16" font-weight="700">Total: 10,000 queries</text>
107
+ <text x="380" y="418" fill="#f85149" font-size="16" font-weight="700">$34.11/mo</text>
108
+ <text x="470" y="418" fill="#484f58" font-size="16">→</text>
109
+ <text x="498" y="418" fill="#3fb950" font-size="16" font-weight="700">$12.36/mo</text>
110
+ <text x="600" y="418" fill="#3fb950" font-size="20" font-weight="800">Save 64%</text>
111
+ </g>
112
+
113
+ <!-- Scale projections -->
114
+ <g font-family="'SF Mono','Fira Code',monospace" font-size="11">
115
+ <text x="24" y="448" fill="#8b949e">At scale:</text>
116
+ <text x="24" y="468" fill="#484f58"> 100K queries/mo</text>
117
+ <text x="200" y="468" fill="#f85149">$341</text>
118
+ <text x="240" y="468" fill="#484f58">→</text>
119
+ <text x="260" y="468" fill="#3fb950">$124</text>
120
+ <text x="310" y="468" fill="#3fb950">save $218/mo</text>
121
+
122
+ <text x="420" y="468" fill="#484f58"> 1M queries/mo</text>
123
+ <text x="580" y="468" fill="#f85149">$3,411</text>
124
+ <text x="630" y="468" fill="#484f58">→</text>
125
+ <text x="650" y="468" fill="#3fb950">$1,236</text>
126
+ <text x="700" y="468" fill="#3fb950">save $2,175/mo</text>
127
+ </g>
128
+
129
+ <!-- Bottom note -->
130
+ <rect x="16" y="488" width="748" height="24" rx="4" fill="#161b22"/>
131
+ <text x="390" y="504" text-anchor="middle" font-family="-apple-system,system-ui,sans-serif" font-size="11" fill="#8b949e">
132
+ Based on real provider pricing from providerConfig.ts · RouteLLM query distribution (47% simple) · Savings vary by usage
133
+ </text>
134
+ </svg>