modelmix 4.5.18 → 4.5.20
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/index.js +39 -2
- package/package.json +2 -2
- package/test/tokens.test.js +57 -1
package/index.js
CHANGED
|
@@ -530,7 +530,21 @@ class ModelMix {
|
|
|
530
530
|
if (mix.minimax) return this.attach('MiniMax-M2.7', new MixMiniMax({ options, config }));
|
|
531
531
|
if (mix.together) return this.attach('MiniMaxAI/MiniMax-M2.7', new MixTogether({ options, config }));
|
|
532
532
|
return this;
|
|
533
|
-
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
mimo25({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
536
|
+
mix = { ...this.mix, ...mix };
|
|
537
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5', new MixOpenRouter({ options, config }));
|
|
538
|
+
if (mix.mimo) this.attach('mimo-v2.5', new MixMiMo({ options, config }));
|
|
539
|
+
return this;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
mimo25pro({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
543
|
+
mix = { ...this.mix, ...mix };
|
|
544
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.5-pro', new MixOpenRouter({ options, config }));
|
|
545
|
+
if (mix.mimo) this.attach('mimo-v2.5-pro', new MixMiMo({ options, config }));
|
|
546
|
+
return this;
|
|
547
|
+
}
|
|
534
548
|
|
|
535
549
|
deepseekV4Pro({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
|
|
536
550
|
mix = { ...this.mix, ...mix };
|
|
@@ -2316,6 +2330,29 @@ class MixMiniMax extends MixOpenAI {
|
|
|
2316
2330
|
}
|
|
2317
2331
|
}
|
|
2318
2332
|
|
|
2333
|
+
class MixMiMo extends MixOpenAI {
|
|
2334
|
+
getDefaultConfig(customConfig) {
|
|
2335
|
+
if (!process.env.MIMO_API_KEY) {
|
|
2336
|
+
throw new Error('MiMo API key not found. Please provide it in config or set MIMO_API_KEY environment variable.');
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
return MixCustom.prototype.getDefaultConfig.call(this, {
|
|
2340
|
+
url: 'https://api.xiaomimimo.com/v1/chat/completions',
|
|
2341
|
+
apiKey: process.env.MIMO_API_KEY,
|
|
2342
|
+
...customConfig
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
getDefaultHeaders(customHeaders) {
|
|
2347
|
+
return {
|
|
2348
|
+
'accept': 'application/json',
|
|
2349
|
+
'content-type': 'application/json',
|
|
2350
|
+
'api-key': this.config.apiKey,
|
|
2351
|
+
...customHeaders
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2319
2356
|
class MixPerplexity extends MixCustom {
|
|
2320
2357
|
getDefaultConfig(customConfig) {
|
|
2321
2358
|
|
|
@@ -2854,4 +2891,4 @@ class MixGoogle extends MixCustom {
|
|
|
2854
2891
|
}
|
|
2855
2892
|
}
|
|
2856
2893
|
|
|
2857
|
-
module.exports = { MixCustom, ModelMix, MixAnthropic, MixMiniMax, MixOpenAI, MixOpenAIResponses, MixOpenAIWebSocket, MixOpenRouter, MixPerplexity, MixOllama, MixLMStudio, MixGroq, MixTogether, MixGrok, MixCerebras, MixGoogle, MixFireworks, MixNVIDIA };
|
|
2894
|
+
module.exports = { MixCustom, ModelMix, MixAnthropic, MixMiniMax, MixMiMo, MixOpenAI, MixOpenAIResponses, MixOpenAIWebSocket, MixOpenRouter, MixPerplexity, MixOllama, MixLMStudio, MixGroq, MixTogether, MixGrok, MixCerebras, MixGoogle, MixFireworks, MixNVIDIA };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelmix",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.20",
|
|
4
4
|
"description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"lmstudio",
|
|
33
33
|
"deepseek",
|
|
34
34
|
"oss",
|
|
35
|
-
"
|
|
35
|
+
"k26",
|
|
36
36
|
"reasoning",
|
|
37
37
|
"minimax",
|
|
38
38
|
"thinking",
|
package/test/tokens.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect } from 'chai';
|
|
2
|
-
import { ModelMix, MixAnthropic, MixCustom, MixGoogle, MixOpenAIResponses } from '../index.js';
|
|
2
|
+
import { ModelMix, MixAnthropic, MixCustom, MixGoogle, MixMiMo, MixOpenAIResponses, MixOpenRouter } from '../index.js';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
@@ -88,6 +88,62 @@ describe('Token Usage Tracking', () => {
|
|
|
88
88
|
expect(model.models[1].provider).to.be.instanceOf(MixOpenAIResponses);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
it('should register MiMo shortcuts with native and OpenRouter providers', function () {
|
|
92
|
+
const originalMimoApiKey = process.env.MIMO_API_KEY;
|
|
93
|
+
const originalOpenRouterApiKey = process.env.OPENROUTER_API_KEY;
|
|
94
|
+
|
|
95
|
+
process.env.MIMO_API_KEY = 'test-mimo-key';
|
|
96
|
+
process.env.OPENROUTER_API_KEY = 'test-openrouter-key';
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const model = ModelMix.new()
|
|
100
|
+
.mimo25()
|
|
101
|
+
.mimo25pro({ mix: { mimo: true, openrouter: true } });
|
|
102
|
+
|
|
103
|
+
expect(model.models).to.have.length(3);
|
|
104
|
+
expect(model.models[0].key).to.equal('xiaomi/mimo-v2.5');
|
|
105
|
+
expect(model.models[1].key).to.equal('mimo-v2.5-pro');
|
|
106
|
+
expect(model.models[2].key).to.equal('xiaomi/mimo-v2.5-pro');
|
|
107
|
+
|
|
108
|
+
expect(model.models[0].provider).to.be.instanceOf(MixOpenRouter);
|
|
109
|
+
expect(model.models[1].provider).to.be.instanceOf(MixMiMo);
|
|
110
|
+
expect(model.models[2].provider).to.be.instanceOf(MixOpenRouter);
|
|
111
|
+
} finally {
|
|
112
|
+
if (originalMimoApiKey === undefined) delete process.env.MIMO_API_KEY;
|
|
113
|
+
else process.env.MIMO_API_KEY = originalMimoApiKey;
|
|
114
|
+
|
|
115
|
+
if (originalOpenRouterApiKey === undefined) delete process.env.OPENROUTER_API_KEY;
|
|
116
|
+
else process.env.OPENROUTER_API_KEY = originalOpenRouterApiKey;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should use api-key header for MiMo provider', function () {
|
|
121
|
+
const originalMimoApiKey = process.env.MIMO_API_KEY;
|
|
122
|
+
process.env.MIMO_API_KEY = 'test-mimo-key';
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const provider = new MixMiMo();
|
|
126
|
+
expect(provider.headers['api-key']).to.equal('test-mimo-key');
|
|
127
|
+
expect(provider.headers.authorization).to.equal(undefined);
|
|
128
|
+
expect(provider.config.url).to.equal('https://api.xiaomimimo.com/v1/chat/completions');
|
|
129
|
+
} finally {
|
|
130
|
+
if (originalMimoApiKey === undefined) delete process.env.MIMO_API_KEY;
|
|
131
|
+
else process.env.MIMO_API_KEY = originalMimoApiKey;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should throw a clear error when MIMO_API_KEY is missing', function () {
|
|
136
|
+
const originalMimoApiKey = process.env.MIMO_API_KEY;
|
|
137
|
+
delete process.env.MIMO_API_KEY;
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
expect(() => new MixMiMo()).to.throw('MIMO_API_KEY');
|
|
141
|
+
} finally {
|
|
142
|
+
if (originalMimoApiKey === undefined) delete process.env.MIMO_API_KEY;
|
|
143
|
+
else process.env.MIMO_API_KEY = originalMimoApiKey;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
91
147
|
it('should track tokens in OpenAI response', async function () {
|
|
92
148
|
this.timeout(30000);
|
|
93
149
|
|