modelmix 5.2.3 → 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/README.md CHANGED
@@ -138,11 +138,11 @@ const ETH = ModelMix.new()
138
138
  console.log(ETH.price);
139
139
  ```
140
140
 
141
- **This example uses providers with free quotas (Groq, Cerebras, and Together). OpenRouter is disabled because its GPT-OSS 120B route is no longer free. If one model runs out of quota, ModelMix automatically falls back to the next model in the chain.**
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
- .gptOss()
145
- .kimiK25()
144
+ .kimiK26()
145
+ .GLM52()
146
146
  .addText('What is the capital of France?');
147
147
  ```
148
148
 
@@ -160,7 +160,9 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
160
160
  | Method | Provider | Model | Input / 1M | Output / 1M |
161
161
  | --- | --- | --- | ---: | ---: |
162
162
  | `gpt6astra()` | OpenAI | gpt-6-astra | [\$10.00][1] | [\$50.00][1] |
163
- | `gpt56sol()` | OpenAI | gpt-5.6-sol | [\$5.00][1] | [\$30.00][1] |
163
+ | `gpt6sol()` | OpenAI | gpt-6-sol | [\$2.00][1] | [\$10.00][1] |
164
+ | `gpt6luna()` | OpenAI | gpt-6-luna | [\$0.10][1] | [\$0.50][1] |
165
+ | `gpt56sol()` | OpenAI | gpt-5.6-sol | [\$4.00][1] | [\$20.00][1] |
164
166
  | `gpt56terra()` | OpenAI | gpt-5.6-terra | [\$2.00][1] | [\$12.00][1] |
165
167
  | `gpt56luna()` | OpenAI | gpt-5.6-luna | [\$0.20][1] | [\$1.20][1] |
166
168
  | `gpt55()` | OpenAI | gpt-5.5 | [\$5.00][1] | [\$30.00][1] |
@@ -169,14 +171,9 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
169
171
  | `gpt54mini()` | OpenAI | gpt-5.4-mini | [\$0.75][1] | [\$4.50][1] |
170
172
  | `gpt54nano()` | OpenAI | gpt-5.4-nano | [\$0.20][1] | [\$1.25][1] |
171
173
  | `gpt54pro()` | OpenAI | gpt-5.4-pro | [\$30.00][1] | [\$180.00][1] |
172
- | `gpt53codex()` | OpenAI | gpt-5.3-codex | [\$1.75][1] | [\$14.00][1] |
173
- | `gpt53chat()` | OpenAI | gpt-5.3-chat-latest | [\$1.75][1] | [\$14.00][1] |
174
174
  | `gpt52()` | OpenAI | gpt-5.2 | [\$1.75][1] | [\$14.00][1] |
175
- | `gpt51()` | OpenAI | gpt-5.1 | [\$1.25][1] | [\$10.00][1] |
176
- | `gpt5()` | OpenAI | gpt-5 | [\$1.25][1] | [\$10.00][1] |
177
175
  | `gpt5mini()` | OpenAI | gpt-5-mini | [\$0.25][1] | [\$2.00][1] |
178
176
  | `gpt5nano()` | OpenAI | gpt-5-nano | [\$0.05][1] | [\$0.40][1] |
179
- | `gptOss()` | Multi-provider | gpt-oss-120B | [\$0.15][7] | [\$0.60][7] |
180
177
  | `fable51()` | Anthropic | claude-fable-5-1 | [\$10.00][2] | [\$50.00][2] |
181
178
  | `fable5()` | Anthropic | claude-fable-5 | [\$10.00][2] | [\$50.00][2] |
182
179
  | `opus55()` | Anthropic | claude-opus-5-5 | [\$5.00][2] | [\$25.00][2] |
@@ -185,9 +182,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
185
182
  | `opus47()` | Anthropic | claude-opus-4-7 | [\$5.00][2] | [\$25.00][2] |
186
183
  | `opus46()` | Anthropic | claude-opus-4-6 | [\$5.00][2] | [\$25.00][2] |
187
184
  | `sonnet5()` | Anthropic | claude-sonnet-5 | [\$3.00][2] | [\$15.00][2] |
188
- | `sonnet46()` | Anthropic | claude-sonnet-4-6 | [\$3.00][2] | [\$15.00][2] |
189
185
  | `haiku45()` | Anthropic | claude-haiku-4-5-20251001 | [\$1.00][2] | [\$5.00][2] |
190
- | `gemini31pro()` | Google | gemini-3.1-pro-preview | [\$2.00][3] | [\$12.00][3] |
191
186
  | `gemini38flash()` | Google | gemini-3.8-flash | [\$0.75][3] | [\$3.75][3] |
192
187
  | `gemini37flash()` | Google | gemini-3.7-flash | [\$0.75][3] | [\$3.75][3] |
193
188
  | `gemini36flash()` | Google | gemini-3.6-flash | [\$0.75][3] | [\$3.75][3] |
@@ -196,10 +191,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
196
191
  | `gemini31flashLite()` | Google | gemini-3.1-flash-lite-preview | [\$0.25][3] | [\$1.50][3] |
197
192
  | `grok47()` | Grok | grok-4.7 | — | — |
198
193
  | `grok46()` | Grok | grok-4.6 | [\$2.00][6] | [\$6.00][6] |
199
- | `grok45()` | Grok | grok-4.5 | [\$2.00][6] | [\$6.00][6] |
200
194
  | `grok43()` | Grok | grok-4.3 | [\$1.25][6] | [\$2.50][6] |
201
- | `grok420multiAgent()` | Grok | grok-4.20-multi-agent-0309 | [\$1.25][6] | [\$2.50][6] |
202
- | `grok420()` | Grok | grok-4.20-0309 (†) | [\$1.25][6] | [\$2.50][6] |
203
195
  | `museGlimmer30b()` | Fireworks | models/muse-glimmer-30b | [\$0.35][17] | [\$1.50][17] |
204
196
  | `museSpark12()` | OpenRouter | meta/muse-spark-1.2 | [\$1.25][25] | [\$4.25][25] |
205
197
  | `museSpark12c()` | OpenRouter | meta/muse-spark-1.2-contributor | [\$0.10][22] | [\$0.20][22] |
@@ -212,7 +204,7 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
212
204
  | `qwen3827b()` | OpenRouter | qwen/qwen3.8-27b | [\$0.45][15] | [\$3.20][15] |
213
205
  | `qwen38flash()` | OpenRouter | qwen/qwen3.8-flash | [\$0.16][19] | [\$0.47][19] |
214
206
  | `deepseekV4Flash()` | Fireworks | models/deepseek-v4-flash | [\$0.14][10] | [\$0.28][10] |
215
- | `deepseekV41Flash()` | OpenRouter | deepseek/deepseek-v4.1-flash | [\$0.15][27] | [\$0.60][27] |
207
+ | `deepseekV41Flash()` | DeepSeek | deepseek-flash | [\$0.30][29] | [\$1.20][29] |
216
208
  | `deepseekV4Pro()` | Fireworks | models/deepseek-v4-pro-0813 | [\$1.32][12] | [\$3.96][12] |
217
209
  | `deepseekPro()` | OpenRouter | deepseek/deepseek-v4-pro-0813 | [\$0.5808][28] | [\$1.7424][28] |
218
210
  | `GLM53()` | OpenRouter | z-ai/glm-5.3 | [\$1.40][16] | [\$4.40][16] |
@@ -228,7 +220,6 @@ ModelMix provides convenient shorthand methods for quickly accessing different A
228
220
  | `hermes3()` | Lambda | Hermes-3-Llama-3.1-405B-FP8 | [\$0.80][8] | [\$0.80][8] |
229
221
  | `kimiK3()` | Moonshot | kimi-k3 | [\$3.00][11] | [\$15.00][11] |
230
222
  | `kimiK27Code()` | Together | Kimi-K2.7-Code | [\$0.95][7] | [\$4.00][7] |
231
- | `kimiK25()` | Together | Kimi-K2.5 | [\$0.50][7] | [\$2.80][7] |
232
223
  | `kimiK26()` | Fireworks | models/kimi-k2p6 | [\$0.95][10] | [\$4.00][10] |
233
224
 
234
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.
@@ -237,9 +228,9 @@ Gemini 3.8 Flash, 3.7 Flash, and 3.6 Flash use Google's introductory standard pr
237
228
 
238
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.
239
230
 
240
- 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. `gpt53chat()` maps the official `gpt-5.3-chat-latest` alias to `openai/gpt-5.3-chat`. Realtime shortcuts remain official-only because they use OpenAI's WebSocket transport.
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.
241
232
 
242
- 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: `gptOss()` supports NVIDIA and Fireworks; `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.
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.
243
234
 
244
235
  [1]: https://platform.openai.com/docs/pricing "Pricing | OpenAI"
245
236
  [2]: https://docs.anthropic.com/en/docs/about-claude/pricing "Pricing - Anthropic"
@@ -268,16 +259,14 @@ OpenRouter fallbacks are disabled globally by default and are appended only with
268
259
 
269
260
  [25]: https://openrouter.ai/meta/muse-spark-1.2 "Muse Spark 1.2 on OpenRouter"
270
261
  [26]: https://openrouter.ai/meta/muse-spark-1.3-contributor "Muse Spark 1.3 Contributor on OpenRouter"
271
- [27]: https://openrouter.ai/deepseek/deepseek-v4.1-flash "DeepSeek V4.1 Flash on OpenRouter"
272
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"
273
264
 
274
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.
275
266
 
276
- `deepseekV41Flash()` supports text and image input through OpenRouter and requires `OPENROUTER_API_KEY`. Use `chain('deepseekV41Flash@100')` for maximum reasoning effort. Cost estimates use the listed base rates and $0.015/M cached input tokens; actual OpenRouter pricing varies by provider and time.
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.
277
268
 
278
- For direct Fireworks access, use `deepseekV41Flash({ mix: { fireworks: true, openrouter: false } })` with `FIREWORKS_API_KEY`. This selects `accounts/fireworks/models/deepseek-v4p1-flash`, priced at [$0.22 input / $0.007 cached input / $0.66 output per 1M tokens](https://fireworks.ai/models/deepseek-ai/deepseek-v4p1-flash). Set both providers to `true` to try Fireworks first and fall back to OpenRouter.
279
-
280
- 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.
281
270
 
282
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.
283
272
 
@@ -320,6 +309,7 @@ ModelMix.new().effort(-1).minimaxM3().addText('...').message();
320
309
 
321
310
  - **Gemini:** Gemini 3+ uses bands 0–24 / 25–49 / 50–74 / 75–100. Gemini 3.8 Flash and 3.7 Flash clamp these bands to `low` / `low` / `medium` / `high`; `-1` leaves their native `medium` default unchanged. Gemini 2.5 maps 0–100 to `thinkingBudget`.
322
311
  - **GPT-6 Astra:** 0–39 maps to `low`, 40–59 to `medium`, 60–79 to `high`, 80–99 to `xhigh`, and 100 to `max`. [Model details](https://developers.openai.com/api/docs/models/gpt-6-astra). Cache reads cost $1.00 and cache writes $12.50 per 1M tokens; requests over 272K input tokens apply 2× input/cache and 1.5× output rates.
312
+ - **GPT-6 Sol and GPT-6 Luna:** `100` maps to `max`; the remaining bands match OpenAI, so 0–19 is `none` and 80–99 is `xhigh`. [Sol model details](https://developers.openai.com/api/docs/models/gpt-6-sol), [Luna model details](https://developers.openai.com/api/docs/models/gpt-6-luna). Cache reads cost $0.20 and $0.01 and cache writes $2.50 and $0.125 per 1M tokens; requests over 272K input tokens apply the same 2× input/cache and 1.5× output rates as Astra.
323
313
  - **GPT-5.6:** `100` maps to `max`; 80–99 remains `xhigh`.
324
314
  - **Qwen 3.8 27B and Flash:** 0–39 / 40–79 / 80–100 map to `low` / `medium` / `xhigh`; `-1` leaves the native `xhigh` default unchanged. Qwen 3.8 Flash is the managed production version based on the open-weight Flash-Next architecture.
325
315
  - **GLM 5.3 and GLM 5.3 Flash:** reasoning is mandatory; 0–39 / 40–79 / 80–100 map to `low` / `high` / `max`; `-1` leaves the native `max` default unchanged.
@@ -334,8 +324,7 @@ ModelMix.new().effort(-1).minimaxM3().addText('...').message();
334
324
 
335
325
  The former `*think()` methods were removed. Use `.effort(n).<model>()` with `0`–`100` or `-1` instead.
336
326
 
337
- - **Kimi:** use `kimiK25()` or `kimiK26()`.
338
- - **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()`.
339
328
 
340
329
  ## 🔄 Templates
341
330
 
@@ -831,9 +820,9 @@ await ask('Summarize support ticket 456.');
831
820
 
832
821
  The contents of `support.md` and the cache key stay the same between calls; only the final question changes. The first request may report `cacheWrite > 0`, while later requests confirm reuse with `cached > 0`. For GPT-5.6, the stable prefix must contain at least 1,024 tokens. Keep all variable content after the breakpoint, and change `prompt_cache_key` when the stable instructions change.
833
822
 
834
- ### GPT-5.6 prompt caching
823
+ ### GPT-5.6 and GPT-6 prompt caching
835
824
 
836
- GPT-5.6 supports implicit or explicit caching through `prompt_cache_options`. Put the explicit breakpoint at the end of the stable prefix; the provider only caches prompts with at least 1,024 tokens.
825
+ GPT-5.6 and the GPT-6 models (Astra, Sol, and Luna) support implicit or explicit caching through `prompt_cache_options`. Put the explicit breakpoint at the end of the stable prefix; the provider only caches prompts with at least 1,024 tokens.
837
826
 
838
827
  ```javascript
839
828
  const model = ModelMix.new()
@@ -854,16 +843,18 @@ console.log(result.tokens.cached, result.tokens.cacheWrite, result.tokens.cost);
854
843
 
855
844
  The provider-neutral `cache: { breakpoint: true }` option is accepted by `addTextFromFile()`, `addImage()`, `addImageFromUrl()`, and `addImageFromBuffer()`. Responses-native `input_text`, `input_image`, and `input_file` blocks preserve the native `prompt_cache_breakpoint` field when supplied directly through `options.messages`.
856
845
 
857
- GPT-5.6 uses `prompt_cache_options.ttl`; `prompt_cache_retention` remains available for earlier OpenAI models. ModelMix rejects the incompatible control instead of silently dropping it. For GPT-5.6 requests over 272K input tokens, the cost calculation applies the documented 2× input and 1.5× output multipliers to the complete request, including cache reads and writes.
846
+ GPT-5.6 and GPT-6 use `prompt_cache_options.ttl`; `prompt_cache_retention` remains available for earlier OpenAI models. ModelMix rejects the incompatible control instead of silently dropping it. For GPT-5.6 requests over 272K input tokens, the cost calculation applies the documented 2× input and 1.5× output multipliers to the complete request, including cache reads and writes.
858
847
 
859
848
  GPT-5.6 prices per 1M tokens:
860
849
 
861
850
  | Model | Input | Cached input | Cache write | Output |
862
851
  | --- | ---: | ---: | ---: | ---: |
863
- | `gpt-5.6-sol` | $5.00 | $0.50 | $6.25 | $30.00 |
852
+ | `gpt-5.6-sol` | $4.00 | $0.40 | $5.00 | $20.00 |
864
853
  | `gpt-5.6-terra` | $2.00 | $0.20 | $2.50 | $12.00 |
865
854
  | `gpt-5.6-luna` | $0.20 | $0.02 | $0.25 | $1.20 |
866
855
 
856
+ GPT-5.6 Sol's $4.00 input and $20.00 output rates are promotional and available at least through November 21, 2026.
857
+
867
858
  ### Cross-provider cache fallback
868
859
 
869
860
  Neutral breakpoints are translated at the last moment by each provider adapter. Native request policies remain scoped to their model, so they cannot leak into a fallback request:
@@ -885,7 +876,7 @@ const model = ModelMix.new()
885
876
  .addText('Answer this variable request.');
886
877
  ```
887
878
 
888
- GPT-5.6 receives `prompt_cache_breakpoint`; Anthropic receives `cache_control`; older OpenAI models and providers without an equivalent omit the marker. When a neutral explicit breakpoint is present for Anthropic, its model-scoped `cache_control` becomes that block's policy instead of adding an automatic breakpoint after the variable suffix.
879
+ GPT-5.6 and GPT-6 receive `prompt_cache_breakpoint`; Anthropic receives `cache_control`; older OpenAI models and providers without an equivalent omit the marker. When a neutral explicit breakpoint is present for Anthropic, its model-scoped `cache_control` becomes that block's policy instead of adding an automatic breakpoint after the variable suffix.
889
880
 
890
881
  ## 🔧 Model Context Protocol (MCP) Integration
891
882
 
@@ -1055,7 +1046,7 @@ Pass `mix` to `benchmark()` to select providers for the criteria model, particip
1055
1046
 
1056
1047
  JSON parsing accepts a Markdown code block or a lone closing triple-backtick delimiter after valid JSON. Other extra content, malformed JSON, and invalid evaluation scores remain errors.
1057
1048
 
1058
- Run `node demo/benchmark.js` for a complete five-model comparison. It allows up to 32,768 output tokens per call, prints intermediate progress, a final ranking and error details, then saves each response as Markdown together with the full JSON report under `demo/results/`.
1049
+ Run `node demo/benchmark.js` for a complete model comparison. It allows up to 32,768 output tokens per call, prints intermediate progress, a final ranking and error details, then saves each response as Markdown together with the full JSON report under `demo/results/`.
1059
1050
 
1060
1051
  ### Recursive Language Model plugin
1061
1052
 
package/demo/benchmark.js CHANGED
@@ -11,16 +11,13 @@ const { benchmark } = benchmarkPlugin;
11
11
  const task = await readFile(process.argv[2] || new URL('./prompts/story.txt', import.meta.url), 'utf8');
12
12
 
13
13
  const models = [
14
- // 'opus50@20',
15
- 'gpt6astra@0',
16
- 'gpt6astra@20',
14
+ 'gpt6sol@40',
15
+ 'gpt6luna@40',
17
16
  'gpt56sol@40',
18
- // 'gemini38flash@20',
19
- // 'grok46@20',
20
- 'deepseekV41Flash@60'
17
+ 'gpt56luna@40'
21
18
  ];
22
19
 
23
- console.log(`Running benchmark: ${models.length} models, 26 sequential model calls.`);
20
+ console.log(`Running benchmark: ${models.length} models, 17 sequential model calls.`);
24
21
 
25
22
  const report = await ModelMix.new({
26
23
  config: { debug: 1 },
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" + '--------| gpt51() |--------');
27
+ console.log("\n" + '--------| gpt52() |--------');
28
28
  const gptArgs = { options: { reasoning_effort: "none", verbosity: "low" } };
29
- const gpt = mmix.gpt51(gptArgs).addText("Have you ever eaten a <%- animal %>?");
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
@@ -15,7 +15,7 @@ const mmix = new ModelMix({
15
15
  }
16
16
  });
17
17
 
18
- mmix.sonnet46({ config: { url: 'fail' } }).gpt5nano();
18
+ mmix.sonnet5({ config: { url: 'fail' } }).gpt5nano();
19
19
 
20
20
  async function main() {
21
21
  mmix.addText('hola, como estas?');
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
- .gptOss()
6
- .kimiK25()
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 a free-tier provider:', response);
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.1 Pro with custom config
24
- console.log("\n" + '--------| gemini31pro() with JSON response |--------');
25
- const pro = mmix.new().gemini31pro();
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
@@ -3,7 +3,6 @@ try { process.loadEnvFile(); } catch {}
3
3
 
4
4
  const model = await ModelMix.new({ options: { max_tokens: 10000 }, config: { debug: 3 } })
5
5
  .gpt54nano()
6
- // .gptOss()
7
6
  // .o4mini()
8
7
  // .gpt45()
9
8
  // .gemini37flash()
@@ -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
- .gptOss();
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 (cerebras + groq)
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
- .sonnet46() // (fallback 2) Anthropic claude-sonnet-4-6
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
@@ -43,6 +43,8 @@ const GLM53_BANDS = [
43
43
  /** Exact model → supported OpenAI reasoning_effort values */
44
44
  const OPENAI_MODEL_LEVELS = {
45
45
  'gpt-6-astra': ['low', 'medium', 'high', 'xhigh', 'max'],
46
+ 'gpt-6-sol': ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
47
+ 'gpt-6-luna': ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
46
48
  'gpt-5.6-sol': ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
47
49
  'gpt-5.6-terra': ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
48
50
  'gpt-5.6-luna': ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
@@ -139,7 +141,7 @@ const PROVIDER_FAMILY_BY_CLASS = {
139
141
  MixCustom: null,
140
142
  };
141
143
 
142
- /** Logical alias from `.grok420()` — resolved to reasoning / non-reasoning at request time. */
144
+ /** Logical alias key `grok-4.20-0309` — resolved to reasoning / non-reasoning at request time. */
143
145
  const GROK420_ALIAS = 'grok-4.20-0309';
144
146
  const GROK420_REASONING = 'grok-4.20-0309-reasoning';
145
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;
@@ -457,14 +455,13 @@ export declare class ModelMix {
457
455
  gpt55(args?: ModelAttachArgs): this;
458
456
  gpt55pro(args?: ModelAttachArgs): this;
459
457
  gpt6astra(args?: ModelAttachArgs): this;
458
+ gpt6sol(args?: ModelAttachArgs): this;
459
+ gpt6luna(args?: ModelAttachArgs): this;
460
460
  gpt56sol(args?: ModelAttachArgs): this;
461
461
  gpt56terra(args?: ModelAttachArgs): this;
462
462
  gpt56luna(args?: ModelAttachArgs): this;
463
463
  gptRealtime(args?: ModelAttachArgs): this;
464
464
  gptRealtimeMini(args?: ModelAttachArgs): this;
465
- gpt53codex(args?: ModelAttachArgs): this;
466
- gpt53chat(args?: ModelAttachArgs): this;
467
- gptOss(args?: ModelAttachArgs): this;
468
465
 
469
466
  // Anthropic
470
467
  fable51(args?: ModelAttachArgs): this;
@@ -478,12 +475,10 @@ export declare class ModelMix {
478
475
  opus46(args?: ModelAttachArgs): this;
479
476
  sonnet50(args?: ModelAttachArgs): this;
480
477
  sonnet5(args?: ModelAttachArgs): this;
481
- sonnet46(args?: ModelAttachArgs): this;
482
478
  sonnet45(args?: ModelAttachArgs): this;
483
479
  haiku45(args?: ModelAttachArgs): this;
484
480
 
485
481
  // Google
486
- gemini31pro(args?: ModelAttachArgs): this;
487
482
  gemini38flash(args?: ModelAttachArgs): this;
488
483
  gemini37flash(args?: ModelAttachArgs): this;
489
484
  gemini36flash(args?: ModelAttachArgs): this;
@@ -498,11 +493,7 @@ export declare class ModelMix {
498
493
  // Grok
499
494
  grok47(args?: ModelAttachArgs): this;
500
495
  grok46(args?: ModelAttachArgs): this;
501
- grok45(args?: ModelAttachArgs): this;
502
496
  grok43(args?: ModelAttachArgs): this;
503
- grok420multiAgent(args?: ModelAttachArgs): this;
504
- /** Non-reasoning by default; with `.effort(20+)` / `-1` uses the reasoning model at request time. */
505
- grok420(args?: ModelAttachArgs): this;
506
497
 
507
498
  // Multi-provider
508
499
  museGlimmer30b(args?: ModelAttachArgs): this;
@@ -522,7 +513,6 @@ export declare class ModelMix {
522
513
  kimiK26(args?: ModelAttachArgs): this;
523
514
  kimiK27Code(args?: ModelAttachArgs): this;
524
515
  kimiK3(args?: ModelAttachArgs): this;
525
- kimiK25(args?: ModelAttachArgs): this;
526
516
  lmstudio(model?: string, args?: ModelAttachArgs): this;
527
517
  minimaxM27(args?: ModelAttachArgs): this;
528
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
  }
@@ -499,6 +493,12 @@ class ModelMix {
499
493
  gpt6astra(args = {}) {
500
494
  return this._attachOpenAIWithOpenRouter('gpt-6-astra', MixOpenAIResponses, args);
501
495
  }
496
+ gpt6sol(args = {}) {
497
+ return this._attachOpenAIWithOpenRouter('gpt-6-sol', MixOpenAIResponses, args);
498
+ }
499
+ gpt6luna(args = {}) {
500
+ return this._attachOpenAIWithOpenRouter('gpt-6-luna', MixOpenAIResponses, args);
501
+ }
502
502
  gpt56sol(args = {}) {
503
503
  return this._attachOpenAIWithOpenRouter('gpt-5.6-sol', MixOpenAIResponses, args);
504
504
  }
@@ -514,25 +514,6 @@ class ModelMix {
514
514
  gptRealtimeMini({ options = {}, config = {} } = {}) {
515
515
  return this.attach('gpt-realtime-mini', new MixOpenAIWebSocket({ options, config }));
516
516
  }
517
- gpt53codex(args = {}) {
518
- return this._attachOpenAIWithOpenRouter('gpt-5.3-codex', MixOpenAIResponses, args);
519
- }
520
- gpt53chat(args = {}) {
521
- return this._attachOpenAIWithOpenRouter('gpt-5.3-chat-latest', MixOpenAIResponses, {
522
- ...args,
523
- openRouterKey: 'openai/gpt-5.3-chat'
524
- });
525
- }
526
- gptOss({ options = {}, config = {}, mix = {} } = {}) {
527
- mix = { ...this.mix, ...mix };
528
- if (mix.nvidia) this.attach('openai/gpt-oss-120b', new MixNVIDIA({ options, config }));
529
- if (mix.fireworks) this.attach('accounts/fireworks/models/gpt-oss-120b', new MixFireworks({ options, config }));
530
- if (mix.together) this.attach('openai/gpt-oss-120b', new MixTogether({ options, config }));
531
- if (mix.cerebras) this.attach('gpt-oss-120b', new MixCerebras({ options, config }));
532
- if (mix.groq) this.attach('openai/gpt-oss-120b', new MixGroq({ options, config }));
533
- if (mix.openrouter) this.attach('openai/gpt-oss-120b', new MixOpenRouter({ options, config }));
534
- return this;
535
- }
536
517
  fable50({ options = {}, config = {} } = {}) {
537
518
  return this.attach('claude-fable-5', new MixAnthropic({ options, config }));
538
519
  }
@@ -569,18 +550,12 @@ class ModelMix {
569
550
  sonnet5(args = {}) {
570
551
  return this.sonnet50(args);
571
552
  }
572
- sonnet46({ options = {}, config = {} } = {}) {
573
- return this.attach('claude-sonnet-4-6', new MixAnthropic({ options, config }));
574
- }
575
553
  sonnet45({ options = {}, config = {} } = {}) {
576
554
  return this.attach('claude-sonnet-4-5-20250929', new MixAnthropic({ options, config }));
577
555
  }
578
556
  haiku45({ options = {}, config = {} } = {}) {
579
557
  return this.attach('claude-haiku-4-5-20251001', new MixAnthropic({ options, config }));
580
558
  }
581
- gemini31pro({ options = {}, config = {} } = {}) {
582
- return this.attach('gemini-3.1-pro-preview', new MixGoogle({ options, config }));
583
- }
584
559
  gemini38flash({ options = {}, config = {} } = {}) {
585
560
  return this.attach('gemini-3.8-flash', new MixGoogle({ options, config }));
586
561
  }
@@ -612,19 +587,9 @@ class ModelMix {
612
587
  grok46({ options = {}, config = {} } = {}) {
613
588
  return this.attach('grok-4.6', new MixGrok({ options, config }));
614
589
  }
615
- grok45({ options = {}, config = {} } = {}) {
616
- return this.attach('grok-4.5', new MixGrok({ options, config }));
617
- }
618
590
  grok43({ options = {}, config = {} } = {}) {
619
591
  return this.attach('grok-4.3', new MixGrok({ options, config }));
620
592
  }
621
- grok420multiAgent({ options = {}, config = {} } = {}) {
622
- return this.attach('grok-4.20-multi-agent-0309', new MixGrok({ options, config }));
623
- }
624
- /** Non-reasoning by default; with `.effort(20+)` / `-1` resolves to the reasoning model at request time. */
625
- grok420({ options = {}, config = {} } = {}) {
626
- return this.attach('grok-4.20-0309', new MixGrok({ options, config }));
627
- }
628
593
 
629
594
  museGlimmer30b({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
630
595
  mix = { ...this.mix, ...mix };
@@ -726,14 +691,6 @@ class ModelMix {
726
691
  return this;
727
692
  }
728
693
 
729
- kimiK25({ options = {}, config = {}, mix = { together: true } } = {}) {
730
- mix = { ...this.mix, ...mix };
731
- if (mix.together) this.attach('moonshotai/Kimi-K2.5', new MixTogether({ options, config }));
732
- if (mix.fireworks) this.attach('accounts/fireworks/models/kimi-k2p5', new MixFireworks({ options, config }));
733
- if (mix.openrouter) this.attach('moonshotai/kimi-k2.5', new MixOpenRouter({ options, config }));
734
- return this;
735
- }
736
-
737
694
  lmstudio(model = 'lmstudio', { options = {}, config = {} } = {}) {
738
695
  return this.attach(model, new MixLMStudio({ options, config }));
739
696
  }
@@ -1798,7 +1755,7 @@ class ModelMix {
1798
1755
  });
1799
1756
  } else {
1800
1757
  if (!this.models || this.models.length === 0) {
1801
- throw new Error('No models specified. Use methods like .gpt5(), .sonnet46() first.');
1758
+ throw new Error('No models specified. Use methods like .gpt5mini(), .sonnet5() first.');
1802
1759
  }
1803
1760
  execution = this.limiter.schedule(() => {
1804
1761
  throwIfAborted(signal);
@@ -1,19 +1,19 @@
1
1
  const { normalizeEffort } = require('../effort');
2
2
 
3
3
  const CHAIN_MODEL_SHORTCUTS = new Set([
4
- 'gpt5', 'gpt5mini', 'gpt5nano',
5
- 'gpt51', 'gpt52', 'gpt54', 'gpt54mini', 'gpt54nano', 'gpt54pro',
6
- 'gpt6astra', 'gpt55', 'gpt55pro', 'gpt56sol', 'gpt56terra', 'gpt56luna',
7
- 'gptRealtime', 'gptRealtimeMini', 'gpt53codex', 'gpt53chat', 'gptOss',
4
+ 'gpt5mini', 'gpt5nano',
5
+ 'gpt52', 'gpt54', 'gpt54mini', 'gpt54nano', 'gpt54pro',
6
+ 'gpt6astra', 'gpt6sol', 'gpt6luna', 'gpt55', 'gpt55pro', 'gpt56sol', 'gpt56terra', 'gpt56luna',
7
+ 'gptRealtime', 'gptRealtimeMini',
8
8
  'fable51', 'fable50', 'fable5', 'opus55', 'opus50', 'opus5', 'opus48', 'opus47', 'opus46',
9
- 'sonnet50', 'sonnet5', 'sonnet46', 'sonnet45', 'haiku45',
10
- 'gemini31pro', 'gemini38flash', 'gemini37flash', 'gemini36flash', 'gemini35flash',
9
+ 'sonnet50', 'sonnet5', 'sonnet45', 'haiku45',
10
+ 'gemini38flash', 'gemini37flash', 'gemini36flash', 'gemini35flash',
11
11
  'gemini35flashLite', 'gemini31flashLite', 'sonarPro', 'sonar',
12
- 'grok47', 'grok46', 'grok45', 'grok43', 'grok420multiAgent', 'grok420',
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', 'kimiK25',
16
+ 'kimiK26', 'kimiK27Code', 'kimiK3',
17
17
  'minimaxM27', 'minimaxM3', 'mimo25', 'mimo25pro', 'mimo26pro',
18
18
  'deepseekV4Pro', 'deepseekPro', 'deepseekV4Flash', 'deepseekV41Flash', 'GLM52', 'GLM53', 'GLM53Flash'
19
19
  ]);
@@ -3,7 +3,7 @@ function normalizeOpenAIOptions(options) {
3
3
  delete options.max_tokens;
4
4
  delete options.temperature;
5
5
  }
6
- if (options.model?.includes('gpt-5') || /^(?:openai\/)?gpt-6-astra(?:-|$)/.test(options.model || '')) {
6
+ if (options.model?.includes('gpt-5') || /^(?:openai\/)?gpt-6(?:-|$)/.test(options.model || '')) {
7
7
  if (options.max_tokens) {
8
8
  options.max_completion_tokens = options.max_tokens;
9
9
  delete options.max_tokens;
@@ -11,6 +11,12 @@ const {
11
11
  validateProviderExecution
12
12
  } = require('../abort-signal');
13
13
 
14
+ /** Explicit prompt cache controls belong to the documented "GPT-5.6 and later" family. */
15
+ function isGPT56OrLater(model) {
16
+ if (typeof model !== 'string') return false;
17
+ return model.startsWith('gpt-5.6') || /^(?:openai\/)?gpt-6(?:-|$)/.test(model);
18
+ }
19
+
14
20
  function createOpenAIProviders({
15
21
  ModelMix,
16
22
  MixCustom,
@@ -38,9 +44,8 @@ function createOpenAIProviders({
38
44
  }
39
45
 
40
46
  static buildResponsesRequest(options = {}, config = {}) {
41
- const isGPT56 = typeof options.model === 'string' && options.model.startsWith('gpt-5.6');
42
47
  const input = MixOpenAIResponses.messagesToResponsesInput(options.messages, {
43
- translateNeutralCache: isGPT56
48
+ translateNeutralCache: isGPT56OrLater(options.model)
44
49
  });
45
50
  if (config.system) {
46
51
  input.unshift({ role: 'developer', content: [{ type: 'input_text', text: config.system }] });
@@ -106,7 +111,7 @@ function createOpenAIProviders({
106
111
  }
107
112
 
108
113
  static validatePromptCaching(options, input) {
109
- const isGPT56 = typeof options.model === 'string' && options.model.startsWith('gpt-5.6');
114
+ const supportsCacheControls = isGPT56OrLater(options.model);
110
115
  const cacheOptions = options.prompt_cache_options;
111
116
  const breakpoints = input.flatMap(message => Array.isArray(message.content)
112
117
  ? message.content
@@ -114,14 +119,14 @@ function createOpenAIProviders({
114
119
  .map(block => block.prompt_cache_breakpoint)
115
120
  : []);
116
121
 
117
- if (isGPT56 && options.prompt_cache_retention !== undefined) {
118
- throw new Error('GPT-5.6 does not support prompt_cache_retention; use prompt_cache_options.ttl instead.');
122
+ if (supportsCacheControls && options.prompt_cache_retention !== undefined) {
123
+ throw new Error('GPT-5.6 and later models do not support prompt_cache_retention; use prompt_cache_options.ttl instead.');
119
124
  }
120
- if (!isGPT56 && cacheOptions !== undefined) {
121
- throw new Error('prompt_cache_options is only supported by GPT-5.6 models.');
125
+ if (!supportsCacheControls && cacheOptions !== undefined) {
126
+ throw new Error('prompt_cache_options is only supported by GPT-5.6 and later models.');
122
127
  }
123
- if (!isGPT56 && breakpoints.length > 0) {
124
- throw new Error('prompt_cache_breakpoint is only supported by GPT-5.6 models.');
128
+ if (!supportsCacheControls && breakpoints.length > 0) {
129
+ throw new Error('prompt_cache_breakpoint is only supported by GPT-5.6 and later models.');
125
130
  }
126
131
  if (cacheOptions !== undefined) {
127
132
  if (!isPlainObject(cacheOptions)) {
@@ -22,9 +22,11 @@ function usesLongContextRates(pricing, inputTokens) {
22
22
  const MODEL_PRICING = {
23
23
  // OpenAI
24
24
  'gpt-6-astra': { input: 10.00, cachedInput: 1.00, cacheWrite: 12.50, output: 50.00, longContext: OPENAI_LONG_CONTEXT_PRICING },
25
+ 'gpt-6-sol': { input: 2.00, cachedInput: 0.20, cacheWrite: 2.50, output: 10.00, longContext: OPENAI_LONG_CONTEXT_PRICING },
26
+ 'gpt-6-luna': { input: 0.10, cachedInput: 0.01, cacheWrite: 0.125, output: 0.50, longContext: OPENAI_LONG_CONTEXT_PRICING },
25
27
  'gpt-realtime-mini': { input: 0.60, cachedInput: 0.06, output: 2.40 },
26
28
  'gpt-realtime': { input: 4.00, cachedInput: 0.40, output: 16.00 },
27
- 'gpt-5.6-sol': { input: 5.00, cachedInput: 0.50, cacheWrite: 6.25, output: 30.00, longContext: OPENAI_LONG_CONTEXT_PRICING },
29
+ 'gpt-5.6-sol': { input: 4.00, cachedInput: 0.40, cacheWrite: 5.00, output: 20.00, longContext: OPENAI_LONG_CONTEXT_PRICING },
28
30
  'gpt-5.6-terra': { input: 2.00, cachedInput: 0.20, cacheWrite: 2.50, output: 12.00, longContext: OPENAI_LONG_CONTEXT_PRICING },
29
31
  'gpt-5.6-luna': { input: 0.20, cachedInput: 0.02, cacheWrite: 0.25, output: 1.20, longContext: OPENAI_LONG_CONTEXT_PRICING },
30
32
  'gpt-5.5-pro': { input: 30.00, output: 180.00 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modelmix",
3
- "version": "5.2.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",