modelmix 5.2.2 → 5.2.3
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 +2 -0
- package/index.d.ts +2 -0
- package/index.js +10 -0
- package/lib/model-chain.js +2 -2
- package/lib/token-usage.js +1 -0
- package/package.json +1 -1
- package/skills/modelmix/SKILL.md +4 -1
- package/test/anthropic.test.js +21 -0
- package/test/effort.test.js +4 -0
- package/test/provider-expansion.test.js +27 -0
- package/test/tokens.test.js +32 -0
package/README.md
CHANGED
|
@@ -179,6 +179,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
179
179
|
| `gptOss()` | Multi-provider | gpt-oss-120B | [\$0.15][7] | [\$0.60][7] |
|
|
180
180
|
| `fable51()` | Anthropic | claude-fable-5-1 | [\$10.00][2] | [\$50.00][2] |
|
|
181
181
|
| `fable5()` | Anthropic | claude-fable-5 | [\$10.00][2] | [\$50.00][2] |
|
|
182
|
+
| `opus55()` | Anthropic | claude-opus-5-5 | [\$5.00][2] | [\$25.00][2] |
|
|
182
183
|
| `opus5()` | Anthropic | claude-opus-5 | [\$5.00][2] | [\$25.00][2] |
|
|
183
184
|
| `opus48()` | Anthropic | claude-opus-4-8 | [\$5.00][2] | [\$25.00][2] |
|
|
184
185
|
| `opus47()` | Anthropic | claude-opus-4-7 | [\$5.00][2] | [\$25.00][2] |
|
|
@@ -219,6 +220,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
219
220
|
| `GLM52()` | Together | zai-org/GLM-5.2 | [\$1.40][7] | [\$4.40][7] |
|
|
220
221
|
| `minimaxM3()` | MiniMax | MiniMax-M3 | [\$0.30][9] | [\$1.20][9] |
|
|
221
222
|
| `minimaxM27()` | MiniMax | MiniMax-M2.7 | [\$0.30][9] | [\$1.20][9] |
|
|
223
|
+
| `mimo26pro()` | MiMo | mimo-v2.6-pro | — | — |
|
|
222
224
|
| `sonar()` | Perplexity | sonar | [\$1.00][4] | [\$1.00][4] |
|
|
223
225
|
| `sonarPro()` | Perplexity | sonar-pro | [\$3.00][4] | [\$15.00][4] |
|
|
224
226
|
| `hermes470b()` | OpenRouter | nousresearch/hermes-4-70b | [\$0.13][13] | [\$0.40][13] |
|
package/index.d.ts
CHANGED
|
@@ -470,6 +470,7 @@ export declare class ModelMix {
|
|
|
470
470
|
fable51(args?: ModelAttachArgs): this;
|
|
471
471
|
fable50(args?: ModelAttachArgs): this;
|
|
472
472
|
fable5(args?: ModelAttachArgs): this;
|
|
473
|
+
opus55(args?: ModelAttachArgs): this;
|
|
473
474
|
opus50(args?: ModelAttachArgs): this;
|
|
474
475
|
opus5(args?: ModelAttachArgs): this;
|
|
475
476
|
opus48(args?: ModelAttachArgs): this;
|
|
@@ -527,6 +528,7 @@ export declare class ModelMix {
|
|
|
527
528
|
minimaxM3(args?: ModelAttachArgs): this;
|
|
528
529
|
mimo25(args?: ModelAttachArgs): this;
|
|
529
530
|
mimo25pro(args?: ModelAttachArgs): this;
|
|
531
|
+
mimo26pro(args?: ModelAttachArgs): this;
|
|
530
532
|
deepseekV4Pro(args?: ModelAttachArgs): this;
|
|
531
533
|
/** Uses deepseek/deepseek-v4-pro-0813 through OpenRouter. */
|
|
532
534
|
deepseekPro(args?: ModelAttachArgs): this;
|
package/index.js
CHANGED
|
@@ -545,6 +545,9 @@ class ModelMix {
|
|
|
545
545
|
if (mix.openrouter) this.attach('anthropic/claude-fable-5.1', new MixOpenRouter({ options, config }));
|
|
546
546
|
return this;
|
|
547
547
|
}
|
|
548
|
+
opus55({ options = {}, config = {} } = {}) {
|
|
549
|
+
return this.attach('claude-opus-5-5', new MixAnthropic({ options, config }));
|
|
550
|
+
}
|
|
548
551
|
opus50({ options = {}, config = {} } = {}) {
|
|
549
552
|
return this.attach('claude-opus-5', new MixAnthropic({ options, config }));
|
|
550
553
|
}
|
|
@@ -769,6 +772,13 @@ class ModelMix {
|
|
|
769
772
|
return this;
|
|
770
773
|
}
|
|
771
774
|
|
|
775
|
+
mimo26pro({ options = {}, config = {}, mix = { openrouter: true } } = {}) {
|
|
776
|
+
mix = { ...this.mix, ...mix };
|
|
777
|
+
if (mix.mimo) this.attach('mimo-v2.6-pro', new MixMiMo({ options, config }));
|
|
778
|
+
if (mix.openrouter) this.attach('xiaomi/mimo-v2.6-pro', new MixOpenRouter({ options, config }));
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
781
|
+
|
|
772
782
|
deepseekPro({ options = {}, config = {} } = {}) {
|
|
773
783
|
return this.attach('deepseek/deepseek-v4-pro-0813', new MixOpenRouter({ options, config }));
|
|
774
784
|
}
|
package/lib/model-chain.js
CHANGED
|
@@ -5,7 +5,7 @@ const CHAIN_MODEL_SHORTCUTS = new Set([
|
|
|
5
5
|
'gpt51', 'gpt52', 'gpt54', 'gpt54mini', 'gpt54nano', 'gpt54pro',
|
|
6
6
|
'gpt6astra', 'gpt55', 'gpt55pro', 'gpt56sol', 'gpt56terra', 'gpt56luna',
|
|
7
7
|
'gptRealtime', 'gptRealtimeMini', 'gpt53codex', 'gpt53chat', 'gptOss',
|
|
8
|
-
'fable51', 'fable50', 'fable5', 'opus50', 'opus5', 'opus48', 'opus47', 'opus46',
|
|
8
|
+
'fable51', 'fable50', 'fable5', 'opus55', 'opus50', 'opus5', 'opus48', 'opus47', 'opus46',
|
|
9
9
|
'sonnet50', 'sonnet5', 'sonnet46', 'sonnet45', 'haiku45',
|
|
10
10
|
'gemini31pro', 'gemini38flash', 'gemini37flash', 'gemini36flash', 'gemini35flash',
|
|
11
11
|
'gemini35flashLite', 'gemini31flashLite', 'sonarPro', 'sonar',
|
|
@@ -14,7 +14,7 @@ const CHAIN_MODEL_SHORTCUTS = new Set([
|
|
|
14
14
|
'qwen35397b', 'qwen36plus', 'qwen37plus', 'qwen38max', 'qwen3827b', 'qwen38flash',
|
|
15
15
|
'hermes470b', 'hermes4405b', 'hermes3',
|
|
16
16
|
'kimiK26', 'kimiK27Code', 'kimiK3', 'kimiK25',
|
|
17
|
-
'minimaxM27', 'minimaxM3', 'mimo25', 'mimo25pro',
|
|
17
|
+
'minimaxM27', 'minimaxM3', 'mimo25', 'mimo25pro', 'mimo26pro',
|
|
18
18
|
'deepseekV4Pro', 'deepseekPro', 'deepseekV4Flash', 'deepseekV41Flash', 'GLM52', 'GLM53', 'GLM53Flash'
|
|
19
19
|
]);
|
|
20
20
|
|
package/lib/token-usage.js
CHANGED
|
@@ -53,6 +53,7 @@ const MODEL_PRICING = {
|
|
|
53
53
|
'claude-fable-5-1': { input: 10.00, cachedInput: 0.25, cacheWrite: 12.50, cacheWrite1h: 20.00, output: 50.00 },
|
|
54
54
|
'anthropic/claude-fable-5.1': { input: 10.00, cachedInput: 0.25, cacheWrite: 12.50, cacheWrite1h: 20.00, output: 50.00 },
|
|
55
55
|
'claude-fable-5': { input: 10.00, cachedInput: 1.00, cacheWrite: 12.50, cacheWrite1h: 20.00, output: 50.00 },
|
|
56
|
+
'claude-opus-5-5': { input: 5.00, cachedInput: 0.50, cacheWrite: 6.25, cacheWrite1h: 10.00, output: 25.00 },
|
|
56
57
|
'claude-opus-5': { input: 5.00, cachedInput: 0.50, cacheWrite: 6.25, cacheWrite1h: 10.00, output: 25.00 },
|
|
57
58
|
'claude-sonnet-5': { input: 3.00, cachedInput: 0.30, cacheWrite: 3.75, cacheWrite1h: 6.00, output: 15.00 },
|
|
58
59
|
'claude-opus-4-8': { input: 5.00, cachedInput: 0.50, cacheWrite: 6.25, cacheWrite1h: 10.00, output: 25.00 },
|
package/package.json
CHANGED
package/skills/modelmix/SKILL.md
CHANGED
|
@@ -177,7 +177,7 @@ Use `ModerationMix.new().openai()` with `.raw()` to classify text and images thr
|
|
|
177
177
|
Every textual GPT-5 and GPT-6 shortcut registers only the official OpenAI model by default. Pass `mix: { openrouter: true }` to `ModelMix.new()` or to an individual shortcut to append its `openai/*` OpenRouter route as a fallback. `gpt53chat()` uses `gpt-5.3-chat-latest` officially and `openai/gpt-5.3-chat` through OpenRouter. Both API keys are required when that fallback is enabled. Realtime shortcuts remain official-only.
|
|
178
178
|
|
|
179
179
|
### Anthropic
|
|
180
|
-
`fable51()` `fable50()` `opus50()` `opus48()` `opus47()` `opus46()` `sonnet5()` `sonnet46()` `sonnet45()` `haiku45()`
|
|
180
|
+
`fable51()` `fable50()` `opus55()` `opus50()` `opus48()` `opus47()` `opus46()` `sonnet5()` `sonnet46()` `sonnet45()` `haiku45()`
|
|
181
181
|
|
|
182
182
|
Use `.effort(n)` (or `config.effort`) to enable Anthropic thinking — e.g. `.effort(100).opus50()`. `fable5()` and `opus5()` remain available as compatibility aliases.
|
|
183
183
|
|
|
@@ -204,6 +204,9 @@ Use `.effort(n)` (or `config.effort`) to enable Anthropic thinking — e.g. `.ef
|
|
|
204
204
|
### MiniMax
|
|
205
205
|
`minimaxM27()` `minimaxM3()`
|
|
206
206
|
|
|
207
|
+
### MiMo
|
|
208
|
+
`mimo26pro()` — uses OpenRouter (`xiaomi/mimo-v2.6-pro`) by default; the native API requires `MIMO_API_KEY` and `mix: { mimo: true }`.
|
|
209
|
+
|
|
207
210
|
### DeepSeek
|
|
208
211
|
`deepseekV41Flash({ mix: { deepseek: true, openrouter: false } })` uses the native API at `https://api.deepseek.com/chat/completions` with model `deepseek-flash` (currently V4.1 Flash). Requires `DEEPSEEK_API_KEY`; `MixDeepSeek` supports explicit `.attach()` calls. Unified effort and native cache usage are supported, and assistant reasoning is preserved for tool continuations. Cost estimates use peak rates per 1M tokens: $0.30 input, $0.006 cached input, $1.20 output; off-peak charges are half. Enabling all three providers orders them DeepSeek → Fireworks → OpenRouter.
|
|
209
212
|
|
package/test/anthropic.test.js
CHANGED
|
@@ -122,6 +122,15 @@ describe('Anthropic Model Registration Tests', () => {
|
|
|
122
122
|
expect(model.models[0].provider).to.be.instanceOf(MixAnthropic);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
it('should register Claude Opus 5.5', () => {
|
|
126
|
+
const model = ModelMix.new();
|
|
127
|
+
model.opus55();
|
|
128
|
+
|
|
129
|
+
expect(model.models).to.have.length(1);
|
|
130
|
+
expect(model.models[0].key).to.equal('claude-opus-5-5');
|
|
131
|
+
expect(model.models[0].provider).to.be.instanceOf(MixAnthropic);
|
|
132
|
+
});
|
|
133
|
+
|
|
125
134
|
it('should keep opus5() as an alias for opus50()', () => {
|
|
126
135
|
const model = ModelMix.new();
|
|
127
136
|
|
|
@@ -147,9 +156,21 @@ describe('Anthropic Model Registration Tests', () => {
|
|
|
147
156
|
expect(options.thinking).to.deep.equal({ type: 'adaptive', display: 'summarized' });
|
|
148
157
|
});
|
|
149
158
|
|
|
159
|
+
it('should apply max effort thinking via .effort(100).opus55()', () => {
|
|
160
|
+
const model = ModelMix.new().effort(100).opus55();
|
|
161
|
+
const { applyUnifiedEffort } = require('../effort.js');
|
|
162
|
+
|
|
163
|
+
expect(model.config.effort).to.equal(100);
|
|
164
|
+
const options = { model: 'claude-opus-5-5' };
|
|
165
|
+
applyUnifiedEffort(options, model.config, 'anthropic', 'claude-opus-5-5');
|
|
166
|
+
expect(options.output_config).to.deep.equal({ effort: 'max' });
|
|
167
|
+
expect(options.thinking).to.deep.equal({ type: 'adaptive', display: 'summarized' });
|
|
168
|
+
});
|
|
169
|
+
|
|
150
170
|
describe('Sampling params (temperature/top_p/top_k)', () => {
|
|
151
171
|
it('should detect models that reject sampling params', () => {
|
|
152
172
|
expect(MixAnthropic.rejectsSamplingParams('claude-opus-5')).to.equal(true);
|
|
173
|
+
expect(MixAnthropic.rejectsSamplingParams('claude-opus-5-5')).to.equal(true);
|
|
153
174
|
expect(MixAnthropic.rejectsSamplingParams('claude-opus-4-8')).to.equal(true);
|
|
154
175
|
expect(MixAnthropic.rejectsSamplingParams('claude-opus-4-7')).to.equal(true);
|
|
155
176
|
expect(MixAnthropic.rejectsSamplingParams('claude-sonnet-5')).to.equal(true);
|
package/test/effort.test.js
CHANGED
|
@@ -197,6 +197,10 @@ describe('Unified effort scale', () => {
|
|
|
197
197
|
thinking: { type: 'adaptive', display: 'summarized' },
|
|
198
198
|
output_config: { effort: 'low' }
|
|
199
199
|
});
|
|
200
|
+
expect(mapEffort('anthropic', 50, 'claude-opus-5-5')).to.deep.equal({
|
|
201
|
+
thinking: { type: 'adaptive', display: 'summarized' },
|
|
202
|
+
output_config: { effort: 'high' }
|
|
203
|
+
});
|
|
200
204
|
expect(mapEffort('anthropic', 90, 'claude-fable-5-1')).to.deep.equal({
|
|
201
205
|
thinking: { type: 'adaptive', display: 'summarized' },
|
|
202
206
|
output_config: { effort: 'max' }
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const { expect } = require('chai');
|
|
2
|
+
const nock = require('nock');
|
|
2
3
|
const {
|
|
3
4
|
ModelMix,
|
|
4
5
|
MixFireworks,
|
|
6
|
+
MixMiMo,
|
|
5
7
|
MixMiniMax,
|
|
6
8
|
MixNVIDIA,
|
|
7
9
|
MixOpenRouter,
|
|
@@ -97,4 +99,29 @@ describe('Provider expansion regressions', () => {
|
|
|
97
99
|
expect(model.models[0].key).to.equal('accounts/fireworks/models/minimax-m3');
|
|
98
100
|
expect(model.models[0].provider).to.be.instanceOf(MixFireworks);
|
|
99
101
|
});
|
|
102
|
+
|
|
103
|
+
it('should send MiMo 2.6 Pro requests to the native MiMo API', async () => {
|
|
104
|
+
const api = nock('https://api.xiaomimimo.com')
|
|
105
|
+
.post('/v1/chat/completions', body => {
|
|
106
|
+
expect(body.model).to.equal('mimo-v2.6-pro');
|
|
107
|
+
return true;
|
|
108
|
+
})
|
|
109
|
+
.reply(200, {
|
|
110
|
+
choices: [{ message: { content: 'ok' } }],
|
|
111
|
+
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const model = ModelMix.new().mimo26pro({
|
|
115
|
+
mix: { mimo: true, openrouter: false },
|
|
116
|
+
config: { apiKey: 'test-mimo-key' }
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
expect(model.models).to.have.length(1);
|
|
120
|
+
expect(model.models[0].provider).to.be.instanceOf(MixMiMo);
|
|
121
|
+
|
|
122
|
+
const response = await model.addText('Hi').message();
|
|
123
|
+
|
|
124
|
+
expect(response).to.equal('ok');
|
|
125
|
+
api.done();
|
|
126
|
+
});
|
|
100
127
|
});
|
package/test/tokens.test.js
CHANGED
|
@@ -674,6 +674,38 @@ describe('Token Usage Tracking', () => {
|
|
|
674
674
|
}
|
|
675
675
|
});
|
|
676
676
|
|
|
677
|
+
it('should register MiMo 2.6 Pro with native and OpenRouter providers', function () {
|
|
678
|
+
const originalMimoApiKey = process.env.MIMO_API_KEY;
|
|
679
|
+
const originalOpenRouterApiKey = process.env.OPENROUTER_API_KEY;
|
|
680
|
+
|
|
681
|
+
process.env.MIMO_API_KEY = 'test-mimo-key';
|
|
682
|
+
process.env.OPENROUTER_API_KEY = 'test-openrouter-key';
|
|
683
|
+
|
|
684
|
+
try {
|
|
685
|
+
const model = ModelMix.new().mimo26pro();
|
|
686
|
+
const withNative = ModelMix.new()
|
|
687
|
+
.mimo26pro({ mix: { mimo: true, openrouter: true } });
|
|
688
|
+
|
|
689
|
+
expect(model.models.map(({ key }) => key)).to.deep.equal(['xiaomi/mimo-v2.6-pro']);
|
|
690
|
+
expect(model.models[0].provider).to.be.instanceOf(MixOpenRouter);
|
|
691
|
+
|
|
692
|
+
expect(withNative.models.map(({ key }) => key)).to.deep.equal([
|
|
693
|
+
'mimo-v2.6-pro',
|
|
694
|
+
'xiaomi/mimo-v2.6-pro'
|
|
695
|
+
]);
|
|
696
|
+
expect(withNative.models[0].provider).to.be.instanceOf(MixMiMo);
|
|
697
|
+
expect(withNative.models[1].provider).to.be.instanceOf(MixOpenRouter);
|
|
698
|
+
|
|
699
|
+
expect(ModelMix.new().chain('mimo26pro').models[0].key).to.equal('xiaomi/mimo-v2.6-pro');
|
|
700
|
+
} finally {
|
|
701
|
+
if (originalMimoApiKey === undefined) delete process.env.MIMO_API_KEY;
|
|
702
|
+
else process.env.MIMO_API_KEY = originalMimoApiKey;
|
|
703
|
+
|
|
704
|
+
if (originalOpenRouterApiKey === undefined) delete process.env.OPENROUTER_API_KEY;
|
|
705
|
+
else process.env.OPENROUTER_API_KEY = originalOpenRouterApiKey;
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
|
|
677
709
|
it('should register GPT-OSS 120B through the current OpenRouter model ID', function () {
|
|
678
710
|
const originalOpenRouterApiKey = process.env.OPENROUTER_API_KEY;
|
|
679
711
|
process.env.OPENROUTER_API_KEY = 'test-openrouter-key';
|