modelmix 4.5.22 → 4.5.26
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 +3 -0
- package/demo/images.js +1 -1
- package/demo/json.js +0 -1
- package/index.js +29 -24
- package/package.json +3 -4
- package/skills/modelmix/SKILL.md +4 -7
- 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/test/tokens.test.js +9 -0
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
|
@@ -153,6 +153,7 @@ Here's a comprehensive list of available methods:
|
|
|
153
153
|
| `sonnet46[think]()` | Anthropic | claude-sonnet-4-6 | [\$3.00 / \$15.00][2] |
|
|
154
154
|
| `haiku45[think]()` | Anthropic | claude-haiku-4-5-20251001 | [\$1.00 / \$5.00][2] |
|
|
155
155
|
| `gemini31pro()` | Google | gemini-3.1-pro-preview | [\$2.00 / \$12.00][3] |
|
|
156
|
+
| `gemini35flash()` | Google | gemini-3.5-flash | N/A |
|
|
156
157
|
| `gemini31flashLite()`| Google | gemini-3.1-flash-lite-preview | [\$0.25 / \$1.50][3] |
|
|
157
158
|
| `grok43()` | Grok | grok-4.3 | [\$1.25 / \$2.50][6] |
|
|
158
159
|
| `grok420multiAgent()`| Grok | grok-4.20-multi-agent-0309 | [\$1.25 / \$2.50][6] |
|
|
@@ -160,7 +161,9 @@ Here's a comprehensive list of available methods:
|
|
|
160
161
|
| `grok41[think]()` | Grok | grok-4-1-fast | [\$0.20 / \$0.50][6] |
|
|
161
162
|
| `qwen36plus()` | Fireworks/Together | qwen3p6-plus / Qwen3.6-Plus | [\$0.50 / \$3.00][10] |
|
|
162
163
|
| `deepseekV4Pro()` | Fireworks | models/deepseek-v4-pro | [\$1.74 / \$3.48][10] |
|
|
164
|
+
| `GLM52()` | Together | zai-org/GLM-5.2 | [\$1.40 / \$4.40][7] |
|
|
163
165
|
| `GLM51()` | Fireworks | models/glm-5p1 | [\$1.05 / \$3.50][10] |
|
|
166
|
+
| `minimaxM3()` | MiniMax | MiniMax-M3 | [\$0.30 / \$1.20][9] |
|
|
164
167
|
| `minimaxM27()` | MiniMax | MiniMax-M2.7 | [\$0.30 / \$1.20][9] |
|
|
165
168
|
| `sonar()` | Perplexity | sonar | [\$1.00 / \$1.00][4] |
|
|
166
169
|
| `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
|
@@ -87,6 +87,7 @@ const MODEL_PRICING = {
|
|
|
87
87
|
'deepseek-ai/DeepSeek-V4-Pro': [2.10, 4.40],
|
|
88
88
|
'accounts/fireworks/models/glm-4p7': [0.55, 2.19],
|
|
89
89
|
'accounts/fireworks/models/glm-5p1': [1.05, 3.50],
|
|
90
|
+
'zai-org/GLM-5.2': [1.40, 4.40],
|
|
90
91
|
'accounts/fireworks/models/kimi-k2p5': [0.50, 2.80],
|
|
91
92
|
'accounts/fireworks/models/qwen3p6-plus': [0.50, 3.00],
|
|
92
93
|
'Qwen/Qwen3.6-Plus': [0.50, 3.00],
|
|
@@ -94,19 +95,14 @@ const MODEL_PRICING = {
|
|
|
94
95
|
// MiniMax
|
|
95
96
|
'MiniMax-M2.5': [0.30, 1.20],
|
|
96
97
|
'MiniMax-M2.7': [0.30, 1.20],
|
|
98
|
+
'MiniMax-M3': [0.30, 1.20],
|
|
97
99
|
'fireworks/minimax-m2p5': [0.30, 1.20],
|
|
98
100
|
'minimax/minimax-m2.7': [0.30, 1.20],
|
|
101
|
+
'minimax/minimax-m3': [0.30, 1.20],
|
|
102
|
+
'MiniMaxAI/MiniMax-M3': [0.30, 1.20],
|
|
99
103
|
// Perplexity
|
|
100
104
|
'sonar': [1.00, 1.00],
|
|
101
105
|
'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
106
|
// Hermes3 (Lambda/OpenRouter)
|
|
111
107
|
'Hermes-3-Llama-3.1-405B-FP8': [0.80, 0.80],
|
|
112
108
|
'nousresearch/hermes-3-llama-3.1-405b:free': [0, 0],
|
|
@@ -420,6 +416,9 @@ class ModelMix {
|
|
|
420
416
|
gemini3flash({ options = {}, config = {} } = {}) {
|
|
421
417
|
return this.attach('gemini-3-flash-preview', new MixGoogle({ options, config }));
|
|
422
418
|
}
|
|
419
|
+
gemini35flash({ options = {}, config = {} } = {}) {
|
|
420
|
+
return this.attach('gemini-3.5-flash', new MixGoogle({ options, config }));
|
|
421
|
+
}
|
|
423
422
|
gemini31flashLite({ options = {}, config = {} } = {}) {
|
|
424
423
|
return this.attach('gemini-3.1-flash-lite-preview', new MixGoogle({ options, config }));
|
|
425
424
|
}
|
|
@@ -465,20 +464,6 @@ class ModelMix {
|
|
|
465
464
|
return this;
|
|
466
465
|
}
|
|
467
466
|
|
|
468
|
-
scout({ options = {}, config = {}, mix = {} } = {}) {
|
|
469
|
-
mix = { ...this.mix, ...mix };
|
|
470
|
-
if (mix.groq) this.attach('meta-llama/llama-4-scout-17b-16e-instruct', new MixGroq({ options, config }));
|
|
471
|
-
if (mix.together) this.attach('meta-llama/Llama-4-Scout-17B-16E-Instruct', new MixTogether({ options, config }));
|
|
472
|
-
if (mix.cerebras) this.attach('llama-4-scout-17b-16e-instruct', new MixCerebras({ options, config }));
|
|
473
|
-
return this;
|
|
474
|
-
}
|
|
475
|
-
maverick({ options = {}, config = {}, mix = {} } = {}) {
|
|
476
|
-
mix = { ...this.mix, ...mix };
|
|
477
|
-
if (mix.together) this.attach('meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8', new MixTogether({ options, config }));
|
|
478
|
-
if (mix.lambda) this.attach('llama-4-maverick-17b-128e-instruct-fp8', new MixLambda({ options, config }));
|
|
479
|
-
return this;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
467
|
deepseekR1({ options = {}, config = {}, mix = {} } = {}) {
|
|
483
468
|
mix = { ...this.mix, ...mix };
|
|
484
469
|
if (mix.groq) this.attach('deepseek-r1-distill-llama-70b', new MixGroq({ options, config }));
|
|
@@ -503,6 +488,12 @@ class ModelMix {
|
|
|
503
488
|
return this;
|
|
504
489
|
}
|
|
505
490
|
|
|
491
|
+
kimiK27Code({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
492
|
+
mix = { ...this.mix, ...mix };
|
|
493
|
+
if (mix.together) this.attach('moonshotai/Kimi-K2.7-Code', new MixTogether({ options, config }));
|
|
494
|
+
return this;
|
|
495
|
+
}
|
|
496
|
+
|
|
506
497
|
kimiK25think({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
507
498
|
mix = { ...this.mix, ...mix };
|
|
508
499
|
if (mix.together) this.attach('moonshotai/Kimi-K2.5', new MixTogether({ options, config }));
|
|
@@ -532,17 +523,25 @@ class ModelMix {
|
|
|
532
523
|
return this;
|
|
533
524
|
}
|
|
534
525
|
|
|
526
|
+
minimaxM3({ options = {}, config = {}, mix = { minimax: true, openrouter: false } } = {}) {
|
|
527
|
+
mix = { ...this.mix, ...mix };
|
|
528
|
+
if (mix.minimax) this.attach('MiniMax-M3', new MixMiniMax({ options, config }));
|
|
529
|
+
if (mix.openrouter) this.attach('minimax/minimax-m3', new MixOpenRouter({ options, config }));
|
|
530
|
+
if (mix.together) this.attach('MiniMaxAI/MiniMax-M3', new MixTogether({ options, config }));
|
|
531
|
+
return this;
|
|
532
|
+
}
|
|
533
|
+
|
|
535
534
|
mimo25({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
536
535
|
mix = { ...this.mix, ...mix };
|
|
537
|
-
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5', new MixOpenRouter({ options, config }));
|
|
538
536
|
if (mix.mimo) this.attach('mimo-v2.5', new MixMiMo({ options, config }));
|
|
537
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5', new MixOpenRouter({ options, config }));
|
|
539
538
|
return this;
|
|
540
539
|
}
|
|
541
540
|
|
|
542
541
|
mimo25pro({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
543
542
|
mix = { ...this.mix, ...mix };
|
|
544
|
-
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5-pro', new MixOpenRouter({ options, config }));
|
|
545
543
|
if (mix.mimo) this.attach('mimo-v2.5-pro', new MixMiMo({ options, config }));
|
|
544
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5-pro', new MixOpenRouter({ options, config }));
|
|
546
545
|
return this;
|
|
547
546
|
}
|
|
548
547
|
|
|
@@ -570,6 +569,12 @@ class ModelMix {
|
|
|
570
569
|
return this;
|
|
571
570
|
}
|
|
572
571
|
|
|
572
|
+
GLM52({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
573
|
+
mix = { ...this.mix, ...mix };
|
|
574
|
+
if (mix.together) this.attach('zai-org/GLM-5.2', new MixTogether({ options, config }));
|
|
575
|
+
return this;
|
|
576
|
+
}
|
|
577
|
+
|
|
573
578
|
GLM5({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
|
|
574
579
|
mix = { ...this.mix, ...mix };
|
|
575
580
|
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.26",
|
|
4
4
|
"description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -71,6 +71,5 @@
|
|
|
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
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"
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/skills/modelmix/SKILL.md
CHANGED
|
@@ -101,7 +101,7 @@ If `sonnet46` fails, it automatically tries `gpt52`, then `gemini3flash`.
|
|
|
101
101
|
Thinking variants: append `think` — e.g. `opus46think()` `sonnet46think()` `sonnet45think()` `sonnet4think()` `opus45think()` `opus41think()` `haiku45think()`
|
|
102
102
|
|
|
103
103
|
### Google
|
|
104
|
-
`gemini3pro()` `gemini3flash()` `gemini25pro()` `gemini25flash()`
|
|
104
|
+
`gemini3pro()` `gemini3flash()` `gemini35flash()` `gemini25pro()` `gemini25flash()`
|
|
105
105
|
|
|
106
106
|
### Grok
|
|
107
107
|
`grok43()` `grok420multiAgent()` `grok420()` `grok420think()` `grok41()` `grok41think()`
|
|
@@ -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
|
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
|
|
package/test/tokens.test.js
CHANGED
|
@@ -88,6 +88,15 @@ describe('Token Usage Tracking', () => {
|
|
|
88
88
|
expect(model.models[1].provider).to.be.instanceOf(MixOpenAIResponses);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
it('should register Gemini 3.5 Flash shortcut with Google provider', function () {
|
|
92
|
+
const model = ModelMix.new()
|
|
93
|
+
.gemini35flash();
|
|
94
|
+
|
|
95
|
+
expect(model.models).to.have.length(1);
|
|
96
|
+
expect(model.models[0].key).to.equal('gemini-3.5-flash');
|
|
97
|
+
expect(model.models[0].provider).to.be.instanceOf(MixGoogle);
|
|
98
|
+
});
|
|
99
|
+
|
|
91
100
|
it('should register MiMo shortcuts with native and OpenRouter providers', function () {
|
|
92
101
|
const originalMimoApiKey = process.env.MIMO_API_KEY;
|
|
93
102
|
const originalOpenRouterApiKey = process.env.OPENROUTER_API_KEY;
|