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 +22 -31
- package/demo/benchmark.js +4 -7
- 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 +3 -1
- package/index.d.ts +2 -12
- package/index.js +7 -50
- package/lib/model-chain.js +8 -8
- package/lib/providers/openai-options.js +1 -1
- package/lib/providers/openai.js +14 -9
- package/lib/token-usage.js +3 -1
- package/package.json +1 -1
- package/plugins/benchmark/test/benchmark.test.js +33 -29
- package/skills/modelmix/SKILL.md +26 -35
- package/test/abort.test.js +1 -1
- package/test/bottleneck.test.js +12 -12
- package/test/effort.test.js +9 -0
- package/test/fallback.test.js +63 -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 +63 -23
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
|
|
|
@@ -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
|
-
| `
|
|
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()` |
|
|
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.
|
|
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: `
|
|
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()`
|
|
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
|
-
|
|
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 `
|
|
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
|
|
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
|
|
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` | $
|
|
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
|
|
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
|
|
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
|
-
|
|
15
|
-
'
|
|
16
|
-
'gpt6astra@20',
|
|
14
|
+
'gpt6sol@40',
|
|
15
|
+
'gpt6luna@40',
|
|
17
16
|
'gpt56sol@40',
|
|
18
|
-
|
|
19
|
-
// 'grok46@20',
|
|
20
|
-
'deepseekV41Flash@60'
|
|
17
|
+
'gpt56luna@40'
|
|
21
18
|
];
|
|
22
19
|
|
|
23
|
-
console.log(`Running benchmark: ${models.length} models,
|
|
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" + '--------|
|
|
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
|
@@ -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
|
|
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 .
|
|
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);
|
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
|
-
'
|
|
6
|
-
'gpt6astra', 'gpt55', 'gpt55pro', 'gpt56sol', 'gpt56terra', 'gpt56luna',
|
|
7
|
-
'gptRealtime', 'gptRealtimeMini',
|
|
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', '
|
|
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
|
]);
|
|
@@ -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
|
|
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;
|
package/lib/providers/openai.js
CHANGED
|
@@ -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:
|
|
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
|
|
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 (
|
|
118
|
-
throw new Error('GPT-5.6
|
|
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 (!
|
|
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 (!
|
|
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)) {
|
package/lib/token-usage.js
CHANGED
|
@@ -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:
|
|
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 },
|