adaptive-memory-multi-model-router 2.15.3 → 2.16.0

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README_ja.md +2 -2
  3. package/README_zh.md +1 -1
  4. package/apps/cost-calculator/README.md +72 -0
  5. package/apps/cost-calculator/calculator.css +280 -0
  6. package/apps/cost-calculator/calculator.js +150 -0
  7. package/apps/cost-calculator/index.html +321 -0
  8. package/apps/cost-calculator/package.json +13 -0
  9. package/articles/ANNOUNCEMENT_reddit_ml.md +76 -0
  10. package/articles/ANNOUNCEMENT_vc/347/244/276/345/214/272.md +71 -0
  11. package/articles/ANNOUNCEMENT_vercel.md +85 -0
  12. package/dist/providers/providerConfig.d.ts +5 -1
  13. package/dist/providers/providerConfig.js +1006 -1
  14. package/dist/providers/providerConfig.js.map +1 -1
  15. package/docs/llms.txt +3 -3
  16. package/package.json +2 -2
  17. package/packages/a3m-vercel-ai/README.md +161 -0
  18. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts +12 -0
  19. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts.map +1 -0
  20. package/packages/a3m-vercel-ai/dist/a3m-language-model.js +289 -0
  21. package/packages/a3m-vercel-ai/dist/a3m-language-model.js.map +1 -0
  22. package/packages/a3m-vercel-ai/dist/index.d.ts +82 -0
  23. package/packages/a3m-vercel-ai/dist/index.d.ts.map +1 -0
  24. package/packages/a3m-vercel-ai/dist/index.js +79 -0
  25. package/packages/a3m-vercel-ai/dist/index.js.map +1 -0
  26. package/packages/a3m-vercel-ai/dist/types.d.ts +97 -0
  27. package/packages/a3m-vercel-ai/dist/types.d.ts.map +1 -0
  28. package/packages/a3m-vercel-ai/dist/types.js +5 -0
  29. package/packages/a3m-vercel-ai/dist/types.js.map +1 -0
  30. package/packages/a3m-vercel-ai/package-lock.json +969 -0
  31. package/packages/a3m-vercel-ai/package.json +46 -0
  32. package/packages/a3m-vercel-ai/src/a3m-language-model.ts +381 -0
  33. package/packages/a3m-vercel-ai/src/index.ts +104 -0
  34. package/packages/a3m-vercel-ai/src/types.ts +116 -0
  35. package/packages/a3m-vercel-ai/tsconfig.json +20 -0
  36. package/src/providers/providerConfig.ts +1053 -1
  37. package/summary.txt +38 -0
package/CHANGELOG.md CHANGED
@@ -14,7 +14,13 @@
14
14
  ### Changed
15
15
  - Cleanup removed 4 unused deps, fixed 0 vulns, deduplicated
16
16
 
17
- ## [2.14.0] — 2026-05-28
17
+ ## [2.16.0] — 2026-08-12
18
+
19
+ ### Added
20
+ - **80+ providers** (up from 36): Cloudflare Workers AI, HuggingFace Inference, Modal, Lepton AI, NVIDIA NIM, Baseten, RunPod, Predibase, Featherless AI, Abacus AI, Hyperbolic, Stability AI, SiliconFlow, Yandex GPT, Tencent Hunyuan, VolcEngine (Doubao), Baidu Qianfan, Kuaishou, 360 AI, Naver Clova, Kakao Brain, Upstage, SkyFire, LIVEPEOPLE, Scale AI, Titanium Network, Aizel Cloud, Poe, Phind, Banana, Forefront AI, You.com, Komo, Shine AI, AIDE Labs, Writer API, Databricks, La Plateforme, and more
21
+
22
+ ### Changed
23
+ - Provider expansion: 36 → 80+ providers across free, cheap, mid, premium, and enterprise tiers — 2026-05-28
18
24
 
19
25
  ### Added
20
26
  - MCP server for AI agent integration
package/README_ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # A3M Router 🔀 — 成本最优的LLMRouter & 并行执行
2
2
 
3
- **💰 $0.0768/1Kリクエスト · 47+プロバイダー · メモリ付きルーティング**
3
+ **💰 $0.0768/1Kリクエスト · 80+プロバイダー · メモリ付きルーティング**
4
4
 
5
5
  [English](./README.md) | [中文](./README_zh.md) | [日本語](./README_ja.md)
6
6
 
@@ -40,7 +40,7 @@ A3M: モデルA ║ モデルB ║ モデルC → スコアリングで最良
40
40
  - 🔄 **セマンティックキャッシュ** — 30%+ヒット率コスト節約
41
41
  - 🛡️ **予算強制** — クエリごとコスト追跡,超過防止
42
42
  - ⚡ **高速起動** — <100ms、19.5KB、ML依存なし
43
- - 🌐 **47+プロバイダー** — OpenAI, Anthropic, DeepSeek, Groq, NVIDIA等
43
+ - 🌐 **80+プロバイダー** — OpenAI, Anthropic, DeepSeek, Groq, NVIDIA等
44
44
 
45
45
  ## クイックスタート
46
46
 
package/README_zh.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # A3M Router 🔀 — 最便宜的LLM路由 & 并行执行
2
2
 
3
- **💰 $0.0768/1K请求 · 47+提供商 · 带记忆路由**
3
+ **💰 $0.0768/1K请求 · 80+提供商 · 带记忆路由**
4
4
 
5
5
  [English](./README.md) | [日本語](./README_ja.md) | [中文](./README_zh.md)
6
6
 
@@ -0,0 +1,72 @@
1
+ # A3M Router Cost Calculator
2
+
3
+ **Live:** https://a3m.router/calculator
4
+
5
+ Drop-in interactive calculator. No build step. No npm dependencies for the calculator itself.
6
+
7
+ ## What it does
8
+
9
+ - Input: monthly request volume + model mix
10
+ - Output: side-by-side cost comparison (baseline vs A3M routed)
11
+ - Generates shareable URL with encoded config (base64url)
12
+ - Exports comparison as CSV
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ # Open directly
18
+ open apps/cost-calculator/index.html
19
+
20
+ # Or serve locally
21
+ npx serve apps/cost-calculator
22
+ ```
23
+
24
+ ## Embed in any site
25
+
26
+ ```html
27
+ <iframe
28
+ src="https://a3m.router/calculator"
29
+ width="100%"
30
+ height="700"
31
+ frameborder="0"
32
+ style="border-radius: 12px;"
33
+ ></iframe>
34
+ ```
35
+
36
+ ## Architecture
37
+
38
+ ```
39
+ calculator.js — Pure JS, no dependencies. All pricing, routing, and encoding logic.
40
+ calculator.css — Standalone styles. Dark theme, responsive.
41
+ index.html — Self-contained. Vanilla JS. Loads calculator.js.
42
+ package.json — vitest for unit testing the pure JS logic.
43
+ ```
44
+
45
+ ## Testing
46
+
47
+ ```bash
48
+ cd apps/cost-calculator
49
+ npm install
50
+ npm test
51
+ ```
52
+
53
+ ## Models Supported
54
+
55
+ | Premium Model | Routed To | Savings |
56
+ |---------------|-----------|---------|
57
+ | GPT-4o | GPT-4o-mini | ~35% |
58
+ | Claude 3.5 Sonnet | Claude 3 Haiku | ~40% |
59
+ | Gemini 1.5 Pro | Gemini 1.5 Flash | ~45% |
60
+ | Groq Llama 3.3 70B | Groq Mixtral 8x7B | ~30% |
61
+
62
+ ## Pricing Source
63
+
64
+ OpenRouter provider rates (per 1M tokens). Update `PRICING` constant in `calculator.js` to reflect latest rates.
65
+
66
+ ## Next Steps
67
+
68
+ - [ ] Deploy to `a3m.router/calculator` (Vercel static)
69
+ - [ ] Add UTM tracking on share links
70
+ - [ ] Add "embed widget" script for dynamic resize
71
+ - [ ] Write HN + Reddit post with actual example calculations
72
+ - [ ] Add unit tests with vitest
@@ -0,0 +1,280 @@
1
+ /* A3M Router Cost Calculator Styles */
2
+
3
+ :root {
4
+ --a3m-primary: #6366f1;
5
+ --a3m-accent: #818cf8;
6
+ --a3m-bg: #0f0f1a;
7
+ --a3m-surface: #1a1a2e;
8
+ --a3m-border: #2d2d4a;
9
+ --a3m-text: #e2e8f0;
10
+ --a3m-muted: #94a3b8;
11
+ --a3m-green: #22c55e;
12
+ --a3m-red: #ef4444;
13
+ }
14
+
15
+ * { box-sizing: border-box; margin: 0; padding: 0; }
16
+
17
+ body {
18
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
19
+ background: var(--a3m-bg);
20
+ color: var(--a3m-text);
21
+ min-height: 100vh;
22
+ padding: 2rem 1rem;
23
+ }
24
+
25
+ .container {
26
+ max-width: 900px;
27
+ margin: 0 auto;
28
+ }
29
+
30
+ h1 {
31
+ font-size: 1.75rem;
32
+ font-weight: 700;
33
+ text-align: center;
34
+ margin-bottom: 0.5rem;
35
+ }
36
+
37
+ .subtitle {
38
+ text-align: center;
39
+ color: var(--a3m-muted);
40
+ margin-bottom: 2rem;
41
+ }
42
+
43
+ .card {
44
+ background: var(--a3m-surface);
45
+ border: 1px solid var(--a3m-border);
46
+ border-radius: 12px;
47
+ padding: 1.5rem;
48
+ margin-bottom: 1.5rem;
49
+ }
50
+
51
+ .card-title {
52
+ font-size: 0.875rem;
53
+ font-weight: 600;
54
+ text-transform: uppercase;
55
+ letter-spacing: 0.05em;
56
+ color: var(--a3m-muted);
57
+ margin-bottom: 1rem;
58
+ }
59
+
60
+ /* Input grid */
61
+ .input-grid {
62
+ display: grid;
63
+ grid-template-columns: 1fr 1fr;
64
+ gap: 1rem;
65
+ }
66
+
67
+ @media (max-width: 600px) {
68
+ .input-grid { grid-template-columns: 1fr; }
69
+ }
70
+
71
+ .input-group {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: 0.5rem;
75
+ }
76
+
77
+ .input-group label {
78
+ font-size: 0.875rem;
79
+ font-weight: 500;
80
+ color: var(--a3m-muted);
81
+ }
82
+
83
+ .input-group input,
84
+ .input-group select {
85
+ padding: 0.625rem 0.875rem;
86
+ background: var(--a3m-bg);
87
+ border: 1px solid var(--a3m-border);
88
+ border-radius: 8px;
89
+ color: var(--a3m-text);
90
+ font-size: 1rem;
91
+ width: 100%;
92
+ }
93
+
94
+ .input-group input:focus,
95
+ .input-group select:focus {
96
+ outline: none;
97
+ border-color: var(--a3m-primary);
98
+ }
99
+
100
+ /* Model mix rows */
101
+ .model-mix {
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: 0.75rem;
105
+ margin-top: 1rem;
106
+ }
107
+
108
+ .model-row {
109
+ display: grid;
110
+ grid-template-columns: 1fr 100px auto;
111
+ gap: 0.5rem;
112
+ align-items: center;
113
+ }
114
+
115
+ .model-row select,
116
+ .model-row input {
117
+ padding: 0.5rem;
118
+ background: var(--a3m-bg);
119
+ border: 1px solid var(--a3m-border);
120
+ border-radius: 6px;
121
+ color: var(--a3m-text);
122
+ font-size: 0.875rem;
123
+ }
124
+
125
+ .model-row span {
126
+ color: var(--a3m-muted);
127
+ font-size: 0.875rem;
128
+ white-space: nowrap;
129
+ }
130
+
131
+ .btn {
132
+ display: inline-flex;
133
+ align-items: center;
134
+ gap: 0.5rem;
135
+ padding: 0.625rem 1.25rem;
136
+ background: var(--a3m-primary);
137
+ color: white;
138
+ border: none;
139
+ border-radius: 8px;
140
+ font-size: 0.875rem;
141
+ font-weight: 600;
142
+ cursor: pointer;
143
+ transition: background 0.2s;
144
+ }
145
+
146
+ .btn:hover { background: var(--a3m-accent); }
147
+ .btn-secondary {
148
+ background: var(--a3m-border);
149
+ color: var(--a3m-text);
150
+ }
151
+ .btn-secondary:hover { background: #3d3d5a; }
152
+
153
+ .btn-row {
154
+ display: flex;
155
+ gap: 0.75rem;
156
+ margin-top: 1.25rem;
157
+ flex-wrap: wrap;
158
+ }
159
+
160
+ /* Results */
161
+ .results-grid {
162
+ display: grid;
163
+ grid-template-columns: repeat(3, 1fr);
164
+ gap: 1rem;
165
+ margin-bottom: 1.5rem;
166
+ }
167
+
168
+ @media (max-width: 600px) {
169
+ .results-grid { grid-template-columns: 1fr; }
170
+ }
171
+
172
+ .result-card {
173
+ background: var(--a3m-bg);
174
+ border: 1px solid var(--a3m-border);
175
+ border-radius: 10px;
176
+ padding: 1.25rem;
177
+ text-align: center;
178
+ }
179
+
180
+ .result-label {
181
+ font-size: 0.75rem;
182
+ font-weight: 600;
183
+ text-transform: uppercase;
184
+ letter-spacing: 0.05em;
185
+ color: var(--a3m-muted);
186
+ margin-bottom: 0.5rem;
187
+ }
188
+
189
+ .result-value {
190
+ font-size: 1.75rem;
191
+ font-weight: 700;
192
+ }
193
+
194
+ .result-value.savings { color: var(--a3m-green); }
195
+ .result-value.baseline { color: var(--a3m-muted); text-decoration: line-through; }
196
+
197
+ /* Breakdown table */
198
+ .breakdown-table {
199
+ width: 100%;
200
+ border-collapse: collapse;
201
+ font-size: 0.875rem;
202
+ margin-top: 1rem;
203
+ }
204
+
205
+ .breakdown-table th {
206
+ text-align: left;
207
+ padding: 0.625rem 0.75rem;
208
+ color: var(--a3m-muted);
209
+ font-weight: 600;
210
+ font-size: 0.75rem;
211
+ text-transform: uppercase;
212
+ border-bottom: 1px solid var(--a3m-border);
213
+ }
214
+
215
+ .breakdown-table td {
216
+ padding: 0.625rem 0.75rem;
217
+ border-bottom: 1px solid var(--a3m-border);
218
+ }
219
+
220
+ .breakdown-table tr:last-child td { border-bottom: none; }
221
+ .breakdown-table .num { text-align: right; font-variant-numeric: tabular-nums; }
222
+ .breakdown-table .savings-cell { color: var(--a3m-green); }
223
+
224
+ /* Share bar */
225
+ .share-bar {
226
+ display: flex;
227
+ gap: 0.5rem;
228
+ align-items: center;
229
+ margin-top: 1rem;
230
+ }
231
+
232
+ .share-bar input {
233
+ flex: 1;
234
+ padding: 0.5rem 0.75rem;
235
+ background: var(--a3m-bg);
236
+ border: 1px solid var(--a3m-border);
237
+ border-radius: 6px;
238
+ color: var(--a3m-text);
239
+ font-size: 0.8rem;
240
+ font-family: monospace;
241
+ }
242
+
243
+ /* Chart */
244
+ .chart-container {
245
+ position: relative;
246
+ height: 250px;
247
+ margin: 1.5rem 0;
248
+ }
249
+
250
+ .chart-bar {
251
+ position: absolute;
252
+ bottom: 0;
253
+ width: 40%;
254
+ border-radius: 6px 6px 0 0;
255
+ transition: height 0.5s ease;
256
+ }
257
+
258
+ .chart-bar.baseline {
259
+ left: 15%;
260
+ background: var(--a3m-muted);
261
+ opacity: 0.5;
262
+ }
263
+
264
+ .chart-bar.a3m {
265
+ right: 15%;
266
+ background: var(--a3m-primary);
267
+ }
268
+
269
+ /* Hidden until calculated */
270
+ .hidden { display: none; }
271
+
272
+ /* Footer */
273
+ .footer {
274
+ text-align: center;
275
+ color: var(--a3m-muted);
276
+ font-size: 0.75rem;
277
+ margin-top: 2rem;
278
+ }
279
+
280
+ .footer a { color: var(--a3m-accent); text-decoration: none; }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * A3M Router Cost Calculator
3
+ * Pure JS, no dependencies.
4
+ */
5
+
6
+ // --- Pricing constants (per 1M tokens) ---
7
+ const PRICING = {
8
+ 'gpt-4o': { input: 5.0, output: 15.0 },
9
+ 'gpt-4o-mini': { input: 0.15, output: 0.60 },
10
+ 'claude-3.5-sonnet': { input: 3.0, output: 15.0 },
11
+ 'claude-3-haiku': { input: 0.25, output: 1.25 },
12
+ 'gemini-1.5-pro': { input: 3.5, output: 10.5 },
13
+ 'gemini-1.5-flash': { input: 0.075, output: 0.30 },
14
+ 'groq-llama-3.3-70b': { input: 0.59, output: 0.79 },
15
+ 'groq-mixtral-8x7b': { input: 0.24, output: 0.24 },
16
+ };
17
+
18
+ const ROUTING_SAVINGS = {
19
+ // % of requests A3M routes to cheaper model
20
+ 'gpt-4o': 0.35, // 35% routed to 4o-mini
21
+ 'claude-3.5-sonnet': 0.40, // 40% routed to Haiku
22
+ 'gemini-1.5-pro': 0.45, // 45% routed to Flash
23
+ };
24
+
25
+ const AVG_TOKENS = {
26
+ input: 500, // avg input tokens
27
+ output: 800, // avg output tokens
28
+ };
29
+
30
+ /**
31
+ * @param {{ requestsPerMonth: number, modelMix: Array<{model: string, percent: number}> }} cfg
32
+ * @returns {{ totalCost: number, breakdown: Array<{model, requests, cost}> }}
33
+ */
34
+ function calculateBaselineCost({ requestsPerMonth, modelMix }) {
35
+ const breakdown = modelMix.map(({ model, percent }) => {
36
+ const reqCount = Math.round(requestsPerMonth * (percent / 100));
37
+ const pricing = PRICING[model] || { input: 3.0, output: 15.0 };
38
+ const cost = reqCount * (
39
+ (pricing.input * AVG_TOKENS.input / 1_000_000) +
40
+ (pricing.output * AVG_TOKENS.output / 1_000_000)
41
+ );
42
+ return { model, requests: reqCount, cost };
43
+ });
44
+
45
+ const totalCost = breakdown.reduce((sum, b) => sum + b.cost, 0);
46
+ return { totalCost, breakdown };
47
+ }
48
+
49
+ /**
50
+ * @param {{ requestsPerMonth: number, modelMix: Array<{model: string, percent: number}> }} cfg
51
+ * @returns {{ totalCost: number, breakdown: Array<{model, requests, cost, routedTo?, savings?}> }}
52
+ */
53
+ function calculateA3mCost({ requestsPerMonth, modelMix }) {
54
+ const breakdown = modelMix.map(({ model, percent }) => {
55
+ const reqCount = Math.round(requestsPerMonth * (percent / 100));
56
+ const routingSavings = ROUTING_SAVINGS[model] || 0;
57
+ const routedRequests = Math.round(reqCount * routingSavings);
58
+
59
+ // Baseline: all requests on premium model
60
+ const pricing = PRICING[model] || { input: 3.0, output: 15.0 };
61
+ const baselineCost = reqCount * (
62
+ (pricing.input * AVG_TOKENS.input / 1_000_000) +
63
+ (pricing.output * AVG_TOKENS.output / 1_000_000)
64
+ );
65
+
66
+ // A3M: some routed to cheaper model
67
+ // Find a cheaper alternative (heuristic: -mini, -flash, -haiku, or groq)
68
+ const cheaper = findCheaperModel(model);
69
+ const cheaperPricing = cheaper ? PRICING[cheaper] : pricing;
70
+
71
+ const a3mCost = (reqCount - routedRequests) * (
72
+ (pricing.input * AVG_TOKENS.input / 1_000_000) +
73
+ (pricing.output * AVG_TOKENS.output / 1_000_000)
74
+ ) + routedRequests * (
75
+ (cheaperPricing.input * AVG_TOKENS.input / 1_000_000) +
76
+ (cheaperPricing.output * AVG_TOKENS.output / 1_000_000)
77
+ );
78
+
79
+ return {
80
+ model,
81
+ requests: reqCount,
82
+ cost: a3mCost,
83
+ routedTo: routedRequests > 0 ? cheaper : null,
84
+ savings: baselineCost - a3mCost,
85
+ };
86
+ });
87
+
88
+ const totalCost = breakdown.reduce((sum, b) => sum + b.cost, 0);
89
+ const totalSavings = breakdown.reduce((sum, b) => sum + (b.savings || 0), 0);
90
+ return { totalCost, breakdown, totalSavings };
91
+ }
92
+
93
+ function findCheaperModel(model) {
94
+ const cheaperMap = {
95
+ 'gpt-4o': 'gpt-4o-mini',
96
+ 'claude-3.5-sonnet': 'claude-3-haiku',
97
+ 'gemini-1.5-pro': 'gemini-1.5-flash',
98
+ 'groq-llama-3.3-70b': 'groq-mixtral-8x7b',
99
+ };
100
+ return cheaperMap[model] || null;
101
+ }
102
+
103
+ /**
104
+ * @param {number} baseline
105
+ * @param {number} a3m
106
+ * @returns {{ savingsPercent: number, savingsAmount: number }}
107
+ */
108
+ function computeSavings(baseline, a3m) {
109
+ return {
110
+ savingsPercent: baseline > 0 ? ((baseline - a3m) / baseline) * 100 : 0,
111
+ savingsAmount: baseline - a3m,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Encodes calculator config into a URL-safe string
117
+ * @param {{ requestsPerMonth: number, modelMix: Array }} cfg
118
+ * @returns {string} base64url encoded config
119
+ */
120
+ function encodeConfig({ requestsPerMonth, modelMix }) {
121
+ const json = JSON.stringify({ requestsPerMonth, modelMix });
122
+ // btoa but URL-safe
123
+ return btoa(json).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
124
+ }
125
+
126
+ /**
127
+ * Decodes a URL-safe base64 string back to config
128
+ * @param {string} encoded
129
+ * @returns {{ requestsPerMonth: number, modelMix: Array }}
130
+ */
131
+ function decodeConfig(encoded) {
132
+ const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
133
+ const json = atob(base64);
134
+ return JSON.parse(json);
135
+ }
136
+
137
+ /**
138
+ * Generates a full shareable URL
139
+ * @param {{ requestsPerMonth: number, modelMix: Array }} cfg
140
+ * @returns {string}
141
+ */
142
+ function generateShareableLink(cfg) {
143
+ const encoded = encodeConfig(cfg);
144
+ return `${window.location.origin}${window.location.pathname}?cfg=${encoded}`;
145
+ }
146
+
147
+ // --- Exports for testing ---
148
+ if (typeof module !== 'undefined' && module.exports) {
149
+ module.exports = { calculateBaselineCost, calculateA3mCost, computeSavings, encodeConfig, decodeConfig, PRICING };
150
+ }