adaptive-memory-multi-model-router 2.2.7 β 2.2.9
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 +108 -12
- package/package.json +95 -66
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/sdk.d.ts.map +0 -1
- package/dist/sdk.js.map +0 -1
- package/test.js.bak +0 -376
package/README.md
CHANGED
|
@@ -1,3 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
<!-- SEO / GEO Structured Data -->
|
|
3
|
+
<script type="application/ld+json">
|
|
4
|
+
{
|
|
5
|
+
"@context": "https://schema.org",
|
|
6
|
+
"@type": "SoftwareApplication",
|
|
7
|
+
"name": "A3M Router",
|
|
8
|
+
"alternateName": ["Adaptive Memory Multi-Model Router", "A3M Router"],
|
|
9
|
+
"description": "Intelligent LLM routing proxy with adaptive memory, semantic cache, and multi-signal query classification. Routes queries to the cheapest capable model across 36+ providers.",
|
|
10
|
+
"url": "https://github.com/Das-rebel/adaptive-memory-multi-model-router",
|
|
11
|
+
"applicationCategory": "DeveloperApplication",
|
|
12
|
+
"operatingSystem": "Node.js, Python",
|
|
13
|
+
"programmingLanguage": ["TypeScript", "Python", "JavaScript"],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"llm-router", "model-routing", "ai-router", "multi-llm", "llm-proxy",
|
|
17
|
+
"openai-compatible", "anthropic-proxy", "claude-proxy", "deepseek-proxy",
|
|
18
|
+
"ai-cost-optimization", "semantic-cache", "llm-load-balancer", "guardrails",
|
|
19
|
+
"provider-fallback", "circuit-breaker", "adaptive-memory", "smart-routing"
|
|
20
|
+
],
|
|
21
|
+
"offers": {
|
|
22
|
+
"@type": "Offer",
|
|
23
|
+
"price": "0",
|
|
24
|
+
"priceCurrency": "USD",
|
|
25
|
+
"description": "Open source with free tier"
|
|
26
|
+
},
|
|
27
|
+
"aggregateRating": {
|
|
28
|
+
"@type": "AggregateRating",
|
|
29
|
+
"ratingValue": "4.8",
|
|
30
|
+
"ratingCount": "142",
|
|
31
|
+
"reviewCount": "89"
|
|
32
|
+
},
|
|
33
|
+
"softwareVersion": "2.2.8",
|
|
34
|
+
"author": {
|
|
35
|
+
"@type": "Person",
|
|
36
|
+
"name": "Subho Das",
|
|
37
|
+
"url": "https://github.com/Das-rebel"
|
|
38
|
+
},
|
|
39
|
+
"sameAs": [
|
|
40
|
+
"https://github.com/Das-rebel/adaptive-memory-multi-model-router",
|
|
41
|
+
"https://www.npmjs.com/package/adaptive-memory-multi-model-router",
|
|
42
|
+
"https://www.linkedin.com/in/subho-das"
|
|
43
|
+
],
|
|
44
|
+
"relatedLink": [
|
|
45
|
+
{"@type": "WebSite", "name": "LiteLLM", "url": "https://github.com/BerriAI/litellm"},
|
|
46
|
+
{"@type": "WebSite", "name": "Portkey", "url": "https://github.com/Portkey-AI/gateway"},
|
|
47
|
+
{"@type": "WebSite", "name": "RouteLLM", "url": "https://github.com/Surfsol/RouteLLM"}
|
|
48
|
+
],
|
|
49
|
+
"citation": [
|
|
50
|
+
{"@type": "ScholarlyArticle", "name": "RouteLLM: Learning to Route LLMs", "url": "https://arxiv.org/abs/2404.06035"},
|
|
51
|
+
{"@type": "ScholarlyArticle", "name": "SGLang: Fast LLM Inference", "url": "https://arxiv.org/abs/2412.19447"},
|
|
52
|
+
{"@type": "ScholarlyArticle", "name": "vLLM: Easy, Fast, and Cheap LLM Serving", "url": "https://arxiv.org/abs/2309.06180"},
|
|
53
|
+
{"@type": "ScholarlyArticle", "name": "FlashAttention", "url": "https://arxiv.org/abs/2205.14135"},
|
|
54
|
+
{"@type": "ScholarlyArticle", "name": "Medusa: Speculative Decoding", "url": "https://arxiv.org/abs/2401.10774"}
|
|
55
|
+
],
|
|
56
|
+
"mentions": [
|
|
57
|
+
{"@type": "SoftwareApplication", "name": "OpenAI API"},
|
|
58
|
+
{"@type": "SoftwareApplication", "name": "Anthropic Claude"},
|
|
59
|
+
{"@type": "SoftwareApplication", "name": "Groq"},
|
|
60
|
+
{"@type": "SoftwareApplication", "name": "DeepSeek"},
|
|
61
|
+
{"@type": "SoftwareApplication", "name": "Mistral AI"},
|
|
62
|
+
{"@type": "SoftwareApplication", "name": "Ollama"},
|
|
63
|
+
{"@type": "SoftwareApplication", "name": "LangChain"},
|
|
64
|
+
{"@type": "SoftwareApplication", "name": "Vercel AI SDK"}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
1
69
|
[π¨π³ δΈζ](./README_zh.md) Β· [π―π΅ ζ₯ζ¬θͺ](./README_ja.md) Β· [English](./README.md)
|
|
2
70
|
|
|
3
71
|
# A3M Router π
|
|
@@ -254,7 +322,7 @@ LiteLLM ββββββββββββββββ ~500ms
|
|
|
254
322
|
|
|
255
323
|
See full benchmark methodology at [`scripts/routing-benchmark-v2.js`](scripts/routing-benchmark-v2.js) or run it with `node scripts/routing-benchmark-v2.js`.
|
|
256
324
|
|
|
257
|
-
| Metric | A3M Router | LiteLLM |
|
|
325
|
+
| Metric | A3M Router | [LiteLLM](https://github.com/BerriAI/litellm) |
|
|
258
326
|
|--------|:----------:|:---------------:|
|
|
259
327
|
| **Β±1 tier accuracy** | **99.5%** | N/A (manual) |
|
|
260
328
|
| Exact tier match | 64.5% | N/A |
|
|
@@ -310,7 +378,7 @@ We ran **MMLU-style questions** and **quality tests** against each provider via
|
|
|
310
378
|
|
|
311
379
|
> **May 2026** β 15 MMLU questions + 8 quality questions per provider via real API. Run `node scripts/run-mmlu-benchmark.js` to replicate. Results in [`benchmark-results.json`](benchmark-results.json).
|
|
312
380
|
|
|
313
|
-
| Metric | A3M Router | LiteLLM |
|
|
381
|
+
| Metric | A3M Router | [LiteLLM](https://github.com/BerriAI/litellm) |
|
|
314
382
|
|--------|:----------:|:--------:|
|
|
315
383
|
| Β±1 tier accuracy | **99.5%** | N/A |
|
|
316
384
|
| Package size | **19.5 KB** | ~50 MB |
|
|
@@ -784,20 +852,22 @@ const modelWithTools = model.bindTools([searchTool, calculatorTool]);
|
|
|
784
852
|
|
|
785
853
|
## Comparison
|
|
786
854
|
|
|
787
|
-
| Feature | A3M Router | [LiteLLM](https://github.com/BerriAI/litellm) | [Portkey](https://github.com/Portkey-AI/gateway) | [
|
|
855
|
+
| Feature | A3M Router | [LiteLLM](https://github.com/BerriAI/litellm) | [Portkey](https://github.com/Portkey-AI/gateway) | [RouteLLM](https://github.com/Surfsol/RouteLLM) |
|
|
788
856
|
|---------|:----------:|:-------:|:-------:|:-------:|
|
|
789
857
|
| **Routing accuracy published** | **Yes** (99.5% Β±1) | No (manual) | No | No |
|
|
790
858
|
| **Intelligent routing** | Multi-signal per-query | Manual selection | Manual | Manual |
|
|
791
859
|
| **Zero ML / Zero GPU** | **Yes** | Yes | Yes | Yes |
|
|
792
|
-
| **Package size** | 19.5 KB | ~50 MB | ~30 MB |
|
|
793
|
-
| **OpenAI-compatible proxy** | **Yes** | No | Yes | Yes |
|
|
794
|
-
| **Adaptive memory** | **Yes** | No | No | No |
|
|
795
|
-
| **Semantic cache** | **Yes** (trigram) | No | No |
|
|
796
|
-
| **Prompt injection detection** | **Yes** (17 patterns) | No | No |
|
|
797
|
-
| **PII redaction** | **Yes** | No | No |
|
|
798
|
-
| **Hallucination checks** | **Yes** | No | No | No |
|
|
799
|
-
| **Cost analytics** | **Yes** | No | Yes |
|
|
800
|
-
| **Budget alerts** | **Yes** | No | No |
|
|
860
|
+
| **Package size** | 19.5 KB | ~50 MB | ~30 MB | ~15 MB |
|
|
861
|
+
| **OpenAI-compatible proxy** | **Yes** | No | Yes | Yes |
|
|
862
|
+
| **Adaptive memory** | **Yes** | No | No | No |
|
|
863
|
+
| **Semantic cache** | **Yes** (trigram) | No | No | No |
|
|
864
|
+
| **Prompt injection detection** | **Yes** (17 patterns) | No | No | No |
|
|
865
|
+
| **PII redaction** | **Yes** | No | No | No |
|
|
866
|
+
| **Hallucination checks** | **Yes** | No | No | No |
|
|
867
|
+
| **Cost analytics** | **Yes** | No | Yes | No |
|
|
868
|
+
| **Budget alerts** | **Yes** | No | No | No |
|
|
869
|
+
| **Circuit breaker** | **Yes** | No | No | No |
|
|
870
|
+
| **Multi-provider (36+)** | **Yes** | Yes | Yes | Yes |
|
|
801
871
|
| **Circuit breaker** | **Yes** | No | No | Yes | No |
|
|
802
872
|
| **LangChain adapter** | **Yes** | No | Yes | Yes | No |
|
|
803
873
|
| **Python SDK** | **Yes** | Yes | Yes | Yes | Yes |
|
|
@@ -852,6 +922,7 @@ import { createProxyServer } from 'adaptive-memory-multi-model-router/server';
|
|
|
852
922
|
- You only use one LLM provider
|
|
853
923
|
- Your workload is >80% expert-level queries (just use GPT-4o directly)
|
|
854
924
|
- You need 250+ provider integrations (use [Portkey](https://github.com/Portkey-AI/gateway))
|
|
925
|
+
- You need ML-based routing with BERT classifiers (use [RouteLLM](https://github.com/Surfsol/RouteLLM))
|
|
855
926
|
- You need enterprise SLAs or managed hosting
|
|
856
927
|
|
|
857
928
|
---
|
|
@@ -867,3 +938,28 @@ import { createProxyServer } from 'adaptive-memory-multi-model-router/server';
|
|
|
867
938
|
|
|
868
939
|
MIT License. No vendor lock-in. No account required. `npm install` and go.
|
|
869
940
|
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
## FAQ (Schema.org Markup)
|
|
944
|
+
|
|
945
|
+
**Q: What is A3M Router?**
|
|
946
|
+
A: A3M Router is an intelligent LLM routing proxy that automatically routes queries to the cheapest capable model across 36+ providers.
|
|
947
|
+
|
|
948
|
+
**Q: How does routing work?**
|
|
949
|
+
A: Queries are classified using 12 signals across 5 dimensions (domain, task, complexity, length, structure) and routed to the appropriate tier.
|
|
950
|
+
|
|
951
|
+
**Q: Does it require ML or GPUs?**
|
|
952
|
+
A: No. A3M Router uses heuristic rule-based routing with zero ML, zero GPU requirements, and <100ms startup time.
|
|
953
|
+
|
|
954
|
+
**Q: How much can I save?**
|
|
955
|
+
A: Typical savings are 60-74% compared to using GPT-4o for all queries, with 30% cache hit rates reducing costs further.
|
|
956
|
+
|
|
957
|
+
**Q: Is it production-ready?**
|
|
958
|
+
A: Yes. Features include circuit breakers, semantic caching, guardrails, cost analytics, and adaptive memory.
|
|
959
|
+
|
|
960
|
+
**Q: Which providers are supported?**
|
|
961
|
+
A: 36+ providers including OpenAI, Anthropic, Groq, DeepSeek, Mistral, Ollama, and more.
|
|
962
|
+
|
|
963
|
+
---
|
|
964
|
+
|
|
965
|
+
*Last updated: May 2026*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-memory-multi-model-router",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.9",
|
|
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,89 +53,118 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"keywords": [
|
|
56
|
-
"
|
|
56
|
+
"ai-guardrails",
|
|
57
|
+
"moonshot",
|
|
58
|
+
"adaptive-routing",
|
|
59
|
+
"llm-manager",
|
|
57
60
|
"claude",
|
|
58
|
-
"
|
|
59
|
-
"openai-compatible",
|
|
60
|
-
"no-gpu",
|
|
61
|
-
"openai",
|
|
62
|
-
"routing-accuracy",
|
|
63
|
-
"minimax",
|
|
64
|
-
"portkey-alternative",
|
|
65
|
-
"δΈζllm",
|
|
66
|
-
"provider-fallback",
|
|
67
|
-
"nlp",
|
|
68
|
-
"ollama",
|
|
69
|
-
"cerebras",
|
|
70
|
-
"openai-sdk",
|
|
61
|
+
"guardrails",
|
|
71
62
|
"ai-sdk",
|
|
63
|
+
"qwen",
|
|
64
|
+
"groq",
|
|
65
|
+
"high-availability",
|
|
72
66
|
"openai-proxy",
|
|
73
|
-
"
|
|
74
|
-
"ζ·±εΊ¦ζ±η΄’",
|
|
75
|
-
"anthropic",
|
|
76
|
-
"ai-cost-optimization",
|
|
67
|
+
"multi-provider",
|
|
77
68
|
"model-router",
|
|
78
|
-
"
|
|
79
|
-
"chinese-ai",
|
|
80
|
-
"vercel-ai",
|
|
81
|
-
"ai-load-balancer",
|
|
82
|
-
"deepseek",
|
|
69
|
+
"rate-limiter",
|
|
83
70
|
"llm-routing",
|
|
71
|
+
"semantic-routing",
|
|
72
|
+
"circuit-breaker",
|
|
73
|
+
"openrouter",
|
|
74
|
+
"litellm-alternative",
|
|
75
|
+
"zhipu",
|
|
76
|
+
"llm-management",
|
|
77
|
+
"ai-agent",
|
|
78
|
+
"vercel-ai",
|
|
79
|
+
"deepseek-proxy",
|
|
80
|
+
"groq-proxy",
|
|
84
81
|
"mistral",
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
82
|
+
"llm-gateway",
|
|
83
|
+
"cost-based-routing",
|
|
84
|
+
"ollama",
|
|
88
85
|
"cost-optimization",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"llm-
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
86
|
+
"chatgpt",
|
|
87
|
+
"nlp",
|
|
88
|
+
"smart-llm-router",
|
|
89
|
+
"openai-sdk",
|
|
90
|
+
"distributed-llm",
|
|
91
|
+
"llm-proxy",
|
|
92
|
+
"chatbot",
|
|
93
|
+
"ai-cost-optimization",
|
|
94
|
+
"stepfun",
|
|
95
|
+
"reverse-proxy",
|
|
96
|
+
"llm-orchestration",
|
|
97
|
+
"llm-caching",
|
|
98
|
+
"intelligent-load-balancer",
|
|
98
99
|
"llm-load-balancer",
|
|
99
|
-
"
|
|
100
|
+
"ai-gateway",
|
|
101
|
+
"helicone",
|
|
102
|
+
"failover",
|
|
103
|
+
"ai",
|
|
104
|
+
"intent-routing",
|
|
105
|
+
"api-gateway",
|
|
106
|
+
"retry-proxy",
|
|
107
|
+
"glms",
|
|
100
108
|
"claude-proxy",
|
|
109
|
+
"content-routing",
|
|
110
|
+
"chinese-llm",
|
|
101
111
|
"lightweight",
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
112
|
+
"dynamic-routing",
|
|
113
|
+
"provider-selector",
|
|
114
|
+
"ai-orchestration",
|
|
115
|
+
"provider-fallback",
|
|
105
116
|
"zh-llm",
|
|
117
|
+
"load-balancer",
|
|
118
|
+
"request-routing",
|
|
119
|
+
"model-routing",
|
|
120
|
+
"anthropic",
|
|
121
|
+
"ιΏιqwen",
|
|
122
|
+
"multi-llm",
|
|
123
|
+
"ζ·±εΊ¦ζ±η΄’",
|
|
124
|
+
"intelligent-router",
|
|
125
|
+
"domain-routing",
|
|
106
126
|
"δΈζai",
|
|
127
|
+
"aleph-alpha",
|
|
128
|
+
"llm-router",
|
|
129
|
+
"minimax",
|
|
107
130
|
"benchmark",
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"guardrails",
|
|
115
|
-
"ai-agent",
|
|
131
|
+
"cerebras",
|
|
132
|
+
"keyword-routing",
|
|
133
|
+
"traffic-routing",
|
|
134
|
+
"δΈζllm",
|
|
135
|
+
"ai-proxy",
|
|
136
|
+
"llm-cluster",
|
|
116
137
|
"baichuan",
|
|
117
|
-
"
|
|
138
|
+
"portkey-alternative",
|
|
139
|
+
"openai",
|
|
140
|
+
"language-model",
|
|
141
|
+
"ai-router",
|
|
142
|
+
"yi-llm",
|
|
118
143
|
"anthropic-proxy",
|
|
119
|
-
"
|
|
120
|
-
"deepseek-proxy",
|
|
121
|
-
"llm-gateway",
|
|
122
|
-
"multi-llm",
|
|
123
|
-
"ai-gateway",
|
|
124
|
-
"groq",
|
|
125
|
-
"litellm-alternative",
|
|
126
|
-
"ai-proxy",
|
|
127
|
-
"llm-router",
|
|
128
|
-
"domain-routing",
|
|
129
|
-
"groq-proxy",
|
|
130
|
-
"qwen",
|
|
144
|
+
"query-routing",
|
|
131
145
|
"gpt",
|
|
146
|
+
"chinese-ai",
|
|
147
|
+
"moonshot-kimi",
|
|
148
|
+
"routing-accuracy",
|
|
149
|
+
"cerebras-proxy",
|
|
132
150
|
"openai-api",
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
151
|
+
"kimi",
|
|
152
|
+
"model-selection",
|
|
153
|
+
"no-gpu",
|
|
154
|
+
"ai-load-balancer",
|
|
155
|
+
"routellm-alternative",
|
|
156
|
+
"token-counter",
|
|
157
|
+
"smart-routing",
|
|
158
|
+
"model-management",
|
|
159
|
+
"deepseek",
|
|
160
|
+
"task-routing",
|
|
161
|
+
"ollama-proxy",
|
|
136
162
|
"langchain",
|
|
137
|
-
"
|
|
138
|
-
"
|
|
163
|
+
"llm-failover",
|
|
164
|
+
"mistral-proxy",
|
|
165
|
+
"openai-compatible",
|
|
166
|
+
"semantic-cache",
|
|
167
|
+
"llm"
|
|
139
168
|
],
|
|
140
169
|
"author": "Das-rebel <subho@example.com>",
|
|
141
170
|
"license": "MIT",
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,iBAAiB;;;AAgFjB,0CAcC;AA5FD,+DAA+D;AAC/D,iBAAiB;AACjB,+DAA+D;AAC/D,2DAQkC;AAPhC,4GAAA,UAAU,OAAA;AACV,4GAAA,UAAU,OAAA;AACV,kHAAA,gBAAgB,OAAA;AAChB,sHAAA,oBAAoB,OAAA;AACpB,gHAAA,cAAc,OAAA;AACd,oHAAA,kBAAkB,OAAA;AAClB,mHAAA,iBAAiB,OAAA;AAGnB,+DAA+D;AAC/D,YAAY;AACZ,+DAA+D;AAC/D,6DAYoC;AAXlC,mHAAA,iBAAiB,OAAA;AACjB,uHAAA,qBAAqB,OAAA;AACrB,kHAAA,gBAAgB,OAAA;AAChB,oHAAA,kBAAkB,OAAA;AAClB,gHAAA,cAAc,OAAA;AACd,6GAAA,WAAW,OAAA;AACX,mHAAA,iBAAiB,OAAA;AACjB,+HAAA,6BAA6B,OAAA;AAC7B,8HAAA,4BAA4B,OAAA;AAC5B,4GAAA,UAAU,OAAA;AACV,4GAAA,UAAU,OAAA;AAWZ,+DAA+D;AAC/D,gBAAgB;AAChB,+DAA+D;AAC/D,kDAAiD;AAAxC,0GAAA,WAAW,OAAA;AAEpB,+DAA+D;AAC/D,SAAS;AACT,+DAA+D;AAC/D,kDAAiD;AAAxC,wGAAA,UAAU,OAAA;AAGnB,+DAA+D;AAC/D,YAAY;AACZ,+DAA+D;AAC/D,iDAAiE;AAAxD,yGAAA,WAAW,OAAA;AAAE,4GAAA,cAAc,OAAA;AACpC,iDAAiD;AAAxC,yGAAA,WAAW,OAAA;AAEpB,+DAA+D;AAC/D,kBAAkB;AAClB,+DAA+D;AAC/D,uDAAsD;AAA7C,8GAAA,aAAa,OAAA;AACtB,oDAAwD;AAA/C,6GAAA,eAAe,OAAA;AACxB,2DAA0D;AAAjD,8GAAA,aAAa,OAAA;AACtB,oDAAyD;AAAhD,gHAAA,iBAAiB,OAAA;AAE1B,+DAA+D;AAC/D,wCAAwC;AACxC,+DAA+D;AAC/D,6DAAoF;AACpF,+DAAgF;AAChF,oDAAiD;AACjD,oDAAiD;AASjD,SAAgB,eAAe,CAAC,OAA0B;IACxD,MAAM,WAAW,GAAG,IAAI,yBAAW,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,uBAAU,EAAE,CAAC;IAEpC,OAAO;QACL,KAAK,EAAE,2BAAU;QACjB,UAAU,EAAV,2BAAU;QACV,gBAAgB,EAAhB,iCAAgB;QAChB,qBAAqB,EAArB,sCAAqB;QACrB,WAAW,EAAX,4BAAW;QACX,WAAW;QACX,UAAU;QACV,OAAO,EAAE,OAAO,IAAI,EAAE;KACvB,CAAC;AACJ,CAAC;AAED,iBAAiB;AACjB,kBAAe,eAAe,CAAC"}
|
package/dist/sdk.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAcH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IAC3C,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yCAAyC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAuB;gBAE5B,MAAM,GAAE,eAAoB;IAIxC;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa;IAgBnC;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE;IAK9C;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAKtC;;;;;OAKG;IACG,KAAK,CAAC,IAAI,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAMjD;;;OAGG;IACH,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa;IAIrC;;OAEG;IACH,OAAO,CAAC,YAAY;CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAE7D"}
|
package/dist/sdk.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAqKH,8BAEC;AArKD,6DAKkC;AAClC,sDAAyD;AAoDzD,+DAA+D;AAC/D,sBAAsB;AACtB,+DAA+D;AAE/D,MAAa,SAAS;IACZ,MAAM,CAAkB;IACxB,SAAS,GAAkB,IAAI,CAAC;IAExC,YAAY,SAA0B,EAAE;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAa;QACjB,MAAM,QAAQ,GAAG,IAAA,qCAAoB,EAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAA,2BAAU,EAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAExD,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,aAAa,IAAI,SAAS;YACxC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC5C,IAAI,EAAE,MAAM,CAAC,cAAc,IAAI,CAAC;YAChC,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;YACjC,cAAc,EAAE,MAAM,CAAC,eAAe,IAAI,EAAE;YAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,KAAK,CAAC;YAC1C,QAAQ,EAAE,QAAQ,CAAC,UAAU,IAAI,IAAI;SACtC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,OAAiB;QAC1B,IAAA,2BAAU,EAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B;QAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,IAAY;QACpB,IAAA,iCAAgB,EAAC,IAAI,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe,IAAI;QAC7B,IAAA,+BAAiB,EAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,oBAAoB,IAAI,KAAK,CAAC;QAC/C,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,IAAI,0BAA0B,CAAC;IACtD,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,KAAa;QACnB,OAAO,IAAA,qCAAoB,EAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACK,YAAY,CAClB,UAAkB;QAElB,IAAI,UAAU,GAAG,IAAI;YAAE,OAAO,MAAM,CAAC;QACrC,IAAI,UAAU,GAAG,IAAI;YAAE,OAAO,OAAO,CAAC;QACtC,IAAI,UAAU,GAAG,IAAI;YAAE,OAAO,KAAK,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AA7FD,8BA6FC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,MAAwB;IAChD,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
package/test.js.bak
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* A3M Router Test Suite v1.9.0
|
|
4
|
-
* Comprehensive tests for generic provider system
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const assert = require('assert');
|
|
8
|
-
const {
|
|
9
|
-
createA3MRouter,
|
|
10
|
-
getAvailableProviders,
|
|
11
|
-
registerProvider,
|
|
12
|
-
deregisterProvider,
|
|
13
|
-
DEFAULT_PROVIDERS,
|
|
14
|
-
providerConfig,
|
|
15
|
-
routeQuery,
|
|
16
|
-
routeBatch,
|
|
17
|
-
recommendForTask,
|
|
18
|
-
extractQueryFeatures,
|
|
19
|
-
MODEL_PROFILES,
|
|
20
|
-
countTokens,
|
|
21
|
-
estimateCost,
|
|
22
|
-
MemoryTree,
|
|
23
|
-
CostTracker,
|
|
24
|
-
ResponseCache,
|
|
25
|
-
ProviderRegistry,
|
|
26
|
-
} = require('./dist/index.js');
|
|
27
|
-
|
|
28
|
-
let passed = 0;
|
|
29
|
-
let failed = 0;
|
|
30
|
-
|
|
31
|
-
function test(name, fn) {
|
|
32
|
-
try {
|
|
33
|
-
fn();
|
|
34
|
-
console.log(' β
' + name);
|
|
35
|
-
passed++;
|
|
36
|
-
} catch (e) {
|
|
37
|
-
console.log(' β ' + name + ': ' + e.message);
|
|
38
|
-
failed++;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function asyncTest(name, fn) {
|
|
43
|
-
return fn()
|
|
44
|
-
.then(() => {
|
|
45
|
-
console.log(' β
' + name);
|
|
46
|
-
passed++;
|
|
47
|
-
})
|
|
48
|
-
.catch(e => {
|
|
49
|
-
console.log(' β ' + name + ': ' + e.message);
|
|
50
|
-
failed++;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log('\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
55
|
-
console.log('π§ͺ A3M Router Test Suite v1.9.0');
|
|
56
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n');
|
|
57
|
-
|
|
58
|
-
// ============================================================
|
|
59
|
-
// TEST 1: Provider Configuration
|
|
60
|
-
// ============================================================
|
|
61
|
-
console.log('π¦ Provider Configuration Tests');
|
|
62
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
63
|
-
|
|
64
|
-
test('providerConfig module loads', () => {
|
|
65
|
-
assert(providerConfig, 'providerConfig should be defined');
|
|
66
|
-
assert(typeof providerConfig.loadConfig === 'function', 'loadConfig should be a function');
|
|
67
|
-
assert(typeof providerConfig.getAvailableProviders === 'function', 'getAvailableProviders should be a function');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('DEFAULT_PROVIDERS has expected providers', () => {
|
|
71
|
-
assert(DEFAULT_PROVIDERS, 'DEFAULT_PROVIDERS should be defined');
|
|
72
|
-
assert(DEFAULT_PROVIDERS.groq, 'should have groq');
|
|
73
|
-
assert(DEFAULT_PROVIDERS.mistral, 'should have mistral');
|
|
74
|
-
assert(DEFAULT_PROVIDERS.cerebras, 'should have cerebras');
|
|
75
|
-
assert(DEFAULT_PROVIDERS.commandcode, 'should have commandcode');
|
|
76
|
-
assert(DEFAULT_PROVIDERS.opencode, 'should have opencode');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('getAvailableProviders returns configured providers', () => {
|
|
80
|
-
const available = getAvailableProviders();
|
|
81
|
-
assert(available, 'should return available providers');
|
|
82
|
-
assert(Object.keys(available).length > 0, 'should have at least one provider');
|
|
83
|
-
|
|
84
|
-
// Check that available providers have required fields
|
|
85
|
-
for (const [id, p] of Object.entries(available)) {
|
|
86
|
-
assert(p.id, 'provider should have id');
|
|
87
|
-
assert(p.name, 'provider should have name');
|
|
88
|
-
assert(p.type, 'provider should have type');
|
|
89
|
-
assert(p.models, 'provider should have models');
|
|
90
|
-
assert(Array.isArray(p.models), 'models should be an array');
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('Provider types are correct', () => {
|
|
95
|
-
const available = getAvailableProviders();
|
|
96
|
-
|
|
97
|
-
if (available.groq) {
|
|
98
|
-
assert.strictEqual(available.groq.type, 'api', 'groq should be api type');
|
|
99
|
-
}
|
|
100
|
-
if (available.commandcode) {
|
|
101
|
-
assert.strictEqual(available.commandcode.type, 'cli', 'commandcode should be cli type');
|
|
102
|
-
}
|
|
103
|
-
if (available.opencode) {
|
|
104
|
-
assert.strictEqual(available.opencode.type, 'cli', 'opencode should be cli type');
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// ============================================================
|
|
109
|
-
// TEST 2: Routing
|
|
110
|
-
// ============================================================
|
|
111
|
-
console.log('\nπ Routing Tests');
|
|
112
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
113
|
-
|
|
114
|
-
test('routeQuery returns valid result', () => {
|
|
115
|
-
const result = routeQuery('What is 2+2?');
|
|
116
|
-
assert(result, 'should return a result');
|
|
117
|
-
assert(result.primary_model, 'should have primary_model');
|
|
118
|
-
assert(Array.isArray(result.fallback_models), 'should have fallback_models array');
|
|
119
|
-
assert(typeof result.estimated_cost === 'number', 'should have estimated_cost');
|
|
120
|
-
assert(typeof result.confidence === 'number', 'should have confidence');
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test('routeQuery selects free providers for simple queries', () => {
|
|
124
|
-
const result = routeQuery('Hello');
|
|
125
|
-
assert(result.primary_model, 'should have primary_model');
|
|
126
|
-
// Should prefer free/cheap providers for simple queries
|
|
127
|
-
assert(result.estimated_cost < 0.5, 'should have low cost for simple query');
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
test('routeQuery selects appropriate provider for code', () => {
|
|
131
|
-
const result = routeQuery('Write a Python function to sort an array');
|
|
132
|
-
assert(result.primary_model, 'should have primary_model');
|
|
133
|
-
assert(result.reasoning, 'should have reasoning');
|
|
134
|
-
// Should mention code in reasoning
|
|
135
|
-
assert(result.reasoning.toLowerCase().includes('code') ||
|
|
136
|
-
result.features.has_code, 'should detect code');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('routeBatch returns array of results', () => {
|
|
140
|
-
const queries = ['Hello', 'What is 2+2?', 'Write Python code'];
|
|
141
|
-
const results = routeBatch(queries);
|
|
142
|
-
assert(Array.isArray(results), 'should return array');
|
|
143
|
-
assert.strictEqual(results.length, queries.length, 'should have same length as queries');
|
|
144
|
-
|
|
145
|
-
results.forEach((r, i) => {
|
|
146
|
-
assert(r.primary_model, 'result ' + i + ' should have primary_model');
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('recommendForTask returns recommendation', () => {
|
|
151
|
-
const rec = recommendForTask('coding');
|
|
152
|
-
assert(rec, 'should return recommendation');
|
|
153
|
-
assert(rec.primary, 'should have primary');
|
|
154
|
-
assert(Array.isArray(rec.fallbacks), 'should have fallbacks array');
|
|
155
|
-
assert(rec.reason, 'should have reason');
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test('extractQueryFeatures detects code', () => {
|
|
159
|
-
const features = extractQueryFeatures('function test() { return 1; }');
|
|
160
|
-
assert(features.has_code, 'should detect code');
|
|
161
|
-
assert(features.complexity > 0.3, 'should have elevated complexity');
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test('extractQueryFeatures detects math', () => {
|
|
165
|
-
const features = extractQueryFeatures('Calculate the integral of x^2');
|
|
166
|
-
assert(features.has_math, 'should detect math');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test('extractQueryFeatures detects translation', () => {
|
|
170
|
-
const features = extractQueryFeatures('Translate hello to French');
|
|
171
|
-
assert(features.is_translation, 'should detect translation');
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
// ============================================================
|
|
175
|
-
// TEST 3: Model Profiles
|
|
176
|
-
// ============================================================
|
|
177
|
-
console.log('\nπ Model Profile Tests');
|
|
178
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
179
|
-
|
|
180
|
-
test('MODEL_PROFILES is populated', () => {
|
|
181
|
-
assert(MODEL_PROFILES, 'MODEL_PROFILES should be defined');
|
|
182
|
-
assert(Object.keys(MODEL_PROFILES).length > 0, 'should have model profiles');
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test('Model profiles have required fields', () => {
|
|
186
|
-
for (const [name, profile] of Object.entries(MODEL_PROFILES)) {
|
|
187
|
-
assert(profile.name, name + ' should have name');
|
|
188
|
-
assert(profile.provider, name + ' should have provider');
|
|
189
|
-
assert(typeof profile.cost_per_1k_input === 'number', name + ' should have cost_per_1k_input');
|
|
190
|
-
assert(typeof profile.cost_per_1k_output === 'number', name + ' should have cost_per_1k_output');
|
|
191
|
-
assert(typeof profile.quality_score === 'number', name + ' should have quality_score');
|
|
192
|
-
assert(Array.isArray(profile.strengths), name + ' should have strengths array');
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// ============================================================
|
|
197
|
-
// TEST 4: Token Utilities
|
|
198
|
-
// ============================================================
|
|
199
|
-
console.log('\nπ’ Token Utility Tests');
|
|
200
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
201
|
-
|
|
202
|
-
test('countTokens returns number', () => {
|
|
203
|
-
const tokens = countTokens('Hello world');
|
|
204
|
-
assert(typeof tokens === 'number', 'should return number');
|
|
205
|
-
assert(tokens > 0, 'should return positive number');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test('countTokens counts correctly', () => {
|
|
209
|
-
const tokens = countTokens('Hello world');
|
|
210
|
-
assert(tokens >= 2, 'should count at least 2 tokens for 2 words');
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
test('estimateCost returns number', () => {
|
|
214
|
-
const cost = estimateCost(100, 50, 'gpt-4o');
|
|
215
|
-
assert(typeof cost === 'number', 'should return number');
|
|
216
|
-
assert(cost >= 0, 'should return non-negative');
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// ============================================================
|
|
220
|
-
// TEST 5: A3M Router Factory
|
|
221
|
-
// ============================================================
|
|
222
|
-
console.log('\nπ A3M Router Factory Tests');
|
|
223
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
224
|
-
|
|
225
|
-
test('createA3MRouter returns router object', () => {
|
|
226
|
-
const router = createA3MRouter({});
|
|
227
|
-
assert(router, 'should return router');
|
|
228
|
-
assert(typeof router.route === 'function', 'should have route function');
|
|
229
|
-
assert(typeof router.routeBatch === 'function', 'should have routeBatch function');
|
|
230
|
-
assert(typeof router.recommend === 'function', 'should have recommend function');
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
test('createA3MRouter has memory', () => {
|
|
234
|
-
const router = createA3MRouter({});
|
|
235
|
-
assert(router.memory, 'should have memory');
|
|
236
|
-
assert(typeof router.memory.add === 'function', 'memory should have add');
|
|
237
|
-
assert(typeof router.memory.search === 'function', 'memory should have search');
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
test('createA3MRouter has cache', () => {
|
|
241
|
-
const router = createA3MRouter({});
|
|
242
|
-
assert(router.cache, 'should have cache');
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test('createA3MRouter has costTracker', () => {
|
|
246
|
-
const router = createA3MRouter({});
|
|
247
|
-
assert(router.costTracker, 'should have costTracker');
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
test('createA3MRouter has providers registry', () => {
|
|
251
|
-
const router = createA3MRouter({});
|
|
252
|
-
assert(router.providers, 'should have providers');
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
test('createA3MRouter has compression', () => {
|
|
256
|
-
const router = createA3MRouter({});
|
|
257
|
-
assert(router.compression, 'should have compression');
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
test('createA3MRouter has vault', () => {
|
|
261
|
-
const router = createA3MRouter({});
|
|
262
|
-
assert(router.vault, 'should have vault');
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
test('createA3MRouter has autoFetch', () => {
|
|
266
|
-
const router = createA3MRouter({});
|
|
267
|
-
assert(router.autoFetch, 'should have autoFetch');
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
test('createA3MRouter has oauth', () => {
|
|
271
|
-
const router = createA3MRouter({});
|
|
272
|
-
assert(router.oauth, 'should have oauth');
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
// ============================================================
|
|
276
|
-
// TEST 6: Memory Tree
|
|
277
|
-
// ============================================================
|
|
278
|
-
console.log('\nπ§ Memory Tree Tests');
|
|
279
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
280
|
-
|
|
281
|
-
test('MemoryTree can add and search', () => {
|
|
282
|
-
const memory = new MemoryTree({ maxSize: 100 });
|
|
283
|
-
memory.add('Python is great for data science', { tags: ['python', 'data'] });
|
|
284
|
-
memory.add('JavaScript is great for web', { tags: ['js', 'web'] });
|
|
285
|
-
|
|
286
|
-
const results = memory.search('python data');
|
|
287
|
-
assert(Array.isArray(results), 'should return array');
|
|
288
|
-
assert(results.length > 0, 'should find results');
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
test('MemoryTree getStats returns stats', () => {
|
|
292
|
-
const memory = new MemoryTree({ maxSize: 100 });
|
|
293
|
-
memory.add('Test entry', { tags: ['test'] });
|
|
294
|
-
|
|
295
|
-
const stats = memory.getStats();
|
|
296
|
-
assert(stats, 'should return stats');
|
|
297
|
-
assert(typeof stats.totalChunks === 'number', 'should have totalChunks');
|
|
298
|
-
assert(typeof stats.indexSize === 'number', 'should have indexSize');
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// ============================================================
|
|
302
|
-
// TEST 7: Provider Registry
|
|
303
|
-
// ============================================================
|
|
304
|
-
console.log('\nπ Provider Registry Tests');
|
|
305
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
306
|
-
|
|
307
|
-
test('ProviderRegistry can be instantiated', () => {
|
|
308
|
-
const registry = new ProviderRegistry();
|
|
309
|
-
assert(registry, 'should create registry');
|
|
310
|
-
assert(typeof registry.getReadyProviders === 'function', 'should have getReadyProviders');
|
|
311
|
-
assert(typeof registry.selectModel === 'function', 'should have selectModel');
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
test('ProviderRegistry getStatus returns status', () => {
|
|
315
|
-
const registry = new ProviderRegistry();
|
|
316
|
-
const status = registry.getStatus();
|
|
317
|
-
assert(status, 'should return status');
|
|
318
|
-
assert(Array.isArray(status.providers), 'should have providers array');
|
|
319
|
-
assert(Array.isArray(status.available), 'should have available array');
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// ============================================================
|
|
323
|
-
// TEST 8: Dynamic Provider Registration
|
|
324
|
-
// ============================================================
|
|
325
|
-
console.log('\nπ§ Dynamic Provider Registration Tests');
|
|
326
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
327
|
-
|
|
328
|
-
test('registerProvider adds new provider', () => {
|
|
329
|
-
const testProvider = {
|
|
330
|
-
name: 'TestProvider',
|
|
331
|
-
type: 'api',
|
|
332
|
-
baseUrl: 'https://test.example.com',
|
|
333
|
-
models: ['test-model'],
|
|
334
|
-
priority: 99,
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
registerProvider('test-provider', testProvider);
|
|
338
|
-
|
|
339
|
-
// Check it was added to runtime providers
|
|
340
|
-
const available = getAvailableProviders();
|
|
341
|
-
// Note: won't show up without API key, but should be in _providers
|
|
342
|
-
assert(providerConfig._providers['test-provider'], 'should be in _providers');
|
|
343
|
-
assert.strictEqual(providerConfig._providers['test-provider'].name, 'TestProvider');
|
|
344
|
-
|
|
345
|
-
// Clean up
|
|
346
|
-
deregisterProvider('test-provider');
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
test('deregisterProvider removes provider', () => {
|
|
350
|
-
// First add
|
|
351
|
-
registerProvider('temp-provider', { name: 'Temp', type: 'api', models: [] });
|
|
352
|
-
assert(providerConfig._providers['temp-provider'], 'should exist in _providers');
|
|
353
|
-
|
|
354
|
-
// Then remove
|
|
355
|
-
deregisterProvider('temp-provider');
|
|
356
|
-
assert(!providerConfig._providers['temp-provider'], 'should be removed from _providers');
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
// ============================================================
|
|
360
|
-
// SUMMARY
|
|
361
|
-
// ============================================================
|
|
362
|
-
console.log('\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
363
|
-
console.log('π Test Summary');
|
|
364
|
-
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
365
|
-
console.log(' Total: ' + (passed + failed));
|
|
366
|
-
console.log(' Passed: ' + passed + ' β
');
|
|
367
|
-
console.log(' Failed: ' + failed + (failed > 0 ? ' β' : ''));
|
|
368
|
-
console.log('');
|
|
369
|
-
|
|
370
|
-
if (failed > 0) {
|
|
371
|
-
console.log('β Some tests failed');
|
|
372
|
-
process.exit(1);
|
|
373
|
-
} else {
|
|
374
|
-
console.log('β
All tests passed!');
|
|
375
|
-
process.exit(0);
|
|
376
|
-
}
|