adaptive-memory-multi-model-router 2.2.5 → 2.2.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.
Files changed (52) hide show
  1. package/README.md +149 -116
  2. package/README.md.bak +836 -0
  3. package/assets/benchmark-results.png +0 -0
  4. package/assets/complexity-scoring-v2.png +0 -0
  5. package/assets/complexity-scoring.png +0 -0
  6. package/assets/cost-comparison-chart.png +0 -0
  7. package/assets/cost-comparison-v2.png +0 -0
  8. package/assets/feature-comparison-v2.png +0 -0
  9. package/assets/feature-comparison-v3.png +0 -0
  10. package/assets/provider-health-chart.png +0 -0
  11. package/assets/provider-health-v2.png +0 -0
  12. package/assets/routing-flow-v2.png +0 -0
  13. package/assets/routing-flow-v3.png +0 -0
  14. package/assets/routing-flow.png +0 -0
  15. package/assets/tier-distribution.png +0 -0
  16. package/benchmark-results.json +620 -46
  17. package/dist/cache/cacheKeyGenerator.d.ts +67 -0
  18. package/dist/cache/cacheKeyGenerator.d.ts.map +1 -0
  19. package/dist/cache/cacheKeyGenerator.js +211 -0
  20. package/dist/cache/cacheKeyGenerator.js.map +1 -0
  21. package/dist/cli.js +0 -0
  22. package/dist/cost/preCallCostEstimator.d.ts +114 -0
  23. package/dist/cost/preCallCostEstimator.d.ts.map +1 -0
  24. package/dist/cost/preCallCostEstimator.js +256 -0
  25. package/dist/cost/preCallCostEstimator.js.map +1 -0
  26. package/dist/inference/speculativeDecoding.d.ts +133 -0
  27. package/dist/inference/speculativeDecoding.d.ts.map +1 -0
  28. package/dist/inference/speculativeDecoding.js +276 -0
  29. package/dist/inference/speculativeDecoding.js.map +1 -0
  30. package/dist/providers/providerHealth.d.ts +117 -0
  31. package/dist/providers/providerHealth.d.ts.map +1 -0
  32. package/dist/providers/providerHealth.js +309 -0
  33. package/dist/providers/providerHealth.js.map +1 -0
  34. package/dist/routing/difficultyClassifier.d.ts +79 -0
  35. package/dist/routing/difficultyClassifier.d.ts.map +1 -0
  36. package/dist/routing/difficultyClassifier.js +329 -0
  37. package/dist/routing/difficultyClassifier.js.map +1 -0
  38. package/dist/sdk.d.ts +125 -0
  39. package/dist/sdk.d.ts.map +1 -0
  40. package/dist/sdk.js.map +1 -0
  41. package/package.json +2 -322
  42. package/scripts/run-mmlu-benchmark.js +176 -0
  43. package/scripts/run-provider-benchmark.js +244 -0
  44. package/src/cache/cacheKeyGenerator.ts +242 -0
  45. package/src/cost/preCallCostEstimator.ts +345 -0
  46. package/src/inference/speculativeDecoding.ts +373 -0
  47. package/src/providers/providerHealth.ts +397 -0
  48. package/src/routing/difficultyClassifier.ts +420 -0
  49. package/test/provider-test.js +69 -90
  50. package/test.js +43 -69
  51. package/test.js.bak +376 -0
  52. package/src/skills/__tests__/skill_manager.test.ts +0 -328
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adaptive-memory-multi-model-router",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "shortName": "A3M Router",
5
5
  "displayName": "A3M Router - Adaptive Memory Multi-Model Router",
6
6
  "description": "LLM router & AI gateway with 99.5% routing accuracy — supports 47 providers including DeepSeek, Kimi (Moonshot), Qwen, Zhipu GLM, Yi, Baichuan, MiniMax, StepFun. Zero ML, 19.5KB. Multi-signal routing, semantic cache, guardrails, cost analytics. MIT. TypeScript SDK + Python SDK + OpenAI proxy.",
@@ -53,142 +53,6 @@
53
53
  }
54
54
  },
55
55
  "keywords": [
56
- "adaptive-router",
57
- "agent",
58
- "agent-framework",
59
- "ai-agent-tools",
60
- "ai-assistant",
61
- "ai-discoverability",
62
- "ai-routing",
63
- "airtable",
64
- "amplitude",
65
- "api-gateway",
66
- "asana",
67
- "automation",
68
- "autonomous-agents",
69
- "aws-bedrock",
70
- "batch-processing",
71
- "bitbucket",
72
- "circuit-breaker",
73
- "claude-code",
74
- "cli",
75
- "cloud",
76
- "code-generation",
77
- "cohere",
78
- "content-filtering",
79
- "copilot",
80
- "cost-analytics",
81
- "datadog",
82
- "deepinfra",
83
- "developer-experience",
84
- "developer-tools",
85
- "devops",
86
- "discord",
87
- "dropbox",
88
- "dx",
89
- "edge-computing",
90
- "embedding",
91
- "enterprise",
92
- "fallback",
93
- "fine-tuning",
94
- "fireworks",
95
- "gemini",
96
- "generative-engine-optimization",
97
- "geo",
98
- "github",
99
- "gitlab",
100
- "gmail",
101
- "google",
102
- "google-calendar",
103
- "gpt-4",
104
- "graphql",
105
- "high-availability",
106
- "hubspot",
107
- "huggingface",
108
- "inference",
109
- "input-validation",
110
- "intent-mapping",
111
- "intercom",
112
- "javascript",
113
- "jira",
114
- "latency-optimization",
115
- "linear",
116
- "llamaindex",
117
- "llm-intent",
118
- "llm-tools",
119
- "llmlingua",
120
- "load-balancing",
121
- "logging",
122
- "machine-learning",
123
- "mailchimp",
124
- "mcp",
125
- "medusa",
126
- "memory-tree",
127
- "middleware",
128
- "mixpanel",
129
- "monitoring",
130
- "multi-model",
131
- "natural-language-processing",
132
- "netlify",
133
- "nodejs",
134
- "notion",
135
- "npm",
136
- "observability",
137
- "open-source",
138
- "orchestration",
139
- "parallel-execution",
140
- "performance",
141
- "perplexity",
142
- "pii-detection",
143
- "pinecone",
144
- "posthog",
145
- "prefix-caching",
146
- "production",
147
- "prompt-engineering",
148
- "prompt-injection",
149
- "provider-registry",
150
- "proxy",
151
- "proxy-server",
152
- "python",
153
- "radix-attention",
154
- "rag",
155
- "rate-limiting",
156
- "real-time",
157
- "rest-api",
158
- "retrieval-augmented-generation",
159
- "retry",
160
- "route-quality",
161
- "routellm",
162
- "router",
163
- "s3",
164
- "salesforce",
165
- "sanitization",
166
- "scalability",
167
- "sdk",
168
- "security",
169
- "segment",
170
- "sendgrid",
171
- "sentry",
172
- "serverless",
173
- "shopify",
174
- "slack",
175
- "speculative-decoding",
176
- "streaming",
177
- "stripe",
178
- "telegram",
179
- "testing",
180
- "together-ai",
181
- "token-compression",
182
- "tools",
183
- "tracing",
184
- "transformer",
185
- "trello",
186
- "typescript",
187
- "vector-database",
188
- "vercel",
189
- "websocket",
190
- "xai",
191
- "zendesk",
192
56
  "llm-proxy",
193
57
  "claude",
194
58
  "ai",
@@ -271,191 +135,7 @@
271
135
  "semantic-cache",
272
136
  "langchain",
273
137
  "ai-guardrails",
274
- "chatbot",
275
- "a3m",
276
- "a3m-router",
277
- "adaptive",
278
- "memory-based",
279
- "multi-model-router",
280
- "memory-based-router",
281
- "treequest",
282
- "parallel-ai",
283
- "agent-orchestration",
284
- "multi-agent",
285
- "parallel",
286
- "cost-tracking",
287
- "cache",
288
- "caching",
289
- "exponential-backoff",
290
- "mcts",
291
- "monte-carlo-tree-search",
292
- "workflow-optimization",
293
- "hierarchical-planning",
294
- "halo",
295
- "episodic-memory",
296
- "semantic-memory",
297
- "agent-memory",
298
- "python-bindings",
299
- "pypi",
300
- "autogen",
301
- "crewai",
302
- "transformers",
303
- "agent-codegen",
304
- "ai-coding",
305
- "zai",
306
- "llama",
307
- "ai-agents",
308
- "memory-based-llm-router",
309
- "multi-llm-router",
310
- "llm-memory-router",
311
- "adaptive-llm-router",
312
- "intelligent-router",
313
- "intelligent-llm-router",
314
- "learning-router",
315
- "contextual-router",
316
- "context-aware-router",
317
- "task-aware-router",
318
- "memory-augmented",
319
- "memory-augmented-llm",
320
- "episodic-memory-router",
321
- "semantic-memory-router",
322
- "task-memory",
323
- "cross-context-memory",
324
- "context-compression",
325
- "ison-format",
326
- "message-truncation",
327
- "context-management",
328
- "local-llm",
329
- "lmstudio",
330
- "local-model",
331
- "privacy-llm",
332
- "priority-queue",
333
- "token-counting",
334
- "cost-estimation",
335
- "cost-prediction",
336
- "intelligent-failover",
337
- "kv-cache",
338
- "pagedattention",
339
- "kv-cache-quantization",
340
- "streamingllm",
341
- "multimodel-orchestration",
342
- "multi-agent-debate",
343
- "self-consistency",
344
- "tensor-parallelism",
345
- "continuous-batching",
346
- "arxiv",
347
- "research-backed",
348
- "icml",
349
- "neurips",
350
- "iclr",
351
- "pi-extension",
352
- "pi",
353
- "pi-package",
354
- "pi-coding-agent",
355
- "pi-agent",
356
- "agent-discoverable",
357
- "ai-native",
358
- "01-ai",
359
- "01ai",
360
- "128käøŠäø‹ę–‡",
361
- "ai-gateway-cn",
362
- "aič·Æē”±",
363
- "aliyun",
364
- "baichuan-ai",
365
- "baichuan2",
366
- "baichuan2-flash",
367
- "baiducloud",
368
- "chinese-ai-proxy",
369
- "chinese-api-gateway",
370
- "chinese-chatgpt",
371
- "chinese-language-model",
372
- "chinese-llm-proxy",
373
- "chinese-models",
374
- "chinese-nlp",
375
- "chinesellm",
376
- "chinesellm-routing",
377
- "deepseek-ai",
378
- "deepseek-api",
379
- "deepseek-chat",
380
- "deepseek-coder",
381
- "deepseek-reasoner",
382
- "embedding-model",
383
- "glm-4",
384
- "glm-4-air",
385
- "glm-4-flash",
386
- "glm-4-long",
387
- "glm-4-plus",
388
- "huawei-cloud",
389
- "langchain-cn",
390
- "lingyi",
391
- "lingyi-wanwu",
392
- "llamaindex-cn",
393
- "llm-gateway-cn",
394
- "long-context-model",
395
- "minimax-ai",
396
- "minimax-api",
397
- "minimax-chat",
398
- "minimax-turbo",
399
- "moonshot-ai",
400
- "moonshot-v1",
401
- "moonshot-v1-128k",
402
- "moonshot-v1-32k",
403
- "moonshot-v1-8k",
404
- "multimodal",
405
- "qianwen",
406
- "qwen-long",
407
- "qwen-max",
408
- "qwen-plus",
409
- "qwen-turbo",
410
- "qwen2",
411
- "qwen3",
412
- "step-1",
413
- "step-1v",
414
- "step-2",
415
- "tencentcloud",
416
- "tongji",
417
- "tongyi",
418
- "tongyi-qianwen",
419
- "vision-model",
420
- "volcengine",
421
- "wu-yuan",
422
- "wuyuan",
423
- "yi-ai",
424
- "yi-large",
425
- "yi-lightning",
426
- "yi-medium",
427
- "zai-glm",
428
- "zai-glm-4",
429
- "zhipu-ai",
430
- "中国ai",
431
- "äø­å›½å¤§ęØ”åž‹",
432
- "äø­ę–‡chatgpt",
433
- "äø­ę–‡embedding",
434
- "äø­ę–‡langchain",
435
- "äø­ę–‡llamaindex",
436
- "äø­ę–‡nlp",
437
- "äø­ę–‡seo",
438
- "äø­ę–‡å¤šęØ”ę€",
439
- "äø­ę–‡å¤§ęØ”åž‹",
440
- "äø­ę–‡ęœē“¢å¼•ę“Žä¼˜åŒ–",
441
- "äø­ę–‡ęØ”åž‹",
442
- "åŽäøŗäŗ‘",
443
- "向量化",
444
- "国产ai",
445
- "å›½äŗ§å¤§ęØ”åž‹",
446
- "å¤šęØ”åž‹č·Æē”±",
447
- "å¤šęØ”ę€",
448
- "å¤§ęØ”åž‹č·Æē”±",
449
- "å­—čŠ‚ai",
450
- "ę™ŗčƒ½č·Æē”±",
451
- "ē«å±±å¼•ę“Ž",
452
- "百度ai",
453
- "百度云",
454
- "腾讯ai",
455
- "腾讯云",
456
- "é•æäøŠäø‹ę–‡",
457
- "é˜æé‡Œai",
458
- "é˜æé‡Œäŗ‘"
138
+ "chatbot"
459
139
  ],
460
140
  "author": "Das-rebel <subho@example.com>",
461
141
  "license": "MIT",
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * A3M Router — MMLU Benchmark
4
+ * MMLU: 15 multiple choice questions (actual MMLU methodology)
5
+ * MT-Bench proxy: measures response quality via completeness scoring
6
+ */
7
+
8
+ const https = require('https');
9
+
10
+ const MMLU_QUESTIONS = [
11
+ { q: "What is the derivative of x²?", choices: ["x", "2x", "2", "x²"], answer: 1, subject: "math" },
12
+ { q: "Solve for x: 2x + 6 = 14", choices: ["4", "3", "5", "10"], answer: 0, subject: "math" },
13
+ { q: "Time complexity of binary search?", choices: ["O(n)", "O(log n)", "O(n²)", "O(1)"], answer: 1, subject: "cs" },
14
+ { q: "In Python, list.append() does what?", choices: ["Adds to start", "Adds to end", "Removes last", "Sorts list"], answer: 1, subject: "cs" },
15
+ { q: "Output of type([])?", choices: ["<class 'array'>", "<class 'list'>", "<class 'tuple'>", "<class 'dict'>"], answer: 1, subject: "cs" },
16
+ { q: "GDP stands for?", choices: ["Gross Domestic Product", "General Domestic Price", "Government Debt Payment", "Global Demand Protocol"], answer: 0, subject: "economics" },
17
+ { q: "If supply increases and demand stays same, price:", choices: ["Increases", "Decreases", "Stays same", "Doubles"], answer: 1, subject: "economics" },
18
+ { q: "Powerhouse of the cell?", choices: ["Nucleus", "Ribosome", "Mitochondria", "Golgi body"], answer: 2, subject: "biology" },
19
+ { q: "DNA stands for?", choices: ["Deoxyribonucleic Acid", "Dinitrogen Acid", "Dynamic Nuclear Acid", "Dual Nucleotide"], answer: 0, subject: "biology" },
20
+ { q: "Primary purpose of a contract?", choices: ["Entertainment", "Create legal obligations", "Tax avoidance", "Social bonding"], answer: 1, subject: "law" },
21
+ { q: "Which US amendment protects free speech?", choices: ["1st", "2nd", "4th", "5th"], answer: 0, subject: "law" },
22
+ { q: "Car accelerates from rest at 2 m/s². Velocity after 5s?", choices: ["5 m/s", "10 m/s", "7 m/s", "2.5 m/s"], answer: 1, subject: "physics" },
23
+ { q: "Unit of force in SI?", choices: ["Joule", "Watt", "Newton", "Pascal"], answer: 2, subject: "physics" },
24
+ { q: "If gas temp increases at constant volume, pressure:", choices: ["Decreases", "Increases", "Stays constant", "Becomes zero"], answer: 1, subject: "physics" },
25
+ { q: "What is π to two decimal places?", choices: ["3.14", "3.16", "3.12", "3.18"], answer: 0, subject: "math" },
26
+ ];
27
+
28
+ const QUALITY_QUESTIONS = [
29
+ { id: 1, prompt: "If John has 5 apples and gives 3 to Mary, how many does he have left?", expected: "2" },
30
+ { id: 2, prompt: "Write a Python function that checks if a string is a palindrome.", expected: "def" },
31
+ { id: 3, prompt: "Compare supervised vs unsupervised learning in 2 sentences.", expected: "supervised" },
32
+ { id: 4, prompt: "What is the capital of France?", expected: "Paris" },
33
+ { id: 5, prompt: "Train travels 300km in 4 hours. Average speed?", expected: "75" },
34
+ { id: 6, prompt: "All cats are animals. Some animals are black. Are some cats black?", expected: "maybe/not definite" },
35
+ { id: 7, prompt: "What is machine learning?", expected: "learn" },
36
+ { id: 8, prompt: "Write a haiku about programming.", expected: "\n" },
37
+ ];
38
+
39
+ const PROVIDERS = {
40
+ 'groq-llama-3.1-8b': { name: 'Groq Llama 3.1 8B', endpoint: 'https://api.groq.com/openai/v1/chat/completions', model: 'llama-3.1-8b-instant', apiKeyEnv: 'GROQ_API_KEY' },
41
+ 'groq-llama-3.3-70b': { name: 'Groq Llama 3.3 70B', endpoint: 'https://api.groq.com/openai/v1/chat/completions', model: 'llama-3.3-70b-versatile', apiKeyEnv: 'GROQ_API_KEY' },
42
+ 'groq-allam-2-7b': { name: 'Groq Allam 2 7B', endpoint: 'https://api.groq.com/openai/v1/chat/completions', model: 'allam-2-7b', apiKeyEnv: 'GROQ_API_KEY' },
43
+ 'cerebras-llama3.1-8b': { name: 'Cerebras Llama 3.1 8B', endpoint: 'https://api.cerebras.ai/v1/chat/completions', model: 'llama3.1-8b', apiKeyEnv: 'CEREBRAS_API_KEY' },
44
+ 'cerebras-qwen-3-235b': { name: 'Cerebras Qwen 3 235B', endpoint: 'https://api.cerebras.ai/v1/chat/completions', model: 'qwen-3-235b-a22b-instruct-2507', apiKeyEnv: 'CEREBRAS_API_KEY' },
45
+ };
46
+
47
+ function callAPI(provider, prompt, maxTokens = 60) {
48
+ return new Promise((resolve) => {
49
+ const config = PROVIDERS[provider];
50
+ const start = Date.now();
51
+ const body = JSON.stringify({ model: config.model, messages: [{ role: 'user', content: prompt }], max_tokens: maxTokens, temperature: 0 });
52
+ const url = new URL(config.endpoint);
53
+
54
+ const req = https.request({
55
+ hostname: url.hostname, path: url.pathname, method: 'POST',
56
+ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env[config.apiKeyEnv]}`, 'Content-Length': Buffer.byteLength(body) }
57
+ }, (res) => {
58
+ let d = '';
59
+ res.on('data', c => d += c);
60
+ res.on('end', () => {
61
+ try {
62
+ const json = JSON.parse(d);
63
+ resolve({ success: true, latency: Date.now() - start, answer: json.choices?.[0]?.message?.content || '', status: res.statusCode });
64
+ } catch { resolve({ success: false, latency: Date.now() - start, error: d.slice(0, 80) }); }
65
+ });
66
+ });
67
+ req.on('error', e => resolve({ success: false, latency: 0, error: e.message }));
68
+ req.setTimeout(30000, () => { req.destroy(); resolve({ success: false, latency: 30000, error: 'Timeout' }); });
69
+ req.write(body); req.end();
70
+ });
71
+ }
72
+
73
+ function gradeMMLU(question, response) {
74
+ if (!response) return 0;
75
+ const text = response.toLowerCase().trim();
76
+
77
+ // Look for letter A/B/C/D
78
+ const letterMatch = text.match(/^(?:the answer is\s+)?([a-d])(?:\s|$)/i) || text.match(/^\s*([a-d])\s*$/i);
79
+ if (letterMatch) {
80
+ const answered = letterMatch[1].toLowerCase().charCodeAt(0) - 97;
81
+ return answered === question.answer ? 1 : 0;
82
+ }
83
+
84
+ // Full text match
85
+ const correctText = question.choices[question.answer].toLowerCase();
86
+ if (text.includes(correctText)) return 1;
87
+
88
+ // Key word match
89
+ const keyWords = correctText.split(' ').filter(w => w.length > 4);
90
+ if (keyWords.length > 0 && keyWords.some(w => text.includes(w))) return 1;
91
+
92
+ return 0;
93
+ }
94
+
95
+ function scoreQuality(response, question) {
96
+ if (!response) return 0;
97
+ const text = response.toLowerCase();
98
+ const expected = question.expected.toLowerCase();
99
+
100
+ // Check for expected keyword
101
+ if (text.includes(expected)) return 10;
102
+
103
+ // Partial credit based on length (well-formed response)
104
+ const len = response.length;
105
+ if (len > 20) return 5;
106
+ if (len > 5) return 2;
107
+ return 0;
108
+ }
109
+
110
+ async function main() {
111
+ const fs = require('fs');
112
+ console.log('\n🧠 A3M Router — Benchmark\n');
113
+
114
+ const results = {};
115
+
116
+ for (const [pid, config] of Object.entries(PROVIDERS)) {
117
+ if (!process.env[config.apiKeyEnv] || process.env[config.apiKeyEnv].length < 20) {
118
+ console.log(`ā­ļø ${config.name}: No API key`);
119
+ continue;
120
+ }
121
+
122
+ console.log(`\nšŸ“” ${config.name}...`);
123
+
124
+ // MMLU
125
+ let correct = 0;
126
+ const mmluResults = [];
127
+ for (const q of MMLU_QUESTIONS) {
128
+ const prompt = `${q.q}\nA) ${q.choices[0]}\nB) ${q.choices[1]}\nC) ${q.choices[2]}\nD) ${q.choices[3]}\n\nAnswer (just letter A/B/C/D):`;
129
+ const r = await callAPI(pid, prompt, 15);
130
+ const graded = gradeMMLU(q, r.answer);
131
+ correct += graded;
132
+ mmluResults.push({ q: q.q.slice(0, 35), response: r.answer?.slice(0, 20), correct: graded === 1 });
133
+ process.stdout.write(`${graded ? 'āœ…' : 'āŒ'} `);
134
+ await new Promise(r => setTimeout(r, 250));
135
+ }
136
+ console.log(`\n MMLU: ${correct}/15`);
137
+
138
+ // Quality test
139
+ let qualityScore = 0;
140
+ const qualResults = [];
141
+ for (const q of QUALITY_QUESTIONS) {
142
+ const r = await callAPI(pid, q.prompt, 100);
143
+ const score = scoreQuality(r.answer, q);
144
+ qualityScore += score;
145
+ qualResults.push({ prompt: q.prompt.slice(0, 30), response: r.answer?.slice(0, 30), score });
146
+ await new Promise(r2 => setTimeout(r2, 250));
147
+ }
148
+ const qualityAvg = qualityScore / QUALITY_QUESTIONS.length;
149
+ console.log(` Quality: ${qualityAvg.toFixed(1)}/10`);
150
+
151
+ results[pid] = {
152
+ name: config.name,
153
+ mmlu_accuracy: correct / 15,
154
+ quality_score: Math.round(qualityAvg * 10) / 10,
155
+ mmlu_detail: mmluResults,
156
+ quality_detail: qualResults,
157
+ };
158
+ }
159
+
160
+ console.log('\nšŸ“Š Results\n');
161
+ console.log('Provider | MMLU | Quality | Notes');
162
+ console.log('--------------------------|-------|---------|------');
163
+
164
+ for (const [pid, r] of Object.entries(results)) {
165
+ const mmlu = `${(r.mmlu_accuracy * 100).toFixed(0)}%`;
166
+ console.log(`${r.name.padEnd(25)}| ${mmlu.padStart(5)} | ${r.quality_score.toFixed(1).padStart(7)}/10 |`);
167
+ }
168
+
169
+ fs.writeFileSync('benchmark-results.json', JSON.stringify({
170
+ meta: { date: new Date().toISOString(), type: 'mmlu_quality' },
171
+ results
172
+ }, null, 2));
173
+ console.log('\nšŸ’¾ Saved to benchmark-results.json');
174
+ }
175
+
176
+ main().catch(console.error);