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 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 } }).scout()
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
@@ -4,7 +4,6 @@ try { process.loadEnvFile(); } catch {}
4
4
  const model = await ModelMix.new({ options: { max_tokens: 10000 }, config: { debug: 3 } })
5
5
  .gpt54nano()
6
6
  // .gptOss()
7
- // .scout({ config: { temperature: 0 } })
8
7
  // .o4mini()
9
8
  // .gpt45()
10
9
  // .gemini25flash()
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.22",
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
- "packageManager": "pnpm@11.1.2"
76
- }
74
+ }
75
+ }
@@ -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()` `scout()` `maverick()` `kimiK25think()` `GLM47()`
128
+ `deepseekR1()` `hermes3()` `kimiK25think()` `GLM47()`
132
129
 
133
130
  ### Local
134
131
  `lmstudio()` — for LM Studio local models
@@ -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-5nano', async function () {
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
 
@@ -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;