modelmix 4.5.24 → 4.5.28
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/MODELS.md +1 -1
- package/README.md +5 -0
- package/demo/images.js +1 -1
- package/demo/json.js +0 -1
- package/index.js +41 -31
- package/package.json +8 -8
- package/pnpm-workspace.yaml +4 -0
- package/skills/modelmix/SKILL.md +5 -8
- package/test/anthropic.test.js +46 -0
- package/test/glm.test.js +12 -0
- package/test/kimi.test.js +13 -0
- package/test/live.mcp.js +0 -40
- package/test/live.test.js +1 -55
package/MODELS.md
CHANGED
|
@@ -352,4 +352,4 @@ All providers inherit from `MixCustom` base class which provides common function
|
|
|
352
352
|
- Uses OpenAI-compatible API interface
|
|
353
353
|
- Requires `MINIMAX_API_KEY` environment variable
|
|
354
354
|
- Inherits all OpenAI functionality including tool calling
|
|
355
|
-
- Available models: `MiniMax-M2.5`, `MiniMax-M2.7`
|
|
355
|
+
- Available models: `MiniMax-M2.5`, `MiniMax-M2.7`, `MiniMax-M3`
|
package/README.md
CHANGED
|
@@ -136,6 +136,7 @@ Here's a comprehensive list of available methods:
|
|
|
136
136
|
|
|
137
137
|
| Method | Provider | Model | Price (I/O) per 1 M tokens |
|
|
138
138
|
| ------------------- | ---------- | ---------------------------- | -------------------------- |
|
|
139
|
+
| `gpt55()` | OpenAI | gpt-5.5 | [\$5.00 / \$30.00][1] |
|
|
139
140
|
| `gpt54()` | OpenAI | gpt-5.4 | [\$2.50 / \$15.00][1] |
|
|
140
141
|
| `gpt54mini()` | OpenAI | gpt-5.4-mini | [\$0.75 / \$4.50][1] |
|
|
141
142
|
| `gpt54nano()` | OpenAI | gpt-5.4-nano | [\$0.20 / \$1.25][1] |
|
|
@@ -148,8 +149,10 @@ Here's a comprehensive list of available methods:
|
|
|
148
149
|
| `gpt41mini()` | OpenAI | gpt-4.1-mini | [\$0.40 / \$1.60][1] |
|
|
149
150
|
| `gpt41nano()` | OpenAI | gpt-4.1-nano | [\$0.10 / \$0.40][1] |
|
|
150
151
|
| `gptOss()` | Together | gpt-oss-120B | [\$0.15 / \$0.60][7] |
|
|
152
|
+
| `opus48[think]()` | Anthropic | claude-opus-4-8 | [\$5.00 / \$25.00][2] |
|
|
151
153
|
| `opus47[think]()` | Anthropic | claude-opus-4-7 | [\$5.00 / \$25.00][2] |
|
|
152
154
|
| `opus46[think]()` | Anthropic | claude-opus-4-6 | [\$5.00 / \$25.00][2] |
|
|
155
|
+
| `sonnet5[think]()` | Anthropic | claude-sonnet-5 | [\$3.00 / \$15.00][2] |
|
|
153
156
|
| `sonnet46[think]()` | Anthropic | claude-sonnet-4-6 | [\$3.00 / \$15.00][2] |
|
|
154
157
|
| `haiku45[think]()` | Anthropic | claude-haiku-4-5-20251001 | [\$1.00 / \$5.00][2] |
|
|
155
158
|
| `gemini31pro()` | Google | gemini-3.1-pro-preview | [\$2.00 / \$12.00][3] |
|
|
@@ -161,7 +164,9 @@ Here's a comprehensive list of available methods:
|
|
|
161
164
|
| `grok41[think]()` | Grok | grok-4-1-fast | [\$0.20 / \$0.50][6] |
|
|
162
165
|
| `qwen36plus()` | Fireworks/Together | qwen3p6-plus / Qwen3.6-Plus | [\$0.50 / \$3.00][10] |
|
|
163
166
|
| `deepseekV4Pro()` | Fireworks | models/deepseek-v4-pro | [\$1.74 / \$3.48][10] |
|
|
167
|
+
| `GLM52()` | Together | zai-org/GLM-5.2 | [\$1.40 / \$4.40][7] |
|
|
164
168
|
| `GLM51()` | Fireworks | models/glm-5p1 | [\$1.05 / \$3.50][10] |
|
|
169
|
+
| `minimaxM3()` | MiniMax | MiniMax-M3 | [\$0.30 / \$1.20][9] |
|
|
165
170
|
| `minimaxM27()` | MiniMax | MiniMax-M2.7 | [\$0.30 / \$1.20][9] |
|
|
166
171
|
| `sonar()` | Perplexity | sonar | [\$1.00 / \$1.00][4] |
|
|
167
172
|
| `sonarPro()` | Perplexity | sonar-pro | [\$3.00 / \$15.00][4] |
|
package/demo/images.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ModelMix } from '../index.js';
|
|
2
2
|
try { process.loadEnvFile(); } catch {}
|
|
3
3
|
|
|
4
|
-
const model = ModelMix.new({ config: { max_history: 2, debug: 2 } }).
|
|
4
|
+
const model = ModelMix.new({ config: { max_history: 2, debug: 2 } }).grok43()
|
|
5
5
|
// model.addImageFromUrl('https://pbs.twimg.com/media/F6-GsjraAAADDGy?format=jpg');
|
|
6
6
|
model.addImage('./img.png');
|
|
7
7
|
model.addText('in one word, which is the main color of the image?');
|
package/demo/json.js
CHANGED
package/index.js
CHANGED
|
@@ -58,9 +58,10 @@ const MODEL_PRICING = {
|
|
|
58
58
|
'gpt-oss-120b': [0.15, 0.60],
|
|
59
59
|
'openai/gpt-oss-120b:free': [0, 0],
|
|
60
60
|
// Anthropic
|
|
61
|
+
'claude-sonnet-5': [3.00, 15.00],
|
|
62
|
+
'claude-opus-4-8': [5.00, 25.00],
|
|
61
63
|
'claude-opus-4-7': [5.00, 25.00],
|
|
62
64
|
'claude-opus-4-6': [5.00, 25.00],
|
|
63
|
-
'claude-opus-4-5-20251101': [5.00, 25.00],
|
|
64
65
|
'claude-opus-4-1-20250805': [15.00, 75.00],
|
|
65
66
|
'claude-sonnet-4-6': [3.00, 15.00],
|
|
66
67
|
'claude-sonnet-4-5-20250929': [3.00, 15.00],
|
|
@@ -87,6 +88,7 @@ const MODEL_PRICING = {
|
|
|
87
88
|
'deepseek-ai/DeepSeek-V4-Pro': [2.10, 4.40],
|
|
88
89
|
'accounts/fireworks/models/glm-4p7': [0.55, 2.19],
|
|
89
90
|
'accounts/fireworks/models/glm-5p1': [1.05, 3.50],
|
|
91
|
+
'zai-org/GLM-5.2': [1.40, 4.40],
|
|
90
92
|
'accounts/fireworks/models/kimi-k2p5': [0.50, 2.80],
|
|
91
93
|
'accounts/fireworks/models/qwen3p6-plus': [0.50, 3.00],
|
|
92
94
|
'Qwen/Qwen3.6-Plus': [0.50, 3.00],
|
|
@@ -94,19 +96,14 @@ const MODEL_PRICING = {
|
|
|
94
96
|
// MiniMax
|
|
95
97
|
'MiniMax-M2.5': [0.30, 1.20],
|
|
96
98
|
'MiniMax-M2.7': [0.30, 1.20],
|
|
99
|
+
'MiniMax-M3': [0.30, 1.20],
|
|
97
100
|
'fireworks/minimax-m2p5': [0.30, 1.20],
|
|
98
101
|
'minimax/minimax-m2.7': [0.30, 1.20],
|
|
102
|
+
'minimax/minimax-m3': [0.30, 1.20],
|
|
103
|
+
'MiniMaxAI/MiniMax-M3': [0.30, 1.20],
|
|
99
104
|
// Perplexity
|
|
100
105
|
'sonar': [1.00, 1.00],
|
|
101
106
|
'sonar-pro': [3.00, 15.00],
|
|
102
|
-
// Scout (Groq/Together/Cerebras)
|
|
103
|
-
'meta-llama/llama-4-scout-17b-16e-instruct': [0.11, 0.34],
|
|
104
|
-
'meta-llama/Llama-4-Scout-17B-16E-Instruct': [0.11, 0.34],
|
|
105
|
-
'llama-4-scout-17b-16e-instruct': [0.11, 0.34],
|
|
106
|
-
// Maverick (Groq/Together/Lambda)
|
|
107
|
-
'meta-llama/llama-4-maverick-17b-128e-instruct': [0.20, 0.60],
|
|
108
|
-
'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8': [0.20, 0.60],
|
|
109
|
-
'llama-4-maverick-17b-128e-instruct-fp8': [0.20, 0.60],
|
|
110
107
|
// Hermes3 (Lambda/OpenRouter)
|
|
111
108
|
'Hermes-3-Llama-3.1-405B-FP8': [0.80, 0.80],
|
|
112
109
|
'nousresearch/hermes-3-llama-3.1-405b:free': [0, 0],
|
|
@@ -348,6 +345,10 @@ class ModelMix {
|
|
|
348
345
|
if (mix.openrouter) this.attach('openai/gpt-oss-120b:free', new MixOpenRouter({ options, config }));
|
|
349
346
|
return this;
|
|
350
347
|
}
|
|
348
|
+
opus48think({ options = {}, config = {} } = {}) {
|
|
349
|
+
options = { ...MixAnthropic.thinkingOptions, ...options };
|
|
350
|
+
return this.attach('claude-opus-4-8', new MixAnthropic({ options, config }));
|
|
351
|
+
}
|
|
351
352
|
opus47think({ options = {}, config = {} } = {}) {
|
|
352
353
|
options = { ...MixAnthropic.thinkingOptions, ...options };
|
|
353
354
|
return this.attach('claude-opus-4-7', new MixAnthropic({ options, config }));
|
|
@@ -356,9 +357,8 @@ class ModelMix {
|
|
|
356
357
|
options = { ...MixAnthropic.thinkingOptions, ...options };
|
|
357
358
|
return this.attach('claude-opus-4-6', new MixAnthropic({ options, config }));
|
|
358
359
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
return this.attach('claude-opus-4-5-20251101', new MixAnthropic({ options, config }));
|
|
360
|
+
opus48({ options = {}, config = {} } = {}) {
|
|
361
|
+
return this.attach('claude-opus-4-8', new MixAnthropic({ options, config }));
|
|
362
362
|
}
|
|
363
363
|
opus47({ options = {}, config = {} } = {}) {
|
|
364
364
|
return this.attach('claude-opus-4-7', new MixAnthropic({ options, config }));
|
|
@@ -366,9 +366,6 @@ class ModelMix {
|
|
|
366
366
|
opus46({ options = {}, config = {} } = {}) {
|
|
367
367
|
return this.attach('claude-opus-4-6', new MixAnthropic({ options, config }));
|
|
368
368
|
}
|
|
369
|
-
opus45({ options = {}, config = {} } = {}) {
|
|
370
|
-
return this.attach('claude-opus-4-5-20251101', new MixAnthropic({ options, config }));
|
|
371
|
-
}
|
|
372
369
|
opus41({ options = {}, config = {} } = {}) {
|
|
373
370
|
return this.attach('claude-opus-4-1-20250805', new MixAnthropic({ options, config }));
|
|
374
371
|
}
|
|
@@ -376,6 +373,13 @@ class ModelMix {
|
|
|
376
373
|
options = { ...MixAnthropic.thinkingOptions, ...options };
|
|
377
374
|
return this.attach('claude-opus-4-1-20250805', new MixAnthropic({ options, config }));
|
|
378
375
|
}
|
|
376
|
+
sonnet5({ options = {}, config = {} } = {}) {
|
|
377
|
+
return this.attach('claude-sonnet-5', new MixAnthropic({ options, config }));
|
|
378
|
+
}
|
|
379
|
+
sonnet5think({ options = {}, config = {} } = {}) {
|
|
380
|
+
options = { ...MixAnthropic.thinkingOptions, ...options };
|
|
381
|
+
return this.attach('claude-sonnet-5', new MixAnthropic({ options, config }));
|
|
382
|
+
}
|
|
379
383
|
sonnet4({ options = {}, config = {} } = {}) {
|
|
380
384
|
return this.attach('claude-sonnet-4-20250514', new MixAnthropic({ options, config }));
|
|
381
385
|
}
|
|
@@ -468,20 +472,6 @@ class ModelMix {
|
|
|
468
472
|
return this;
|
|
469
473
|
}
|
|
470
474
|
|
|
471
|
-
scout({ options = {}, config = {}, mix = {} } = {}) {
|
|
472
|
-
mix = { ...this.mix, ...mix };
|
|
473
|
-
if (mix.groq) this.attach('meta-llama/llama-4-scout-17b-16e-instruct', new MixGroq({ options, config }));
|
|
474
|
-
if (mix.together) this.attach('meta-llama/Llama-4-Scout-17B-16E-Instruct', new MixTogether({ options, config }));
|
|
475
|
-
if (mix.cerebras) this.attach('llama-4-scout-17b-16e-instruct', new MixCerebras({ options, config }));
|
|
476
|
-
return this;
|
|
477
|
-
}
|
|
478
|
-
maverick({ options = {}, config = {}, mix = {} } = {}) {
|
|
479
|
-
mix = { ...this.mix, ...mix };
|
|
480
|
-
if (mix.together) this.attach('meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8', new MixTogether({ options, config }));
|
|
481
|
-
if (mix.lambda) this.attach('llama-4-maverick-17b-128e-instruct-fp8', new MixLambda({ options, config }));
|
|
482
|
-
return this;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
475
|
deepseekR1({ options = {}, config = {}, mix = {} } = {}) {
|
|
486
476
|
mix = { ...this.mix, ...mix };
|
|
487
477
|
if (mix.groq) this.attach('deepseek-r1-distill-llama-70b', new MixGroq({ options, config }));
|
|
@@ -506,6 +496,12 @@ class ModelMix {
|
|
|
506
496
|
return this;
|
|
507
497
|
}
|
|
508
498
|
|
|
499
|
+
kimiK27Code({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
500
|
+
mix = { ...this.mix, ...mix };
|
|
501
|
+
if (mix.together) this.attach('moonshotai/Kimi-K2.7-Code', new MixTogether({ options, config }));
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
|
|
509
505
|
kimiK25think({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
510
506
|
mix = { ...this.mix, ...mix };
|
|
511
507
|
if (mix.together) this.attach('moonshotai/Kimi-K2.5', new MixTogether({ options, config }));
|
|
@@ -535,17 +531,25 @@ class ModelMix {
|
|
|
535
531
|
return this;
|
|
536
532
|
}
|
|
537
533
|
|
|
534
|
+
minimaxM3({ options = {}, config = {}, mix = { minimax: true, openrouter: false } } = {}) {
|
|
535
|
+
mix = { ...this.mix, ...mix };
|
|
536
|
+
if (mix.minimax) this.attach('MiniMax-M3', new MixMiniMax({ options, config }));
|
|
537
|
+
if (mix.openrouter) this.attach('minimax/minimax-m3', new MixOpenRouter({ options, config }));
|
|
538
|
+
if (mix.together) this.attach('MiniMaxAI/MiniMax-M3', new MixTogether({ options, config }));
|
|
539
|
+
return this;
|
|
540
|
+
}
|
|
541
|
+
|
|
538
542
|
mimo25({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
539
543
|
mix = { ...this.mix, ...mix };
|
|
540
|
-
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5', new MixOpenRouter({ options, config }));
|
|
541
544
|
if (mix.mimo) this.attach('mimo-v2.5', new MixMiMo({ options, config }));
|
|
545
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5', new MixOpenRouter({ options, config }));
|
|
542
546
|
return this;
|
|
543
547
|
}
|
|
544
548
|
|
|
545
549
|
mimo25pro({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
546
550
|
mix = { ...this.mix, ...mix };
|
|
547
|
-
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5-pro', new MixOpenRouter({ options, config }));
|
|
548
551
|
if (mix.mimo) this.attach('mimo-v2.5-pro', new MixMiMo({ options, config }));
|
|
552
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5-pro', new MixOpenRouter({ options, config }));
|
|
549
553
|
return this;
|
|
550
554
|
}
|
|
551
555
|
|
|
@@ -573,6 +577,12 @@ class ModelMix {
|
|
|
573
577
|
return this;
|
|
574
578
|
}
|
|
575
579
|
|
|
580
|
+
GLM52({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
581
|
+
mix = { ...this.mix, ...mix };
|
|
582
|
+
if (mix.together) this.attach('zai-org/GLM-5.2', new MixTogether({ options, config }));
|
|
583
|
+
return this;
|
|
584
|
+
}
|
|
585
|
+
|
|
576
586
|
GLM5({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
|
|
577
587
|
mix = { ...this.mix, ...mix };
|
|
578
588
|
if (mix.fireworks) this.attach('fireworks/glm-5', new MixFireworks({ options, config }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelmix",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.28",
|
|
4
4
|
"description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
51
|
"bottleneck": "^2.19.5",
|
|
52
|
-
"file-type": "^21.3.
|
|
53
|
-
"lemonlog": "^1.2.
|
|
54
|
-
"ws": "^8.
|
|
52
|
+
"file-type": "^21.3.4",
|
|
53
|
+
"lemonlog": "^1.2.2",
|
|
54
|
+
"ws": "^8.21.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"chai": "^5.
|
|
57
|
+
"chai": "^5.3.3",
|
|
58
58
|
"mocha": "^11.7.5",
|
|
59
|
-
"nock": "^14.0.
|
|
60
|
-
"sinon": "^21.
|
|
59
|
+
"nock": "^14.0.15",
|
|
60
|
+
"sinon": "^21.1.2"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"test": "mocha test/**/*.js --timeout 10000 --require test/setup.js",
|
|
@@ -70,6 +70,6 @@
|
|
|
70
70
|
"test:live": "mocha test/live.test.js --timeout 10000 --require test/setup.js",
|
|
71
71
|
"test:live.mcp": "mocha test/live.mcp.js --timeout 60000 --require test/setup.js",
|
|
72
72
|
"test:tokens": "mocha test/tokens.test.js --timeout 10000 --require test/setup.js",
|
|
73
|
-
"test:offline": "mocha test/json.test.js test/fallback.test.js test/templates.test.js test/images.test.js test/bottleneck.test.js test/tokens.test.js test/history.test.js --timeout 10000 --require test/setup.js"
|
|
73
|
+
"test:offline": "mocha test/json.test.js test/fallback.test.js test/templates.test.js test/images.test.js test/bottleneck.test.js test/tokens.test.js test/history.test.js test/anthropic.test.js --timeout 10000 --require test/setup.js"
|
|
74
74
|
}
|
|
75
75
|
}
|
package/pnpm-workspace.yaml
CHANGED
package/skills/modelmix/SKILL.md
CHANGED
|
@@ -96,9 +96,9 @@ If `sonnet46` fails, it automatically tries `gpt52`, then `gemini3flash`.
|
|
|
96
96
|
`gpt52()` `gpt52chat()` `gpt51()` `gpt5()` `gpt5mini()` `gpt5nano()` `gpt45()` `gpt41()` `gpt41mini()` `gpt41nano()` `o3()` `o4mini()`
|
|
97
97
|
|
|
98
98
|
### Anthropic
|
|
99
|
-
`
|
|
99
|
+
`opus48()` `opus47()` `opus46()` `opus41()` `sonnet5()` `sonnet46()` `sonnet45()` `sonnet4()` `haiku45()` `haiku35()`
|
|
100
100
|
|
|
101
|
-
Thinking variants: append `think` — e.g. `opus46think()` `
|
|
101
|
+
Thinking variants: append `think` — e.g. `opus48think()` `opus47think()` `opus46think()` `sonnet5think()` `sonnet46think()` `sonnet45think()` `sonnet4think()` `opus41think()` `haiku45think()`
|
|
102
102
|
|
|
103
103
|
### Google
|
|
104
104
|
`gemini3pro()` `gemini3flash()` `gemini35flash()` `gemini25pro()` `gemini25flash()`
|
|
@@ -109,14 +109,11 @@ Thinking variants: append `think` — e.g. `opus46think()` `sonnet46think()` `so
|
|
|
109
109
|
### Perplexity
|
|
110
110
|
`sonar()` `sonarPro()`
|
|
111
111
|
|
|
112
|
-
### Groq
|
|
113
|
-
`scout()` `maverick()`
|
|
114
|
-
|
|
115
112
|
### Together
|
|
116
|
-
`qwen36plus()` `kimiK25think()` `gptOss()`
|
|
113
|
+
`qwen36plus()` `GLM52()` `kimiK25think()` `gptOss()`
|
|
117
114
|
|
|
118
115
|
### MiniMax
|
|
119
|
-
`minimaxM25()` `minimaxM27()`
|
|
116
|
+
`minimaxM25()` `minimaxM27()` `minimaxM3()`
|
|
120
117
|
|
|
121
118
|
### Fireworks
|
|
122
119
|
`deepseekV32()` `GLM5()` `GLM47()`
|
|
@@ -128,7 +125,7 @@ Thinking variants: append `think` — e.g. `opus46think()` `sonnet46think()` `so
|
|
|
128
125
|
`GLM45()`
|
|
129
126
|
|
|
130
127
|
### Multi-provider (auto-fallback across free/paid tiers)
|
|
131
|
-
`deepseekR1()` `hermes3()` `
|
|
128
|
+
`deepseekR1()` `hermes3()` `kimiK25think()` `GLM47()`
|
|
132
129
|
|
|
133
130
|
### Local
|
|
134
131
|
`lmstudio()` — for LM Studio local models
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { expect } = require('chai');
|
|
2
|
+
const { ModelMix, MixAnthropic } = require('../index.js');
|
|
3
|
+
|
|
4
|
+
describe('Anthropic Model Registration Tests', () => {
|
|
5
|
+
it('should register Claude Opus 4.8', () => {
|
|
6
|
+
const model = ModelMix.new();
|
|
7
|
+
model.opus48();
|
|
8
|
+
|
|
9
|
+
expect(model.models).to.have.length(1);
|
|
10
|
+
expect(model.models[0].key).to.equal('claude-opus-4-8');
|
|
11
|
+
expect(model.models[0].provider).to.be.instanceOf(MixAnthropic);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should register Claude Opus 4.8 with thinking enabled', () => {
|
|
15
|
+
const model = ModelMix.new();
|
|
16
|
+
model.opus48think();
|
|
17
|
+
|
|
18
|
+
expect(model.models).to.have.length(1);
|
|
19
|
+
expect(model.models[0].key).to.equal('claude-opus-4-8');
|
|
20
|
+
expect(model.models[0].provider.options.thinking).to.deep.equal({
|
|
21
|
+
type: 'enabled',
|
|
22
|
+
budget_tokens: 1638
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should register Claude Sonnet 5', () => {
|
|
27
|
+
const model = ModelMix.new();
|
|
28
|
+
model.sonnet5();
|
|
29
|
+
|
|
30
|
+
expect(model.models).to.have.length(1);
|
|
31
|
+
expect(model.models[0].key).to.equal('claude-sonnet-5');
|
|
32
|
+
expect(model.models[0].provider).to.be.instanceOf(MixAnthropic);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should register Claude Sonnet 5 with thinking enabled', () => {
|
|
36
|
+
const model = ModelMix.new();
|
|
37
|
+
model.sonnet5think();
|
|
38
|
+
|
|
39
|
+
expect(model.models).to.have.length(1);
|
|
40
|
+
expect(model.models[0].key).to.equal('claude-sonnet-5');
|
|
41
|
+
expect(model.models[0].provider.options.thinking).to.deep.equal({
|
|
42
|
+
type: 'enabled',
|
|
43
|
+
budget_tokens: 1638
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
package/test/glm.test.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { expect } = require('chai');
|
|
2
|
+
const { ModelMix } = require('../index.js');
|
|
3
|
+
|
|
4
|
+
describe('GLM Model Registration Tests', () => {
|
|
5
|
+
it('should register Together GLM 5.2 by default', () => {
|
|
6
|
+
const model = ModelMix.new();
|
|
7
|
+
model.GLM52();
|
|
8
|
+
|
|
9
|
+
expect(model.models).to.have.length(1);
|
|
10
|
+
expect(model.models[0].key).to.equal('zai-org/GLM-5.2');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { expect } = require('chai');
|
|
2
|
+
const { ModelMix, MixTogether } = require('../index.js');
|
|
3
|
+
|
|
4
|
+
describe('Kimi Model Registration Tests', () => {
|
|
5
|
+
it('should register Together Kimi K2.7 Code by default', () => {
|
|
6
|
+
const model = ModelMix.new();
|
|
7
|
+
model.kimiK27Code();
|
|
8
|
+
|
|
9
|
+
expect(model.models).to.have.length(1);
|
|
10
|
+
expect(model.models[0].key).to.equal('moonshotai/Kimi-K2.7-Code');
|
|
11
|
+
expect(model.models[0].provider).to.be.instanceOf(MixTogether);
|
|
12
|
+
});
|
|
13
|
+
});
|
package/test/live.mcp.js
CHANGED
|
@@ -254,46 +254,6 @@ describe('Live MCP Integration Tests', function () {
|
|
|
254
254
|
expect(response).to.match(/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i);
|
|
255
255
|
});
|
|
256
256
|
|
|
257
|
-
it('should use MCP tools with Scout model', async function () {
|
|
258
|
-
const model = ModelMix.new(setup).scout();
|
|
259
|
-
|
|
260
|
-
// Add text processing tool
|
|
261
|
-
model.addTool({
|
|
262
|
-
name: "text_analysis",
|
|
263
|
-
description: "Analyze text and provide statistics",
|
|
264
|
-
inputSchema: {
|
|
265
|
-
type: "object",
|
|
266
|
-
properties: {
|
|
267
|
-
text: {
|
|
268
|
-
type: "string",
|
|
269
|
-
description: "Text to analyze"
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
required: ["text"]
|
|
273
|
-
}
|
|
274
|
-
}, async ({ text }) => {
|
|
275
|
-
const words = text.split(/\s+/).filter(word => word.length > 0);
|
|
276
|
-
const chars = text.length;
|
|
277
|
-
const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0).length;
|
|
278
|
-
|
|
279
|
-
return `Text Analysis:
|
|
280
|
-
- Characters: ${chars}
|
|
281
|
-
- Words: ${words.length}
|
|
282
|
-
- Sentences: ${sentences}
|
|
283
|
-
- Average word length: ${(chars / words.length).toFixed(1)} characters`;
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
model.setSystem('You are a text analysis assistant. Use the text_analysis tool to analyze text.');
|
|
287
|
-
model.addText('Analyze this text: "Hello world! This is a test sentence for analysis. How many words are there?"');
|
|
288
|
-
|
|
289
|
-
const response = await model.message();
|
|
290
|
-
console.log(`Scout with MCP tools: ${response}`);
|
|
291
|
-
|
|
292
|
-
expect(response).to.be.a('string');
|
|
293
|
-
expect(response).to.include('Characters:');
|
|
294
|
-
expect(response).to.include('Words:');
|
|
295
|
-
});
|
|
296
|
-
|
|
297
257
|
it('should use MCP tools with GPT-5 Mini', async function () {
|
|
298
258
|
const model = ModelMix.new(setup).gpt5mini();
|
|
299
259
|
|
package/test/live.test.js
CHANGED
|
@@ -31,7 +31,7 @@ describe('Live Integration Tests', function () {
|
|
|
31
31
|
|
|
32
32
|
describe('Image Processing', function () {
|
|
33
33
|
|
|
34
|
-
it('should process images with OpenAI GPT-
|
|
34
|
+
it('should process images with OpenAI GPT-5 Nano', async function () {
|
|
35
35
|
const model = ModelMix.new(setup).gpt5nano();
|
|
36
36
|
|
|
37
37
|
model.addImageFromUrl(blueSquareBase64)
|
|
@@ -180,18 +180,6 @@ describe('Live Integration Tests', function () {
|
|
|
180
180
|
|
|
181
181
|
describe('Additional Model Tests', function () {
|
|
182
182
|
|
|
183
|
-
it('should work with Scout model', async function () {
|
|
184
|
-
const model = ModelMix.new(setup).scout();
|
|
185
|
-
|
|
186
|
-
model.addText('Say "scout test successful" and nothing else.');
|
|
187
|
-
|
|
188
|
-
const response = await model.message();
|
|
189
|
-
console.log(`Scout response: ${response}`);
|
|
190
|
-
|
|
191
|
-
expect(response).to.be.a('string');
|
|
192
|
-
expect(response.toLowerCase()).to.include('scout test successful');
|
|
193
|
-
});
|
|
194
|
-
|
|
195
183
|
it('should work with GPT-OSS model', async function () {
|
|
196
184
|
const model = ModelMix.new(setup).gptOss();
|
|
197
185
|
|
|
@@ -240,26 +228,6 @@ describe('Live Integration Tests', function () {
|
|
|
240
228
|
|
|
241
229
|
describe('Image Processing with JSON Output', function () {
|
|
242
230
|
|
|
243
|
-
it('should process images and return JSON with Scout', async function () {
|
|
244
|
-
const model = ModelMix.new(setup).scout();
|
|
245
|
-
model.addImageFromUrl(blueSquareBase64)
|
|
246
|
-
.addText('Analyze this image and provide details in JSON format.');
|
|
247
|
-
|
|
248
|
-
const result = await model.json({
|
|
249
|
-
color: "string",
|
|
250
|
-
shape: "string",
|
|
251
|
-
description: "string"
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
console.log(`Scout image JSON result:`, result);
|
|
255
|
-
|
|
256
|
-
expect(result).to.be.an('object');
|
|
257
|
-
expect(result).to.have.property('color');
|
|
258
|
-
expect(result).to.have.property('shape');
|
|
259
|
-
expect(result).to.have.property('description');
|
|
260
|
-
expect(result.color).to.be.a('string').and.not.empty;
|
|
261
|
-
});
|
|
262
|
-
|
|
263
231
|
it('should process images and return JSON with Grok 4.3', async function () {
|
|
264
232
|
const model = ModelMix.new(setup).grok43();
|
|
265
233
|
|
|
@@ -285,28 +253,6 @@ describe('Live Integration Tests', function () {
|
|
|
285
253
|
|
|
286
254
|
describe('JSON Structured Output for New Models', function () {
|
|
287
255
|
|
|
288
|
-
it('should return structured JSON with Scout', async function () {
|
|
289
|
-
const model = ModelMix.new(setup).scout();
|
|
290
|
-
|
|
291
|
-
model.addText('Generate information about a fictional animal.');
|
|
292
|
-
|
|
293
|
-
const result = await model.json({
|
|
294
|
-
name: "Dragon",
|
|
295
|
-
type: "Mythical",
|
|
296
|
-
abilities: ["Fire breathing", "Flight"],
|
|
297
|
-
habitat: "Mountains"
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
console.log(`Scout JSON result:`, result);
|
|
301
|
-
|
|
302
|
-
expect(result).to.be.an('object');
|
|
303
|
-
expect(result).to.have.property('name');
|
|
304
|
-
expect(result).to.have.property('type');
|
|
305
|
-
expect(result).to.have.property('abilities');
|
|
306
|
-
expect(result).to.have.property('habitat');
|
|
307
|
-
expect(result.abilities).to.be.an('array');
|
|
308
|
-
});
|
|
309
|
-
|
|
310
256
|
it('should return structured JSON with KimiK25 Thinking', async function () {
|
|
311
257
|
const model = ModelMix.new(setup).kimiK25think();
|
|
312
258
|
|