modelmix 5.1.6 → 5.1.8
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.
|
@@ -48,14 +48,14 @@ function createAnthropicProviders({ ModelMix, MixCustom, log }) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
getDefaultConfig(customConfig) {
|
|
51
|
-
|
|
52
|
-
if (!
|
|
51
|
+
const apiKey = customConfig.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
52
|
+
if (!apiKey) {
|
|
53
53
|
throw new Error('Anthropic API key not found. Please provide it in config or set ANTHROPIC_API_KEY environment variable.');
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
return super.getDefaultConfig({
|
|
57
57
|
url: 'https://api.anthropic.com/v1/messages',
|
|
58
|
-
apiKey
|
|
58
|
+
apiKey,
|
|
59
59
|
...customConfig
|
|
60
60
|
});
|
|
61
61
|
}
|
package/lib/providers/base.js
CHANGED
|
@@ -274,14 +274,14 @@ function createBaseProviders({ ModelMix }) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
getDefaultConfig(customConfig) {
|
|
277
|
-
|
|
278
|
-
if (!
|
|
277
|
+
const apiKey = customConfig.apiKey || process.env.OPENAI_API_KEY;
|
|
278
|
+
if (!apiKey) {
|
|
279
279
|
throw new Error('OpenAI API key not found. Please provide it in config or set OPENAI_API_KEY environment variable.');
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
return super.getDefaultConfig({
|
|
283
283
|
url: 'https://api.openai.com/v1/chat/completions',
|
|
284
|
-
apiKey
|
|
284
|
+
apiKey,
|
|
285
285
|
...customConfig
|
|
286
286
|
});
|
|
287
287
|
}
|
package/lib/providers/google.js
CHANGED
|
@@ -4,9 +4,10 @@ const { configForDebug } = require('../provider-debug');
|
|
|
4
4
|
function createGoogleProviders({ ModelMix, MixCustom }) {
|
|
5
5
|
class MixGoogle extends MixCustom {
|
|
6
6
|
getDefaultConfig(customConfig) {
|
|
7
|
+
const apiKey = customConfig.apiKey || process.env.GEMINI_API_KEY;
|
|
7
8
|
return super.getDefaultConfig({
|
|
8
9
|
url: 'https://generativelanguage.googleapis.com/v1beta/models',
|
|
9
|
-
apiKey
|
|
10
|
+
apiKey,
|
|
10
11
|
...customConfig
|
|
11
12
|
});
|
|
12
13
|
}
|
|
@@ -6,14 +6,14 @@ const {
|
|
|
6
6
|
function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
7
7
|
class MixMiniMax extends MixOpenAI {
|
|
8
8
|
getDefaultConfig(customConfig) {
|
|
9
|
-
|
|
10
|
-
if (!
|
|
9
|
+
const apiKey = customConfig.apiKey || process.env.MINIMAX_API_KEY;
|
|
10
|
+
if (!apiKey) {
|
|
11
11
|
throw new Error('MiniMax API key not found. Please provide it in config or set MINIMAX_API_KEY environment variable.');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
return MixCustom.prototype.getDefaultConfig.call(this, {
|
|
15
15
|
url: 'https://api.minimax.io/v1/chat/completions',
|
|
16
|
-
apiKey
|
|
16
|
+
apiKey,
|
|
17
17
|
...customConfig
|
|
18
18
|
});
|
|
19
19
|
}
|
|
@@ -29,13 +29,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
29
29
|
|
|
30
30
|
class MixMiMo extends MixOpenAI {
|
|
31
31
|
getDefaultConfig(customConfig) {
|
|
32
|
-
|
|
32
|
+
const apiKey = customConfig.apiKey || process.env.MIMO_API_KEY;
|
|
33
|
+
if (!apiKey) {
|
|
33
34
|
throw new Error('MiMo API key not found. Please provide it in config or set MIMO_API_KEY environment variable.');
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
return MixCustom.prototype.getDefaultConfig.call(this, {
|
|
37
38
|
url: 'https://api.xiaomimimo.com/v1/chat/completions',
|
|
38
|
-
apiKey
|
|
39
|
+
apiKey,
|
|
39
40
|
...customConfig
|
|
40
41
|
});
|
|
41
42
|
}
|
|
@@ -52,14 +53,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
52
53
|
|
|
53
54
|
class MixPerplexity extends MixCustom {
|
|
54
55
|
getDefaultConfig(customConfig) {
|
|
55
|
-
|
|
56
|
-
if (!
|
|
56
|
+
const apiKey = customConfig.apiKey || process.env.PPLX_API_KEY;
|
|
57
|
+
if (!apiKey) {
|
|
57
58
|
throw new Error('Perplexity API key not found. Please provide it in config or set PPLX_API_KEY environment variable.');
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
return super.getDefaultConfig({
|
|
61
62
|
url: 'https://api.perplexity.ai/chat/completions',
|
|
62
|
-
apiKey
|
|
63
|
+
apiKey,
|
|
63
64
|
...customConfig
|
|
64
65
|
});
|
|
65
66
|
}
|
|
@@ -132,14 +133,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
132
133
|
|
|
133
134
|
class MixGrok extends MixOpenAI {
|
|
134
135
|
getDefaultConfig(customConfig) {
|
|
135
|
-
|
|
136
|
-
if (!
|
|
136
|
+
const apiKey = customConfig.apiKey || process.env.XAI_API_KEY;
|
|
137
|
+
if (!apiKey) {
|
|
137
138
|
throw new Error('Grok API key not found. Please provide it in config or set XAI_API_KEY environment variable.');
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
return super.getDefaultConfig({
|
|
141
142
|
url: 'https://api.x.ai/v1/chat/completions',
|
|
142
|
-
apiKey
|
|
143
|
+
apiKey,
|
|
143
144
|
...customConfig
|
|
144
145
|
});
|
|
145
146
|
}
|
|
@@ -154,14 +155,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
154
155
|
|
|
155
156
|
class MixLambda extends MixCustom {
|
|
156
157
|
getDefaultConfig(customConfig) {
|
|
157
|
-
|
|
158
|
-
if (!
|
|
158
|
+
const apiKey = customConfig.apiKey || process.env.LAMBDA_API_KEY;
|
|
159
|
+
if (!apiKey) {
|
|
159
160
|
throw new Error('Lambda API key not found. Please provide it in config or set LAMBDA_API_KEY environment variable.');
|
|
160
161
|
}
|
|
161
162
|
|
|
162
163
|
return super.getDefaultConfig({
|
|
163
164
|
url: 'https://api.lambda.ai/v1/chat/completions',
|
|
164
|
-
apiKey
|
|
165
|
+
apiKey,
|
|
165
166
|
...customConfig
|
|
166
167
|
});
|
|
167
168
|
}
|
|
@@ -234,14 +235,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
234
235
|
|
|
235
236
|
class MixGroq extends MixCustom {
|
|
236
237
|
getDefaultConfig(customConfig) {
|
|
237
|
-
|
|
238
|
-
if (!
|
|
238
|
+
const apiKey = customConfig.apiKey || process.env.GROQ_API_KEY;
|
|
239
|
+
if (!apiKey) {
|
|
239
240
|
throw new Error('Groq API key not found. Please provide it in config or set GROQ_API_KEY environment variable.');
|
|
240
241
|
}
|
|
241
242
|
|
|
242
243
|
return super.getDefaultConfig({
|
|
243
244
|
url: 'https://api.groq.com/openai/v1/chat/completions',
|
|
244
|
-
apiKey
|
|
245
|
+
apiKey,
|
|
245
246
|
...customConfig
|
|
246
247
|
});
|
|
247
248
|
}
|
|
@@ -249,14 +250,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
249
250
|
|
|
250
251
|
class MixTogether extends MixCustom {
|
|
251
252
|
getDefaultConfig(customConfig) {
|
|
252
|
-
|
|
253
|
-
if (!
|
|
253
|
+
const apiKey = customConfig.apiKey || process.env.TOGETHER_API_KEY;
|
|
254
|
+
if (!apiKey) {
|
|
254
255
|
throw new Error('Together API key not found. Please provide it in config or set TOGETHER_API_KEY environment variable.');
|
|
255
256
|
}
|
|
256
257
|
|
|
257
258
|
return super.getDefaultConfig({
|
|
258
259
|
url: 'https://api.together.xyz/v1/chat/completions',
|
|
259
|
-
apiKey
|
|
260
|
+
apiKey,
|
|
260
261
|
...customConfig
|
|
261
262
|
});
|
|
262
263
|
}
|
|
@@ -271,14 +272,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
271
272
|
|
|
272
273
|
class MixCerebras extends MixCustom {
|
|
273
274
|
getDefaultConfig(customConfig) {
|
|
274
|
-
|
|
275
|
-
if (!
|
|
276
|
-
throw new Error('
|
|
275
|
+
const apiKey = customConfig.apiKey || process.env.CEREBRAS_API_KEY;
|
|
276
|
+
if (!apiKey) {
|
|
277
|
+
throw new Error('Cerebras API key not found. Please provide it in config or set CEREBRAS_API_KEY environment variable.');
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
return super.getDefaultConfig({
|
|
280
281
|
url: 'https://api.cerebras.ai/v1/chat/completions',
|
|
281
|
-
apiKey
|
|
282
|
+
apiKey,
|
|
282
283
|
...customConfig
|
|
283
284
|
});
|
|
284
285
|
}
|
|
@@ -291,14 +292,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
291
292
|
|
|
292
293
|
class MixFireworks extends MixCustom {
|
|
293
294
|
getDefaultConfig(customConfig) {
|
|
294
|
-
|
|
295
|
-
if (!
|
|
295
|
+
const apiKey = customConfig.apiKey || process.env.FIREWORKS_API_KEY;
|
|
296
|
+
if (!apiKey) {
|
|
296
297
|
throw new Error('Fireworks API key not found. Please provide it in config or set FIREWORKS_API_KEY environment variable.');
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
return super.getDefaultConfig({
|
|
300
301
|
url: 'https://api.fireworks.ai/inference/v1/chat/completions',
|
|
301
|
-
apiKey
|
|
302
|
+
apiKey,
|
|
302
303
|
...customConfig
|
|
303
304
|
});
|
|
304
305
|
}
|
|
@@ -306,14 +307,14 @@ function createCompatibleProviders({ MixCustom, MixOpenAI }) {
|
|
|
306
307
|
|
|
307
308
|
class MixNVIDIA extends MixCustom {
|
|
308
309
|
getDefaultConfig(customConfig) {
|
|
309
|
-
|
|
310
|
-
if (!
|
|
310
|
+
const apiKey = customConfig.apiKey || process.env.NVIDIA_API_KEY;
|
|
311
|
+
if (!apiKey) {
|
|
311
312
|
throw new Error('NVIDIA API key not found. Please provide it in config or set NVIDIA_API_KEY environment variable.');
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
return super.getDefaultConfig({
|
|
315
316
|
url: 'https://integrate.api.nvidia.com/v1/chat/completions',
|
|
316
|
-
apiKey
|
|
317
|
+
apiKey,
|
|
317
318
|
...customConfig
|
|
318
319
|
});
|
|
319
320
|
}
|
package/lib/providers/openai.js
CHANGED
|
@@ -556,14 +556,14 @@ function createOpenAIProviders({
|
|
|
556
556
|
|
|
557
557
|
class MixOpenRouter extends MixOpenAI {
|
|
558
558
|
getDefaultConfig(customConfig) {
|
|
559
|
-
|
|
560
|
-
if (!
|
|
559
|
+
const apiKey = customConfig.apiKey || process.env.OPENROUTER_API_KEY;
|
|
560
|
+
if (!apiKey) {
|
|
561
561
|
throw new Error('OpenRouter API key not found. Please provide it in config or set OPENROUTER_API_KEY environment variable.');
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
return MixCustom.prototype.getDefaultConfig.call(this, {
|
|
565
565
|
url: 'https://openrouter.ai/api/v1/chat/completions',
|
|
566
|
-
apiKey
|
|
566
|
+
apiKey,
|
|
567
567
|
...customConfig
|
|
568
568
|
});
|
|
569
569
|
}
|
|
@@ -571,13 +571,14 @@ function createOpenAIProviders({
|
|
|
571
571
|
|
|
572
572
|
class MixKimi extends MixOpenAI {
|
|
573
573
|
getDefaultConfig(customConfig) {
|
|
574
|
-
|
|
574
|
+
const apiKey = customConfig.apiKey || process.env.MOONSHOT_API_KEY;
|
|
575
|
+
if (!apiKey) {
|
|
575
576
|
throw new Error('Moonshot API key not found. Please provide it in config or set MOONSHOT_API_KEY environment variable.');
|
|
576
577
|
}
|
|
577
578
|
|
|
578
579
|
return MixCustom.prototype.getDefaultConfig.call(this, {
|
|
579
580
|
url: 'https://api.moonshot.ai/v1/chat/completions',
|
|
580
|
-
apiKey
|
|
581
|
+
apiKey,
|
|
581
582
|
...customConfig
|
|
582
583
|
});
|
|
583
584
|
}
|
package/package.json
CHANGED
package/test/public-api.test.js
CHANGED
|
@@ -48,6 +48,48 @@ describe('public module boundary', () => {
|
|
|
48
48
|
expect(model.models[0].provider.constructor).to.equal(api.MixOpenRouter);
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
const explicitApiKeyCases = [
|
|
52
|
+
['OpenAI', config => new api.MixOpenAIResponses({ config })],
|
|
53
|
+
['OpenAI moderation', config => new api.MixOpenAIModeration({ config })],
|
|
54
|
+
['Anthropic', config => new api.MixAnthropic({ config })],
|
|
55
|
+
['Gemini', config => new api.MixGoogle({ config })],
|
|
56
|
+
['MiniMax', config => new api.MixMiniMax({ config })],
|
|
57
|
+
['MiMo', config => new api.MixMiMo({ config })],
|
|
58
|
+
['Perplexity', config => new api.MixPerplexity({ config })],
|
|
59
|
+
['Grok', config => new api.MixGrok({ config })],
|
|
60
|
+
['Lambda', config => api.ModelMix.new({ mix: { openrouter: false, lambda: true } })
|
|
61
|
+
.hermes3({ config }).models[0].provider],
|
|
62
|
+
['Groq', config => new api.MixGroq({ config })],
|
|
63
|
+
['Together', config => new api.MixTogether({ config })],
|
|
64
|
+
['Cerebras', config => new api.MixCerebras({ config })],
|
|
65
|
+
['Fireworks', config => new api.MixFireworks({ config })],
|
|
66
|
+
['NVIDIA', config => new api.MixNVIDIA({ config })],
|
|
67
|
+
['OpenRouter', config => new api.MixOpenRouter({ config })],
|
|
68
|
+
['Moonshot', config => new api.MixKimi({ config })]
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
for (const [providerName, createProvider] of explicitApiKeyCases) {
|
|
72
|
+
it(`uses an explicit API key for ${providerName} without reading environment credentials`, () => {
|
|
73
|
+
const originalEnv = process.env;
|
|
74
|
+
process.env = new Proxy(originalEnv, {
|
|
75
|
+
get(target, property, receiver) {
|
|
76
|
+
if (typeof property === 'string' && property.endsWith('_API_KEY')) {
|
|
77
|
+
throw new Error(`${property} should not be read`);
|
|
78
|
+
}
|
|
79
|
+
return Reflect.get(target, property, receiver);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const provider = createProvider({ apiKey: 'explicit-key' });
|
|
85
|
+
|
|
86
|
+
expect(provider.config.apiKey).to.equal('explicit-key');
|
|
87
|
+
} finally {
|
|
88
|
+
process.env = originalEnv;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
51
93
|
it('keeps the mutable pricing catalog private', () => {
|
|
52
94
|
expect(require('../lib/token-usage')).to.not.have.property('MODEL_PRICING');
|
|
53
95
|
});
|