modelmix 4.5.28 → 4.6.0

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
@@ -136,6 +136,9 @@ Here's a comprehensive list of available methods:
136
136
 
137
137
  | Method | Provider | Model | Price (I/O) per 1 M tokens |
138
138
  | ------------------- | ---------- | ---------------------------- | -------------------------- |
139
+ | `gpt56sol()` | OpenAI | gpt-5.6-sol | [\$5.00 / \$30.00][1] |
140
+ | `gpt56terra()` | OpenAI | gpt-5.6-terra | [\$2.50 / \$15.00][1] |
141
+ | `gpt56luna()` | OpenAI | gpt-5.6-luna | [\$1.00 / \$6.00][1] |
139
142
  | `gpt55()` | OpenAI | gpt-5.5 | [\$5.00 / \$30.00][1] |
140
143
  | `gpt54()` | OpenAI | gpt-5.4 | [\$2.50 / \$15.00][1] |
141
144
  | `gpt54mini()` | OpenAI | gpt-5.4-mini | [\$0.75 / \$4.50][1] |
@@ -149,6 +152,7 @@ Here's a comprehensive list of available methods:
149
152
  | `gpt41mini()` | OpenAI | gpt-4.1-mini | [\$0.40 / \$1.60][1] |
150
153
  | `gpt41nano()` | OpenAI | gpt-4.1-nano | [\$0.10 / \$0.40][1] |
151
154
  | `gptOss()` | Together | gpt-oss-120B | [\$0.15 / \$0.60][7] |
155
+ | `fable5[think]()` | Anthropic | claude-fable-5 | [\$10.00 / \$50.00][2] |
152
156
  | `opus48[think]()` | Anthropic | claude-opus-4-8 | [\$5.00 / \$25.00][2] |
153
157
  | `opus47[think]()` | Anthropic | claude-opus-4-7 | [\$5.00 / \$25.00][2] |
154
158
  | `opus46[think]()` | Anthropic | claude-opus-4-6 | [\$5.00 / \$25.00][2] |
package/index.js CHANGED
@@ -37,6 +37,9 @@ const MODEL_PRICING = {
37
37
  // OpenAI
38
38
  'gpt-realtime-mini': [0.60, 2.40],
39
39
  'gpt-realtime': [4.00, 16.00],
40
+ 'gpt-5.6-sol': [5.00, 30.00],
41
+ 'gpt-5.6-terra': [2.50, 15.00],
42
+ 'gpt-5.6-luna': [1.00, 6.00],
40
43
  'gpt-5.5-pro': [30.00, 180.00],
41
44
  'gpt-5.5': [5.00, 30.00],
42
45
  'gpt-5.4': [2.50, 15.00],
@@ -58,6 +61,7 @@ const MODEL_PRICING = {
58
61
  'gpt-oss-120b': [0.15, 0.60],
59
62
  'openai/gpt-oss-120b:free': [0, 0],
60
63
  // Anthropic
64
+ 'claude-fable-5': [10.00, 50.00],
61
65
  'claude-sonnet-5': [3.00, 15.00],
62
66
  'claude-opus-4-8': [5.00, 25.00],
63
67
  'claude-opus-4-7': [5.00, 25.00],
@@ -72,6 +76,7 @@ const MODEL_PRICING = {
72
76
  'gemini-3.1-pro-preview':[2.00, 12.00],
73
77
  'gemini-3-pro-preview': [2.00, 12.00],
74
78
  'gemini-3-flash-preview': [0.50, 3.00],
79
+ 'gemini-3.5-flash': [0.75, 4.50],
75
80
  'gemini-2.5-pro': [1.25, 10.00],
76
81
  'gemini-2.5-flash': [0.30, 2.50],
77
82
  'gemini-3.1-flash-lite-preview': [0.25, 1.50],
@@ -325,6 +330,15 @@ class ModelMix {
325
330
  gpt55pro({ options = {}, config = {} } = {}) {
326
331
  return this.attach('gpt-5.5-pro', new MixOpenAIResponses({ options, config }));
327
332
  }
333
+ gpt56sol({ options = {}, config = {} } = {}) {
334
+ return this.attach('gpt-5.6-sol', new MixOpenAIResponses({ options, config }));
335
+ }
336
+ gpt56terra({ options = {}, config = {} } = {}) {
337
+ return this.attach('gpt-5.6-terra', new MixOpenAIResponses({ options, config }));
338
+ }
339
+ gpt56luna({ options = {}, config = {} } = {}) {
340
+ return this.attach('gpt-5.6-luna', new MixOpenAIResponses({ options, config }));
341
+ }
328
342
  gptRealtime({ options = {}, config = {} } = {}) {
329
343
  return this.attach('gpt-realtime', new MixOpenAIWebSocket({ options, config }));
330
344
  }
@@ -345,6 +359,13 @@ class ModelMix {
345
359
  if (mix.openrouter) this.attach('openai/gpt-oss-120b:free', new MixOpenRouter({ options, config }));
346
360
  return this;
347
361
  }
362
+ fable5({ options = {}, config = {} } = {}) {
363
+ return this.attach('claude-fable-5', new MixAnthropic({ options, config }));
364
+ }
365
+ fable5think({ options = {}, config = {} } = {}) {
366
+ options = { ...MixAnthropic.fableThinkingOptions, ...options };
367
+ return this.attach('claude-fable-5', new MixAnthropic({ options, config }));
368
+ }
348
369
  opus48think({ options = {}, config = {} } = {}) {
349
370
  options = { ...MixAnthropic.thinkingOptions, ...options };
350
371
  return this.attach('claude-opus-4-8', new MixAnthropic({ options, config }));
@@ -2091,6 +2112,12 @@ class MixAnthropic extends MixCustom {
2091
2112
  temperature: 1
2092
2113
  };
2093
2114
 
2115
+ static fableThinkingOptions = {
2116
+ output_config: { effort: 'max' },
2117
+ thinking: { display: 'summarized' },
2118
+ temperature: 1
2119
+ };
2120
+
2094
2121
  getDefaultConfig(customConfig) {
2095
2122
 
2096
2123
  if (!process.env.ANTHROPIC_API_KEY) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modelmix",
3
- "version": "4.5.28",
3
+ "version": "4.6.0",
4
4
  "description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -22,9 +22,9 @@
22
22
  "llama",
23
23
  "fallback",
24
24
  "kimi",
25
- "chat",
25
+ "mythos",
26
26
  "gpt5",
27
- "opus",
27
+ "fable",
28
28
  "sonnet",
29
29
  "openrouter",
30
30
  "gemini",
@@ -96,9 +96,9 @@ If `sonnet46` fails, it automatically tries `gpt52`, then `gemini3flash`.
96
96
  `gpt52()` `gpt52chat()` `gpt51()` `gpt5()` `gpt5mini()` `gpt5nano()` `gpt45()` `gpt41()` `gpt41mini()` `gpt41nano()` `o3()` `o4mini()`
97
97
 
98
98
  ### Anthropic
99
- `opus48()` `opus47()` `opus46()` `opus41()` `sonnet5()` `sonnet46()` `sonnet45()` `sonnet4()` `haiku45()` `haiku35()`
99
+ `fable5()` `opus48()` `opus47()` `opus46()` `opus41()` `sonnet5()` `sonnet46()` `sonnet45()` `sonnet4()` `haiku45()` `haiku35()`
100
100
 
101
- Thinking variants: append `think` — e.g. `opus48think()` `opus47think()` `opus46think()` `sonnet5think()` `sonnet46think()` `sonnet45think()` `sonnet4think()` `opus41think()` `haiku45think()`
101
+ Thinking variants: append `think` — e.g. `fable5think()` `opus48think()` `opus47think()` `opus46think()` `sonnet5think()` `sonnet46think()` `sonnet45think()` `sonnet4think()` `opus41think()` `haiku45think()`
102
102
 
103
103
  ### Google
104
104
  `gemini3pro()` `gemini3flash()` `gemini35flash()` `gemini25pro()` `gemini25flash()`
@@ -2,6 +2,25 @@ const { expect } = require('chai');
2
2
  const { ModelMix, MixAnthropic } = require('../index.js');
3
3
 
4
4
  describe('Anthropic Model Registration Tests', () => {
5
+ it('should register Claude Fable 5', () => {
6
+ const model = ModelMix.new();
7
+ model.fable5();
8
+
9
+ expect(model.models).to.have.length(1);
10
+ expect(model.models[0].key).to.equal('claude-fable-5');
11
+ expect(model.models[0].provider).to.be.instanceOf(MixAnthropic);
12
+ });
13
+
14
+ it('should register Claude Fable 5 with max effort thinking', () => {
15
+ const model = ModelMix.new();
16
+ model.fable5think();
17
+
18
+ expect(model.models).to.have.length(1);
19
+ expect(model.models[0].key).to.equal('claude-fable-5');
20
+ expect(model.models[0].provider.options.output_config).to.deep.equal({ effort: 'max' });
21
+ expect(model.models[0].provider.options.thinking).to.deep.equal({ display: 'summarized' });
22
+ });
23
+
5
24
  it('should register Claude Opus 4.8', () => {
6
25
  const model = ModelMix.new();
7
26
  model.opus48();
@@ -88,6 +88,23 @@ describe('Token Usage Tracking', () => {
88
88
  expect(model.models[1].provider).to.be.instanceOf(MixOpenAIResponses);
89
89
  });
90
90
 
91
+ it('should register GPT-5.6 shortcuts with OpenAI Responses provider', function () {
92
+ const model = ModelMix.new()
93
+ .gpt56sol()
94
+ .gpt56terra()
95
+ .gpt56luna();
96
+
97
+ expect(model.models.map(({ key }) => key)).to.deep.equal([
98
+ 'gpt-5.6-sol',
99
+ 'gpt-5.6-terra',
100
+ 'gpt-5.6-luna'
101
+ ]);
102
+ expect(model.models.every(({ provider }) => provider instanceof MixOpenAIResponses)).to.equal(true);
103
+ expect(ModelMix.calculateCost('gpt-5.6-sol', { input: 1_000_000, output: 1_000_000 })).to.equal(35);
104
+ expect(ModelMix.calculateCost('gpt-5.6-terra', { input: 1_000_000, output: 1_000_000 })).to.equal(17.5);
105
+ expect(ModelMix.calculateCost('gpt-5.6-luna', { input: 1_000_000, output: 1_000_000 })).to.equal(7);
106
+ });
107
+
91
108
  it('should register Gemini 3.5 Flash shortcut with Google provider', function () {
92
109
  const model = ModelMix.new()
93
110
  .gemini35flash();
@@ -95,6 +112,7 @@ describe('Token Usage Tracking', () => {
95
112
  expect(model.models).to.have.length(1);
96
113
  expect(model.models[0].key).to.equal('gemini-3.5-flash');
97
114
  expect(model.models[0].provider).to.be.instanceOf(MixGoogle);
115
+ expect(ModelMix.calculateCost('gemini-3.5-flash', { input: 1_000_000, output: 1_000_000 })).to.equal(5.25);
98
116
  });
99
117
 
100
118
  it('should register MiMo shortcuts with native and OpenRouter providers', function () {