modelmix 5.3.0 → 5.3.1
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/.gitignore +138 -0
- package/README.md +10 -24
- package/demo/demo.js +2 -2
- package/demo/fallback.js +1 -1
- package/demo/free.js +3 -3
- package/demo/gemini.js +3 -3
- package/demo/json.js +0 -1
- package/demo/round-robin.js +2 -2
- package/demo/short.js +1 -1
- package/effort.js +1 -1
- package/index.d.ts +0 -12
- package/index.js +1 -50
- package/lib/model-chain.js +7 -7
- package/package.json +3 -4
- package/plugins/benchmark/test/benchmark.test.js +33 -29
- package/skills/modelmix/SKILL.md +23 -32
- package/test/abort.test.js +1 -1
- package/test/bottleneck.test.js +12 -12
- package/test/fallback.test.js +19 -23
- package/test/grok.test.js +1 -4
- package/test/history.test.js +2 -2
- package/test/images.test.js +3 -3
- package/test/json.test.js +2 -2
- package/test/live.test.js +6 -8
- package/test/provider-expansion.test.js +10 -17
- package/test/templates.test.js +32 -32
- package/test/tokens.test.js +5 -6
- package/demo/package-lock.json +0 -516
package/.gitignore
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
lerna-debug.log*
|
|
8
|
+
.pnpm-debug.log*
|
|
9
|
+
|
|
10
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
11
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
12
|
+
|
|
13
|
+
# Runtime data
|
|
14
|
+
pids
|
|
15
|
+
*.pid
|
|
16
|
+
*.seed
|
|
17
|
+
*.pid.lock
|
|
18
|
+
|
|
19
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
20
|
+
lib-cov
|
|
21
|
+
|
|
22
|
+
# Coverage directory used by tools like istanbul
|
|
23
|
+
coverage
|
|
24
|
+
*.lcov
|
|
25
|
+
|
|
26
|
+
# nyc test coverage
|
|
27
|
+
.nyc_output
|
|
28
|
+
|
|
29
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
30
|
+
.grunt
|
|
31
|
+
|
|
32
|
+
# Bower dependency directory (https://bower.io/)
|
|
33
|
+
bower_components
|
|
34
|
+
|
|
35
|
+
# node-waf configuration
|
|
36
|
+
.lock-wscript
|
|
37
|
+
|
|
38
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
39
|
+
build/Release
|
|
40
|
+
|
|
41
|
+
# Dependency directories
|
|
42
|
+
node_modules/
|
|
43
|
+
jspm_packages/
|
|
44
|
+
|
|
45
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
46
|
+
web_modules/
|
|
47
|
+
|
|
48
|
+
# TypeScript cache
|
|
49
|
+
*.tsbuildinfo
|
|
50
|
+
|
|
51
|
+
# Optional npm cache directory
|
|
52
|
+
.npm
|
|
53
|
+
|
|
54
|
+
# Optional eslint cache
|
|
55
|
+
.eslintcache
|
|
56
|
+
|
|
57
|
+
# Optional stylelint cache
|
|
58
|
+
.stylelintcache
|
|
59
|
+
|
|
60
|
+
# Microbundle cache
|
|
61
|
+
.rpt2_cache/
|
|
62
|
+
.rts2_cache_cjs/
|
|
63
|
+
.rts2_cache_es/
|
|
64
|
+
.rts2_cache_umd/
|
|
65
|
+
|
|
66
|
+
# Optional REPL history
|
|
67
|
+
.node_repl_history
|
|
68
|
+
|
|
69
|
+
# Output of 'npm pack'
|
|
70
|
+
*.tgz
|
|
71
|
+
|
|
72
|
+
# Yarn Integrity file
|
|
73
|
+
.yarn-integrity
|
|
74
|
+
|
|
75
|
+
# dotenv environment variable files
|
|
76
|
+
.env
|
|
77
|
+
.env.development.local
|
|
78
|
+
.env.test.local
|
|
79
|
+
.env.production.local
|
|
80
|
+
.env.local
|
|
81
|
+
|
|
82
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
83
|
+
.cache
|
|
84
|
+
.parcel-cache
|
|
85
|
+
|
|
86
|
+
# Next.js build output
|
|
87
|
+
.next
|
|
88
|
+
out
|
|
89
|
+
|
|
90
|
+
# Nuxt.js build / generate output
|
|
91
|
+
.nuxt
|
|
92
|
+
dist
|
|
93
|
+
|
|
94
|
+
# Gatsby files
|
|
95
|
+
.cache/
|
|
96
|
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
97
|
+
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
98
|
+
# public
|
|
99
|
+
|
|
100
|
+
# vuepress build output
|
|
101
|
+
.vuepress/dist
|
|
102
|
+
|
|
103
|
+
# vuepress v2.x temp and cache directory
|
|
104
|
+
.temp
|
|
105
|
+
.cache
|
|
106
|
+
|
|
107
|
+
# Docusaurus cache and generated files
|
|
108
|
+
.docusaurus
|
|
109
|
+
|
|
110
|
+
# Serverless directories
|
|
111
|
+
.serverless/
|
|
112
|
+
|
|
113
|
+
# FuseBox cache
|
|
114
|
+
.fusebox/
|
|
115
|
+
|
|
116
|
+
# DynamoDB Local files
|
|
117
|
+
.dynamodb/
|
|
118
|
+
|
|
119
|
+
# TernJS port file
|
|
120
|
+
.tern-port
|
|
121
|
+
|
|
122
|
+
# Stores VSCode versions used for testing VSCode extensions
|
|
123
|
+
.vscode-test
|
|
124
|
+
|
|
125
|
+
# yarn v2
|
|
126
|
+
.yarn/cache
|
|
127
|
+
.yarn/unplugged
|
|
128
|
+
.yarn/build-state.yml
|
|
129
|
+
.yarn/install-state.gz
|
|
130
|
+
.pnp.*
|
|
131
|
+
|
|
132
|
+
.DS_Store
|
|
133
|
+
demo/jailbreak.mjs
|
|
134
|
+
CLAUDE.md
|
|
135
|
+
demo/jailbreak.js
|
|
136
|
+
/demo/lab
|
|
137
|
+
/demo/results
|
|
138
|
+
/.pnpm-store/
|
package/README.md
CHANGED
|
@@ -138,11 +138,11 @@ const ETH = ModelMix.new()
|
|
|
138
138
|
console.log(ETH.price);
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
**This example
|
|
141
|
+
**This example chains two multi-provider shortcuts. Each one registers its default provider and accepts additional providers through `mix`; if one model fails, ModelMix automatically falls back to the next model in the chain.**
|
|
142
142
|
```javascript
|
|
143
143
|
ModelMix.new()
|
|
144
|
-
.
|
|
145
|
-
.
|
|
144
|
+
.kimiK26()
|
|
145
|
+
.GLM52()
|
|
146
146
|
.addText('What is the capital of France?');
|
|
147
147
|
```
|
|
148
148
|
|
|
@@ -171,14 +171,9 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
171
171
|
| `gpt54mini()` | OpenAI | gpt-5.4-mini | [\$0.75][1] | [\$4.50][1] |
|
|
172
172
|
| `gpt54nano()` | OpenAI | gpt-5.4-nano | [\$0.20][1] | [\$1.25][1] |
|
|
173
173
|
| `gpt54pro()` | OpenAI | gpt-5.4-pro | [\$30.00][1] | [\$180.00][1] |
|
|
174
|
-
| `gpt53codex()` | OpenAI | gpt-5.3-codex | [\$1.75][1] | [\$14.00][1] |
|
|
175
|
-
| `gpt53chat()` | OpenAI | gpt-5.3-chat-latest | [\$1.75][1] | [\$14.00][1] |
|
|
176
174
|
| `gpt52()` | OpenAI | gpt-5.2 | [\$1.75][1] | [\$14.00][1] |
|
|
177
|
-
| `gpt51()` | OpenAI | gpt-5.1 | [\$1.25][1] | [\$10.00][1] |
|
|
178
|
-
| `gpt5()` | OpenAI | gpt-5 | [\$1.25][1] | [\$10.00][1] |
|
|
179
175
|
| `gpt5mini()` | OpenAI | gpt-5-mini | [\$0.25][1] | [\$2.00][1] |
|
|
180
176
|
| `gpt5nano()` | OpenAI | gpt-5-nano | [\$0.05][1] | [\$0.40][1] |
|
|
181
|
-
| `gptOss()` | Multi-provider | gpt-oss-120B | [\$0.15][7] | [\$0.60][7] |
|
|
182
177
|
| `fable51()` | Anthropic | claude-fable-5-1 | [\$10.00][2] | [\$50.00][2] |
|
|
183
178
|
| `fable5()` | Anthropic | claude-fable-5 | [\$10.00][2] | [\$50.00][2] |
|
|
184
179
|
| `opus55()` | Anthropic | claude-opus-5-5 | [\$5.00][2] | [\$25.00][2] |
|
|
@@ -187,9 +182,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
187
182
|
| `opus47()` | Anthropic | claude-opus-4-7 | [\$5.00][2] | [\$25.00][2] |
|
|
188
183
|
| `opus46()` | Anthropic | claude-opus-4-6 | [\$5.00][2] | [\$25.00][2] |
|
|
189
184
|
| `sonnet5()` | Anthropic | claude-sonnet-5 | [\$3.00][2] | [\$15.00][2] |
|
|
190
|
-
| `sonnet46()` | Anthropic | claude-sonnet-4-6 | [\$3.00][2] | [\$15.00][2] |
|
|
191
185
|
| `haiku45()` | Anthropic | claude-haiku-4-5-20251001 | [\$1.00][2] | [\$5.00][2] |
|
|
192
|
-
| `gemini31pro()` | Google | gemini-3.1-pro-preview | [\$2.00][3] | [\$12.00][3] |
|
|
193
186
|
| `gemini38flash()` | Google | gemini-3.8-flash | [\$0.75][3] | [\$3.75][3] |
|
|
194
187
|
| `gemini37flash()` | Google | gemini-3.7-flash | [\$0.75][3] | [\$3.75][3] |
|
|
195
188
|
| `gemini36flash()` | Google | gemini-3.6-flash | [\$0.75][3] | [\$3.75][3] |
|
|
@@ -198,10 +191,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
198
191
|
| `gemini31flashLite()` | Google | gemini-3.1-flash-lite-preview | [\$0.25][3] | [\$1.50][3] |
|
|
199
192
|
| `grok47()` | Grok | grok-4.7 | — | — |
|
|
200
193
|
| `grok46()` | Grok | grok-4.6 | [\$2.00][6] | [\$6.00][6] |
|
|
201
|
-
| `grok45()` | Grok | grok-4.5 | [\$2.00][6] | [\$6.00][6] |
|
|
202
194
|
| `grok43()` | Grok | grok-4.3 | [\$1.25][6] | [\$2.50][6] |
|
|
203
|
-
| `grok420multiAgent()` | Grok | grok-4.20-multi-agent-0309 | [\$1.25][6] | [\$2.50][6] |
|
|
204
|
-
| `grok420()` | Grok | grok-4.20-0309 (†) | [\$1.25][6] | [\$2.50][6] |
|
|
205
195
|
| `museGlimmer30b()` | Fireworks | models/muse-glimmer-30b | [\$0.35][17] | [\$1.50][17] |
|
|
206
196
|
| `museSpark12()` | OpenRouter | meta/muse-spark-1.2 | [\$1.25][25] | [\$4.25][25] |
|
|
207
197
|
| `museSpark12c()` | OpenRouter | meta/muse-spark-1.2-contributor | [\$0.10][22] | [\$0.20][22] |
|
|
@@ -214,7 +204,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
214
204
|
| `qwen3827b()` | OpenRouter | qwen/qwen3.8-27b | [\$0.45][15] | [\$3.20][15] |
|
|
215
205
|
| `qwen38flash()` | OpenRouter | qwen/qwen3.8-flash | [\$0.16][19] | [\$0.47][19] |
|
|
216
206
|
| `deepseekV4Flash()` | Fireworks | models/deepseek-v4-flash | [\$0.14][10] | [\$0.28][10] |
|
|
217
|
-
| `deepseekV41Flash()` |
|
|
207
|
+
| `deepseekV41Flash()` | DeepSeek | deepseek-flash | [\$0.30][29] | [\$1.20][29] |
|
|
218
208
|
| `deepseekV4Pro()` | Fireworks | models/deepseek-v4-pro-0813 | [\$1.32][12] | [\$3.96][12] |
|
|
219
209
|
| `deepseekPro()` | OpenRouter | deepseek/deepseek-v4-pro-0813 | [\$0.5808][28] | [\$1.7424][28] |
|
|
220
210
|
| `GLM53()` | OpenRouter | z-ai/glm-5.3 | [\$1.40][16] | [\$4.40][16] |
|
|
@@ -230,7 +220,6 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
|
|
|
230
220
|
| `hermes3()` | Lambda | Hermes-3-Llama-3.1-405B-FP8 | [\$0.80][8] | [\$0.80][8] |
|
|
231
221
|
| `kimiK3()` | Moonshot | kimi-k3 | [\$3.00][11] | [\$15.00][11] |
|
|
232
222
|
| `kimiK27Code()` | Together | Kimi-K2.7-Code | [\$0.95][7] | [\$4.00][7] |
|
|
233
|
-
| `kimiK25()` | Together | Kimi-K2.5 | [\$0.50][7] | [\$2.80][7] |
|
|
234
223
|
| `kimiK26()` | Fireworks | models/kimi-k2p6 | [\$0.95][10] | [\$4.00][10] |
|
|
235
224
|
|
|
236
225
|
Gemini 3.8 Flash, 3.7 Flash, and 3.6 Flash use Google's introductory standard pricing through December 31, 2026; standard rates double on January 1, 2027.
|
|
@@ -239,9 +228,9 @@ Gemini 3.8 Flash, 3.7 Flash, and 3.6 Flash use Google's introductory standard pr
|
|
|
239
228
|
|
|
240
229
|
`fable51()` uses the official Anthropic API by default (`claude-fable-5-1`). Pass `mix: { openrouter: true }` to append [`anthropic/claude-fable-5.1`][21] as its fallback.
|
|
241
230
|
|
|
242
|
-
Every textual GPT-5 and GPT-6 shortcut in the table uses the official OpenAI API by default. Pass `mix: { openrouter: true }` to `ModelMix.new()` or to an individual shortcut to append the matching [`openai/*` OpenRouter route][23] as its fallback.
|
|
231
|
+
Every textual GPT-5 and GPT-6 shortcut in the table uses the official OpenAI API by default. Pass `mix: { openrouter: true }` to `ModelMix.new()` or to an individual shortcut to append the matching [`openai/*` OpenRouter route][23] as its fallback. Realtime shortcuts remain official-only because they use OpenAI's WebSocket transport.
|
|
243
232
|
|
|
244
|
-
OpenRouter fallbacks are disabled globally by default and are appended only with `mix.openrouter: true`. Shortcuts whose primary provider is OpenRouter, such as `qwen36plus()`, are unaffected. The multi-provider shortcuts also expose the current catalog alternatives: `
|
|
233
|
+
OpenRouter fallbacks are disabled globally by default and are appended only with `mix.openrouter: true`. Shortcuts whose primary provider is OpenRouter, such as `qwen36plus()`, are unaffected. The multi-provider shortcuts also expose the current catalog alternatives: `qwen37plus()` supports Together; `kimiK27Code()` supports Fireworks and OpenRouter; `kimiK3()` supports Fireworks, OpenRouter, and Together; `GLM52()` supports Fireworks and OpenRouter; and both MiniMax shortcuts support Fireworks. `minimaxM27()` keeps every explicitly enabled provider in its fallback chain.
|
|
245
234
|
|
|
246
235
|
[1]: https://platform.openai.com/docs/pricing "Pricing | OpenAI"
|
|
247
236
|
[2]: https://docs.anthropic.com/en/docs/about-claude/pricing "Pricing - Anthropic"
|
|
@@ -270,16 +259,14 @@ OpenRouter fallbacks are disabled globally by default and are appended only with
|
|
|
270
259
|
|
|
271
260
|
[25]: https://openrouter.ai/meta/muse-spark-1.2 "Muse Spark 1.2 on OpenRouter"
|
|
272
261
|
[26]: https://openrouter.ai/meta/muse-spark-1.3-contributor "Muse Spark 1.3 Contributor on OpenRouter"
|
|
273
|
-
[27]: https://openrouter.ai/deepseek/deepseek-v4.1-flash "DeepSeek V4.1 Flash on OpenRouter"
|
|
274
262
|
[28]: https://openrouter.ai/deepseek/deepseek-v4-pro-0813 "DeepSeek V4 Pro 0813 on OpenRouter"
|
|
263
|
+
[29]: https://api-docs.deepseek.com/quick_start/pricing/ "DeepSeek API Pricing"
|
|
275
264
|
|
|
276
265
|
`deepseekPro()` uses the pinned OpenRouter model `deepseek/deepseek-v4-pro-0813` and requires `OPENROUTER_API_KEY`. Use `chain('deepseekPro@100')` for maximum reasoning effort. Cost estimates use the listed base rates and $0.05808/M cached input tokens; actual rates may change, including provider and time-based pricing.
|
|
277
266
|
|
|
278
|
-
`deepseekV41Flash()`
|
|
267
|
+
By default `deepseekV41Flash()` uses the native DeepSeek API (`https://api.deepseek.com/chat/completions`, model `deepseek-flash`, currently V4.1 Flash) and requires `DEEPSEEK_API_KEY`; `MixDeepSeek` remains available for explicit `.attach()` calls. Use `chain('deepseekV41Flash@100')` for maximum reasoning effort. Native cost estimates use [peak rates](https://api-docs.deepseek.com/quick_start/pricing/): $0.30 input / $0.006 cached input / $1.20 output per 1M tokens; actual off-peak charges are half.
|
|
279
268
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
For the native DeepSeek API, use `deepseekV41Flash({ mix: { deepseek: true, openrouter: false } })` with `DEEPSEEK_API_KEY`. It calls `https://api.deepseek.com/chat/completions` with `deepseek-flash`, currently DeepSeek V4.1 Flash. `MixDeepSeek` is also available for explicit `.attach()` calls. Native cost estimates use [peak rates](https://api-docs.deepseek.com/quick_start/pricing/): $0.30 input / $0.006 cached input / $1.20 output per 1M tokens; actual off-peak charges are half. When all three providers are enabled, the order is DeepSeek → Fireworks → OpenRouter.
|
|
269
|
+
Optional routes: `mix: { fireworks: true }` selects `accounts/fireworks/models/deepseek-v4p1-flash` with `FIREWORKS_API_KEY`, priced at [$0.22 input / $0.007 cached input / $0.66 output per 1M tokens](https://fireworks.ai/models/deepseek-ai/deepseek-v4p1-flash), and `mix: { openrouter: true }` selects `deepseek/deepseek-v4.1-flash` with `OPENROUTER_API_KEY`, which accepts text and image input. With all three providers enabled the order is DeepSeek → Fireworks → OpenRouter.
|
|
283
270
|
|
|
284
271
|
Muse Spark methods ending in `c` select Contributor: prompts and outputs may be used to improve Meta products. Methods without `c` select the standard tier. `museSpark12()` now selects standard; use `museSpark12c()` for the previous Contributor behavior.
|
|
285
272
|
|
|
@@ -337,8 +324,7 @@ ModelMix.new().effort(-1).minimaxM3().addText('...').message();
|
|
|
337
324
|
|
|
338
325
|
The former `*think()` methods were removed. Use `.effort(n).<model>()` with `0`–`100` or `-1` instead.
|
|
339
326
|
|
|
340
|
-
- **Kimi:** use `
|
|
341
|
-
- **Grok 4.20:** `.grok420()` selects the non-reasoning model. Use `.effort(20+).grok420()` or `.effort(-1).grok420()` to select the reasoning model.
|
|
327
|
+
- **Kimi:** use `kimiK26()`.
|
|
342
328
|
|
|
343
329
|
## 🔄 Templates
|
|
344
330
|
|
package/demo/demo.js
CHANGED
|
@@ -24,9 +24,9 @@ const pplxSettings = {
|
|
|
24
24
|
|
|
25
25
|
mmix.assign({ name: 'ALF' });
|
|
26
26
|
|
|
27
|
-
console.log("\n" + '--------|
|
|
27
|
+
console.log("\n" + '--------| gpt52() |--------');
|
|
28
28
|
const gptArgs = { options: { reasoning_effort: "none", verbosity: "low" } };
|
|
29
|
-
const gpt = mmix.
|
|
29
|
+
const gpt = mmix.gpt52(gptArgs).addText("Have you ever eaten a <%- animal %>?");
|
|
30
30
|
gpt.assignKey('animal', 'cat');
|
|
31
31
|
await gpt.json({ time: '24:00:00', message: 'Hello' }, { time: 'Time in format HH:MM:SS' });
|
|
32
32
|
|
package/demo/fallback.js
CHANGED
package/demo/free.js
CHANGED
|
@@ -2,9 +2,9 @@ import { ModelMix } from '../index.js';
|
|
|
2
2
|
try { process.loadEnvFile(); } catch {}
|
|
3
3
|
|
|
4
4
|
const ai = ModelMix.new({ config: { debug: 2 } })
|
|
5
|
-
.
|
|
6
|
-
.
|
|
5
|
+
.kimiK26()
|
|
6
|
+
.GLM52()
|
|
7
7
|
.addText('What is the capital of France?');
|
|
8
8
|
|
|
9
9
|
const response = await ai.message();
|
|
10
|
-
console.log('Response from
|
|
10
|
+
console.log('Response from chained multi-provider models:', response);
|
package/demo/gemini.js
CHANGED
|
@@ -20,9 +20,9 @@ const flash = await mmix.gemini38flash()
|
|
|
20
20
|
|
|
21
21
|
console.log(flash);
|
|
22
22
|
|
|
23
|
-
// Using Gemini 3.
|
|
24
|
-
console.log("\n" + '--------|
|
|
25
|
-
const pro = mmix.new().
|
|
23
|
+
// Using Gemini 3.7 Flash with custom config
|
|
24
|
+
console.log("\n" + '--------| gemini37flash() with JSON response |--------');
|
|
25
|
+
const pro = mmix.new().gemini37flash();
|
|
26
26
|
|
|
27
27
|
pro.addText('Give me a fun fact about cats');
|
|
28
28
|
|
package/demo/json.js
CHANGED
package/demo/round-robin.js
CHANGED
|
@@ -11,11 +11,11 @@ const ai = ModelMix.new({
|
|
|
11
11
|
},
|
|
12
12
|
mix: { openrouter: false } // Exclude OpenRouter (free tier often rate-limited)
|
|
13
13
|
})
|
|
14
|
-
.
|
|
14
|
+
.kimiK26({ mix: { fireworks: true, together: true } });
|
|
15
15
|
|
|
16
16
|
console.log('Making 6 requests with round robin enabled...\n');
|
|
17
17
|
|
|
18
|
-
// Make 6 requests to see rotation through all models (
|
|
18
|
+
// Make 6 requests to see rotation through all models (fireworks + together)
|
|
19
19
|
for (let i = 1; i <= 6; i++) {
|
|
20
20
|
const result = await ai.new()
|
|
21
21
|
.addText(`Calculate ${i} * 2`)
|
package/demo/short.js
CHANGED
|
@@ -10,7 +10,7 @@ const setup = {
|
|
|
10
10
|
|
|
11
11
|
const mmix = await ModelMix.new(setup)
|
|
12
12
|
.fable51({ mix: { openrouter: true } }) // (main + provider fallback) Anthropic/OpenRouter Claude Fable 5.1
|
|
13
|
-
.
|
|
13
|
+
.sonnet5() // (fallback 2) Anthropic claude-sonnet-5
|
|
14
14
|
.gpt56luna({ mix: { openrouter: true } }) // (fallback 3 + provider fallback) OpenAI/OpenRouter gpt-5.6-luna
|
|
15
15
|
.gemini38flash() // (fallback 4) Google gemini-3.8-flash
|
|
16
16
|
.gpt5nano({ mix: { openrouter: true } }) // (fallback 5 + provider fallback) OpenAI/OpenRouter gpt-5-nano
|
package/effort.js
CHANGED
|
@@ -141,7 +141,7 @@ const PROVIDER_FAMILY_BY_CLASS = {
|
|
|
141
141
|
MixCustom: null,
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
/** Logical alias
|
|
144
|
+
/** Logical alias key `grok-4.20-0309` — resolved to reasoning / non-reasoning at request time. */
|
|
145
145
|
const GROK420_ALIAS = 'grok-4.20-0309';
|
|
146
146
|
const GROK420_REASONING = 'grok-4.20-0309-reasoning';
|
|
147
147
|
const GROK420_NON_REASONING = 'grok-4.20-0309-non-reasoning';
|
package/index.d.ts
CHANGED
|
@@ -445,10 +445,8 @@ export declare class ModelMix {
|
|
|
445
445
|
attach(key: string, provider: MixCustom): this;
|
|
446
446
|
|
|
447
447
|
// OpenAI
|
|
448
|
-
gpt5(args?: ModelAttachArgs): this;
|
|
449
448
|
gpt5mini(args?: ModelAttachArgs): this;
|
|
450
449
|
gpt5nano(args?: ModelAttachArgs): this;
|
|
451
|
-
gpt51(args?: ModelAttachArgs): this;
|
|
452
450
|
gpt52(args?: ModelAttachArgs): this;
|
|
453
451
|
gpt54(args?: ModelAttachArgs): this;
|
|
454
452
|
gpt54mini(args?: ModelAttachArgs): this;
|
|
@@ -464,9 +462,6 @@ export declare class ModelMix {
|
|
|
464
462
|
gpt56luna(args?: ModelAttachArgs): this;
|
|
465
463
|
gptRealtime(args?: ModelAttachArgs): this;
|
|
466
464
|
gptRealtimeMini(args?: ModelAttachArgs): this;
|
|
467
|
-
gpt53codex(args?: ModelAttachArgs): this;
|
|
468
|
-
gpt53chat(args?: ModelAttachArgs): this;
|
|
469
|
-
gptOss(args?: ModelAttachArgs): this;
|
|
470
465
|
|
|
471
466
|
// Anthropic
|
|
472
467
|
fable51(args?: ModelAttachArgs): this;
|
|
@@ -480,12 +475,10 @@ export declare class ModelMix {
|
|
|
480
475
|
opus46(args?: ModelAttachArgs): this;
|
|
481
476
|
sonnet50(args?: ModelAttachArgs): this;
|
|
482
477
|
sonnet5(args?: ModelAttachArgs): this;
|
|
483
|
-
sonnet46(args?: ModelAttachArgs): this;
|
|
484
478
|
sonnet45(args?: ModelAttachArgs): this;
|
|
485
479
|
haiku45(args?: ModelAttachArgs): this;
|
|
486
480
|
|
|
487
481
|
// Google
|
|
488
|
-
gemini31pro(args?: ModelAttachArgs): this;
|
|
489
482
|
gemini38flash(args?: ModelAttachArgs): this;
|
|
490
483
|
gemini37flash(args?: ModelAttachArgs): this;
|
|
491
484
|
gemini36flash(args?: ModelAttachArgs): this;
|
|
@@ -500,11 +493,7 @@ export declare class ModelMix {
|
|
|
500
493
|
// Grok
|
|
501
494
|
grok47(args?: ModelAttachArgs): this;
|
|
502
495
|
grok46(args?: ModelAttachArgs): this;
|
|
503
|
-
grok45(args?: ModelAttachArgs): this;
|
|
504
496
|
grok43(args?: ModelAttachArgs): this;
|
|
505
|
-
grok420multiAgent(args?: ModelAttachArgs): this;
|
|
506
|
-
/** Non-reasoning by default; with `.effort(20+)` / `-1` uses the reasoning model at request time. */
|
|
507
|
-
grok420(args?: ModelAttachArgs): this;
|
|
508
497
|
|
|
509
498
|
// Multi-provider
|
|
510
499
|
museGlimmer30b(args?: ModelAttachArgs): this;
|
|
@@ -524,7 +513,6 @@ export declare class ModelMix {
|
|
|
524
513
|
kimiK26(args?: ModelAttachArgs): this;
|
|
525
514
|
kimiK27Code(args?: ModelAttachArgs): this;
|
|
526
515
|
kimiK3(args?: ModelAttachArgs): this;
|
|
527
|
-
kimiK25(args?: ModelAttachArgs): this;
|
|
528
516
|
lmstudio(model?: string, args?: ModelAttachArgs): this;
|
|
529
517
|
minimaxM27(args?: ModelAttachArgs): this;
|
|
530
518
|
minimaxM3(args?: ModelAttachArgs): this;
|
package/index.js
CHANGED
|
@@ -463,18 +463,12 @@ class ModelMix {
|
|
|
463
463
|
return this;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
gpt5(args = {}) {
|
|
467
|
-
return this._attachOpenAIWithOpenRouter('gpt-5', MixOpenAI, args);
|
|
468
|
-
}
|
|
469
466
|
gpt5mini(args = {}) {
|
|
470
467
|
return this._attachOpenAIWithOpenRouter('gpt-5-mini', MixOpenAI, args);
|
|
471
468
|
}
|
|
472
469
|
gpt5nano(args = {}) {
|
|
473
470
|
return this._attachOpenAIWithOpenRouter('gpt-5-nano', MixOpenAI, args);
|
|
474
471
|
}
|
|
475
|
-
gpt51(args = {}) {
|
|
476
|
-
return this._attachOpenAIWithOpenRouter('gpt-5.1', MixOpenAIResponses, args);
|
|
477
|
-
}
|
|
478
472
|
gpt52(args = {}) {
|
|
479
473
|
return this._attachOpenAIWithOpenRouter('gpt-5.2', MixOpenAIResponses, args);
|
|
480
474
|
}
|
|
@@ -520,25 +514,6 @@ class ModelMix {
|
|
|
520
514
|
gptRealtimeMini({ options = {}, config = {} } = {}) {
|
|
521
515
|
return this.attach('gpt-realtime-mini', new MixOpenAIWebSocket({ options, config }));
|
|
522
516
|
}
|
|
523
|
-
gpt53codex(args = {}) {
|
|
524
|
-
return this._attachOpenAIWithOpenRouter('gpt-5.3-codex', MixOpenAIResponses, args);
|
|
525
|
-
}
|
|
526
|
-
gpt53chat(args = {}) {
|
|
527
|
-
return this._attachOpenAIWithOpenRouter('gpt-5.3-chat-latest', MixOpenAIResponses, {
|
|
528
|
-
...args,
|
|
529
|
-
openRouterKey: 'openai/gpt-5.3-chat'
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
gptOss({ options = {}, config = {}, mix = {} } = {}) {
|
|
533
|
-
mix = { ...this.mix, ...mix };
|
|
534
|
-
if (mix.nvidia) this.attach('openai/gpt-oss-120b', new MixNVIDIA({ options, config }));
|
|
535
|
-
if (mix.fireworks) this.attach('accounts/fireworks/models/gpt-oss-120b', new MixFireworks({ options, config }));
|
|
536
|
-
if (mix.together) this.attach('openai/gpt-oss-120b', new MixTogether({ options, config }));
|
|
537
|
-
if (mix.cerebras) this.attach('gpt-oss-120b', new MixCerebras({ options, config }));
|
|
538
|
-
if (mix.groq) this.attach('openai/gpt-oss-120b', new MixGroq({ options, config }));
|
|
539
|
-
if (mix.openrouter) this.attach('openai/gpt-oss-120b', new MixOpenRouter({ options, config }));
|
|
540
|
-
return this;
|
|
541
|
-
}
|
|
542
517
|
fable50({ options = {}, config = {} } = {}) {
|
|
543
518
|
return this.attach('claude-fable-5', new MixAnthropic({ options, config }));
|
|
544
519
|
}
|
|
@@ -575,18 +550,12 @@ class ModelMix {
|
|
|
575
550
|
sonnet5(args = {}) {
|
|
576
551
|
return this.sonnet50(args);
|
|
577
552
|
}
|
|
578
|
-
sonnet46({ options = {}, config = {} } = {}) {
|
|
579
|
-
return this.attach('claude-sonnet-4-6', new MixAnthropic({ options, config }));
|
|
580
|
-
}
|
|
581
553
|
sonnet45({ options = {}, config = {} } = {}) {
|
|
582
554
|
return this.attach('claude-sonnet-4-5-20250929', new MixAnthropic({ options, config }));
|
|
583
555
|
}
|
|
584
556
|
haiku45({ options = {}, config = {} } = {}) {
|
|
585
557
|
return this.attach('claude-haiku-4-5-20251001', new MixAnthropic({ options, config }));
|
|
586
558
|
}
|
|
587
|
-
gemini31pro({ options = {}, config = {} } = {}) {
|
|
588
|
-
return this.attach('gemini-3.1-pro-preview', new MixGoogle({ options, config }));
|
|
589
|
-
}
|
|
590
559
|
gemini38flash({ options = {}, config = {} } = {}) {
|
|
591
560
|
return this.attach('gemini-3.8-flash', new MixGoogle({ options, config }));
|
|
592
561
|
}
|
|
@@ -618,19 +587,9 @@ class ModelMix {
|
|
|
618
587
|
grok46({ options = {}, config = {} } = {}) {
|
|
619
588
|
return this.attach('grok-4.6', new MixGrok({ options, config }));
|
|
620
589
|
}
|
|
621
|
-
grok45({ options = {}, config = {} } = {}) {
|
|
622
|
-
return this.attach('grok-4.5', new MixGrok({ options, config }));
|
|
623
|
-
}
|
|
624
590
|
grok43({ options = {}, config = {} } = {}) {
|
|
625
591
|
return this.attach('grok-4.3', new MixGrok({ options, config }));
|
|
626
592
|
}
|
|
627
|
-
grok420multiAgent({ options = {}, config = {} } = {}) {
|
|
628
|
-
return this.attach('grok-4.20-multi-agent-0309', new MixGrok({ options, config }));
|
|
629
|
-
}
|
|
630
|
-
/** Non-reasoning by default; with `.effort(20+)` / `-1` resolves to the reasoning model at request time. */
|
|
631
|
-
grok420({ options = {}, config = {} } = {}) {
|
|
632
|
-
return this.attach('grok-4.20-0309', new MixGrok({ options, config }));
|
|
633
|
-
}
|
|
634
593
|
|
|
635
594
|
museGlimmer30b({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
|
|
636
595
|
mix = { ...this.mix, ...mix };
|
|
@@ -732,14 +691,6 @@ class ModelMix {
|
|
|
732
691
|
return this;
|
|
733
692
|
}
|
|
734
693
|
|
|
735
|
-
kimiK25({ options = {}, config = {}, mix = { together: true } } = {}) {
|
|
736
|
-
mix = { ...this.mix, ...mix };
|
|
737
|
-
if (mix.together) this.attach('moonshotai/Kimi-K2.5', new MixTogether({ options, config }));
|
|
738
|
-
if (mix.fireworks) this.attach('accounts/fireworks/models/kimi-k2p5', new MixFireworks({ options, config }));
|
|
739
|
-
if (mix.openrouter) this.attach('moonshotai/kimi-k2.5', new MixOpenRouter({ options, config }));
|
|
740
|
-
return this;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
694
|
lmstudio(model = 'lmstudio', { options = {}, config = {} } = {}) {
|
|
744
695
|
return this.attach(model, new MixLMStudio({ options, config }));
|
|
745
696
|
}
|
|
@@ -1804,7 +1755,7 @@ class ModelMix {
|
|
|
1804
1755
|
});
|
|
1805
1756
|
} else {
|
|
1806
1757
|
if (!this.models || this.models.length === 0) {
|
|
1807
|
-
throw new Error('No models specified. Use methods like .
|
|
1758
|
+
throw new Error('No models specified. Use methods like .gpt5mini(), .sonnet5() first.');
|
|
1808
1759
|
}
|
|
1809
1760
|
execution = this.limiter.schedule(() => {
|
|
1810
1761
|
throwIfAborted(signal);
|
package/lib/model-chain.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
const { normalizeEffort } = require('../effort');
|
|
2
2
|
|
|
3
3
|
const CHAIN_MODEL_SHORTCUTS = new Set([
|
|
4
|
-
'
|
|
5
|
-
'
|
|
4
|
+
'gpt5mini', 'gpt5nano',
|
|
5
|
+
'gpt52', 'gpt54', 'gpt54mini', 'gpt54nano', 'gpt54pro',
|
|
6
6
|
'gpt6astra', 'gpt6sol', 'gpt6luna', 'gpt55', 'gpt55pro', 'gpt56sol', 'gpt56terra', 'gpt56luna',
|
|
7
|
-
'gptRealtime', 'gptRealtimeMini',
|
|
7
|
+
'gptRealtime', 'gptRealtimeMini',
|
|
8
8
|
'fable51', 'fable50', 'fable5', 'opus55', 'opus50', 'opus5', 'opus48', 'opus47', 'opus46',
|
|
9
|
-
'sonnet50', 'sonnet5', '
|
|
10
|
-
'
|
|
9
|
+
'sonnet50', 'sonnet5', 'sonnet45', 'haiku45',
|
|
10
|
+
'gemini38flash', 'gemini37flash', 'gemini36flash', 'gemini35flash',
|
|
11
11
|
'gemini35flashLite', 'gemini31flashLite', 'sonarPro', 'sonar',
|
|
12
|
-
'grok47', 'grok46', '
|
|
12
|
+
'grok47', 'grok46', 'grok43',
|
|
13
13
|
'museGlimmer30b', 'museSpark12', 'museSpark12c', 'museSpark13', 'museSpark13c',
|
|
14
14
|
'qwen35397b', 'qwen36plus', 'qwen37plus', 'qwen38max', 'qwen3827b', 'qwen38flash',
|
|
15
15
|
'hermes470b', 'hermes4405b', 'hermes3',
|
|
16
|
-
'kimiK26', 'kimiK27Code', 'kimiK3',
|
|
16
|
+
'kimiK26', 'kimiK27Code', 'kimiK3',
|
|
17
17
|
'minimaxM27', 'minimaxM3', 'mimo25', 'mimo25pro', 'mimo26pro',
|
|
18
18
|
'deepseekV4Pro', 'deepseekPro', 'deepseekV4Flash', 'deepseekV41Flash', 'GLM52', 'GLM53', 'GLM53Flash'
|
|
19
19
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelmix",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.1",
|
|
4
4
|
"description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -82,6 +82,5 @@
|
|
|
82
82
|
"test:benchmark": "mocha plugins/benchmark/test/**/*.test.js --timeout 10000 --require test/setup.js",
|
|
83
83
|
"test:rlm": "mocha plugins/rlm/test/**/*.test.js --timeout 10000 --require test/setup.js",
|
|
84
84
|
"test:offline": "mocha test/abort.test.js 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 test/effort.test.js test/grok.test.js test/google.test.js test/moderation.test.js test/plugins.test.js plugins/skills/test/**/*.test.js plugins/benchmark/test/**/*.test.js plugins/rlm/test/**/*.test.js --timeout 10000 --require test/setup.js"
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
}
|
|
85
|
+
}
|
|
86
|
+
}
|