Skip to content

Commit 5ec88ba

Browse files
committed
Additional providers having apikey
Signed-off-by: Geoff Wilson <[email protected]>
1 parent 95fbe97 commit 5ec88ba

File tree

15 files changed

+378
-202
lines changed

15 files changed

+378
-202
lines changed

packages/types/src/constants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ export const API_KEYS = {
1515
GROQ: 'GROQ_API_KEY',
1616
CHUTES: 'CHUTES_API_KEY',
1717
LITELLM: 'LITELLM_API_KEY',
18+
CEREBRAS: 'CEREBRAS_API_KEY',
19+
DEEP_INFRA: 'DEEPINFRA_API_KEY',
20+
DOUBAO: 'DOUBAO_API_KEY',
21+
FEATHERLESS: 'FEATHERLESS_API_KEY',
22+
FIREWORKS: 'FIREWORKS_API_KEY',
23+
HUGGING_FACE: 'HUGGINGFACE_API_KEY',
24+
IO_INTELLIGENCE: 'IOINTELLIGENCE_API_KEY',
25+
MOONSHOOT: 'MOONSHOT_API_KEY',
26+
SAMBA_NOVA: 'SAMBANOVA_API_KEY',
27+
VERCEL_NOVA: 'VERCEL_API_KEY',
28+
ZAI: 'ZAI_API_KEY',
1829
} as const
1930

2031
/**

packages/types/src/provider-settings.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,19 +320,22 @@ const deepSeekSchema = apiModelIdProviderModelSchema.extend({
320320
const deepInfraSchema = apiModelIdProviderModelSchema.extend({
321321
deepInfraBaseUrl: z.string().optional(),
322322
deepInfraApiKey: z.string().optional(),
323+
deepInfraConfigUseEnvVars: z.boolean().optional(),
323324
deepInfraModelId: z.string().optional(),
324325
})
325326

326327
const doubaoSchema = apiModelIdProviderModelSchema.extend({
327328
doubaoBaseUrl: z.string().optional(),
328329
doubaoApiKey: z.string().optional(),
330+
doubaoConfigUseEnvVars: z.boolean().optional(),
329331
})
330332

331333
const moonshotSchema = apiModelIdProviderModelSchema.extend({
332334
moonshotBaseUrl: z
333335
.union([z.literal("https://api.moonshot.ai/v1"), z.literal("https://api.moonshot.cn/v1")])
334336
.optional(),
335337
moonshotApiKey: z.string().optional(),
338+
moonshotConfigUseEnvVars: z.boolean().optional(),
336339
})
337340

338341
const unboundSchema = baseProviderSettingsSchema.extend({
@@ -366,6 +369,7 @@ const groqSchema = apiModelIdProviderModelSchema.extend({
366369

367370
const huggingFaceSchema = baseProviderSettingsSchema.extend({
368371
huggingFaceApiKey: z.string().optional(),
372+
huggingFaceConfigUseEnvVars: z.boolean().optional(),
369373
huggingFaceModelId: z.string().optional(),
370374
huggingFaceInferenceProvider: z.string().optional(),
371375
})
@@ -385,10 +389,12 @@ const litellmSchema = baseProviderSettingsSchema.extend({
385389

386390
const cerebrasSchema = apiModelIdProviderModelSchema.extend({
387391
cerebrasApiKey: z.string().optional(),
392+
cerebrasConfigUseEnvVars: z.boolean().optional(),
388393
})
389394

390395
const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
391396
sambaNovaApiKey: z.string().optional(),
397+
sambaNovaConfigUseEnvVars: z.boolean().optional(),
392398
})
393399

394400
export const zaiApiLineSchema = z.enum(["international_coding", "international", "china_coding", "china"])
@@ -397,20 +403,24 @@ export type ZaiApiLine = z.infer<typeof zaiApiLineSchema>
397403

398404
const zaiSchema = apiModelIdProviderModelSchema.extend({
399405
zaiApiKey: z.string().optional(),
406+
zaiConfigUseEnvVars: z.boolean().optional(),
400407
zaiApiLine: zaiApiLineSchema.optional(),
401408
})
402409

403410
const fireworksSchema = apiModelIdProviderModelSchema.extend({
404411
fireworksApiKey: z.string().optional(),
412+
fireworksConfigUseEnvVars: z.boolean().optional(),
405413
})
406414

407415
const featherlessSchema = apiModelIdProviderModelSchema.extend({
408416
featherlessApiKey: z.string().optional(),
417+
featherlessConfigUseEnvVars: z.boolean().optional(),
409418
})
410419

411420
const ioIntelligenceSchema = apiModelIdProviderModelSchema.extend({
412421
ioIntelligenceModelId: z.string().optional(),
413422
ioIntelligenceApiKey: z.string().optional(),
423+
ioIntelligenceConfigUseEnvVars: z.boolean().optional(),
414424
})
415425

416426
const qwenCodeSchema = apiModelIdProviderModelSchema.extend({
@@ -423,6 +433,7 @@ const rooSchema = apiModelIdProviderModelSchema.extend({
423433

424434
const vercelAiGatewaySchema = baseProviderSettingsSchema.extend({
425435
vercelAiGatewayApiKey: z.string().optional(),
436+
vercelConfigUseEnvVars: z.boolean().optional(),
426437
vercelAiGatewayModelId: z.string().optional(),
427438
})
428439

src/api/__tests__/index.spec.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ vi.mock("../providers", () => ({
3131
HumanRelayHandler: vi.fn().mockImplementation(() => ({ provider: "human-relay" })),
3232
FakeAIHandler: vi.fn().mockImplementation((options) => ({ provider: "fake-ai", options })),
3333
HuggingFaceHandler: vi.fn().mockImplementation((options) => ({ provider: "huggingface", options })),
34+
CerebrasHandler: vi.fn().mockImplementation((options) => ({ provider: "cerebras", options })),
35+
SambaNovaHandler: vi.fn().mockImplementation((options) => ({ provider: "sambanova", options })),
36+
ZAiHandler: vi.fn().mockImplementation((options) => ({ provider: "zai", options })),
37+
FireworksHandler: vi.fn().mockImplementation((options) => ({ provider: "fireworks", options })),
38+
FeatherlessHandler: vi.fn().mockImplementation((options) => ({ provider: "featherless", options })),
39+
IOIntelligenceHandler: vi.fn().mockImplementation((options) => ({ provider: "io-intelligence", options })),
40+
VercelAiGatewayHandler: vi.fn().mockImplementation((options) => ({ provider: "vercel-ai-gateway", options })),
41+
DoubaoHandler: vi.fn().mockImplementation((options) => ({ provider: "doubao", options })),
42+
DeepInfraHandler: vi.fn().mockImplementation((options) => ({ provider: "deepinfra", options })),
3443
}))
3544

3645
describe("API Environment Variable Integration", () => {
@@ -331,6 +340,171 @@ describe("API Environment Variable Integration", () => {
331340
})
332341
})
333342

343+
describe("cerebras provider", () => {
344+
it("should use environment variable when cerebrasConfigUseEnvVars is true", () => {
345+
process.env.CEREBRAS_API_KEY = "env-cerebras-key"
346+
347+
const config: ProviderSettings = {
348+
apiProvider: "cerebras",
349+
cerebrasApiKey: "config-key",
350+
cerebrasConfigUseEnvVars: true,
351+
}
352+
353+
const handler = buildApiHandler(config) as any
354+
expect(handler.options.cerebrasApiKey).toBe("env-cerebras-key")
355+
})
356+
})
357+
358+
describe("sambanova provider", () => {
359+
it("should use environment variable when sambaNovaConfigUseEnvVars is true", () => {
360+
process.env.SAMBANOVA_API_KEY = "env-sambanova-key"
361+
362+
const config: ProviderSettings = {
363+
apiProvider: "sambanova",
364+
sambaNovaApiKey: "config-key",
365+
sambaNovaConfigUseEnvVars: true,
366+
}
367+
368+
const handler = buildApiHandler(config) as any
369+
expect(handler.options.sambaNovaApiKey).toBe("env-sambanova-key")
370+
})
371+
})
372+
373+
describe("zai provider", () => {
374+
it("should use environment variable when zaiConfigUseEnvVars is true", () => {
375+
process.env.ZAI_API_KEY = "env-zai-key"
376+
377+
const config: ProviderSettings = {
378+
apiProvider: "zai",
379+
zaiApiKey: "config-key",
380+
zaiConfigUseEnvVars: true,
381+
}
382+
383+
const handler = buildApiHandler(config) as any
384+
expect(handler.options.zaiApiKey).toBe("env-zai-key")
385+
})
386+
})
387+
388+
describe("fireworks provider", () => {
389+
it("should use environment variable when fireworksConfigUseEnvVars is true", () => {
390+
process.env.FIREWORKS_API_KEY = "env-fireworks-key"
391+
392+
const config: ProviderSettings = {
393+
apiProvider: "fireworks",
394+
fireworksApiKey: "config-key",
395+
fireworksConfigUseEnvVars: true,
396+
}
397+
398+
const handler = buildApiHandler(config) as any
399+
expect(handler.options.fireworksApiKey).toBe("env-fireworks-key")
400+
})
401+
})
402+
403+
describe("featherless provider", () => {
404+
it("should use environment variable when featherlessConfigUseEnvVars is true", () => {
405+
process.env.FEATHERLESS_API_KEY = "env-featherless-key"
406+
407+
const config: ProviderSettings = {
408+
apiProvider: "featherless",
409+
featherlessApiKey: "config-key",
410+
featherlessConfigUseEnvVars: true,
411+
}
412+
413+
const handler = buildApiHandler(config) as any
414+
expect(handler.options.featherlessApiKey).toBe("env-featherless-key")
415+
})
416+
})
417+
418+
describe("io-intelligence provider", () => {
419+
it("should use environment variable when ioIntelligenceConfigUseEnvVars is true", () => {
420+
process.env.IOINTELLIGENCE_API_KEY = "env-iointelligence-key"
421+
422+
const config: ProviderSettings = {
423+
apiProvider: "io-intelligence",
424+
ioIntelligenceApiKey: "config-key",
425+
ioIntelligenceConfigUseEnvVars: true,
426+
}
427+
428+
const handler = buildApiHandler(config) as any
429+
expect(handler.options.ioIntelligenceApiKey).toBe("env-iointelligence-key")
430+
})
431+
})
432+
433+
describe("vercel-ai-gateway provider", () => {
434+
it("should use environment variable when vercelConfigUseEnvVars is true", () => {
435+
process.env.VERCEL_API_KEY = "env-vercel-key"
436+
437+
const config: ProviderSettings = {
438+
apiProvider: "vercel-ai-gateway",
439+
vercelAiGatewayApiKey: "config-key",
440+
vercelConfigUseEnvVars: true,
441+
}
442+
443+
const handler = buildApiHandler(config) as any
444+
expect(handler.options.vercelAiGatewayApiKey).toBe("env-vercel-key")
445+
})
446+
})
447+
448+
describe("doubao provider", () => {
449+
it("should use environment variable when doubaoConfigUseEnvVars is true", () => {
450+
process.env.DOUBAO_API_KEY = "env-doubao-key"
451+
452+
const config: ProviderSettings = {
453+
apiProvider: "doubao",
454+
doubaoApiKey: "config-key",
455+
doubaoConfigUseEnvVars: true,
456+
}
457+
458+
const handler = buildApiHandler(config) as any
459+
expect(handler.options.doubaoApiKey).toBe("env-doubao-key")
460+
})
461+
})
462+
463+
describe("moonshot provider", () => {
464+
it("should use environment variable when moonshotConfigUseEnvVars is true", () => {
465+
process.env.MOONSHOT_API_KEY = "env-moonshot-key"
466+
467+
const config: ProviderSettings = {
468+
apiProvider: "moonshot",
469+
moonshotApiKey: "config-key",
470+
moonshotConfigUseEnvVars: true,
471+
}
472+
473+
const handler = buildApiHandler(config) as any
474+
expect(handler.options.moonshotApiKey).toBe("env-moonshot-key")
475+
})
476+
})
477+
478+
describe("huggingface provider", () => {
479+
it("should use environment variable when huggingFaceConfigUseEnvVars is true", () => {
480+
process.env.HUGGINGFACE_API_KEY = "env-huggingface-key"
481+
482+
const config: ProviderSettings = {
483+
apiProvider: "huggingface",
484+
huggingFaceApiKey: "config-key",
485+
huggingFaceConfigUseEnvVars: true,
486+
}
487+
488+
const handler = buildApiHandler(config) as any
489+
expect(handler.options.huggingFaceApiKey).toBe("env-huggingface-key")
490+
})
491+
})
492+
493+
describe("deepinfra provider", () => {
494+
it("should use environment variable when deepInfraConfigUseEnvVars is true", () => {
495+
process.env.DEEPINFRA_API_KEY = "env-deepinfra-key"
496+
497+
const config: ProviderSettings = {
498+
apiProvider: "deepinfra",
499+
deepInfraApiKey: "config-key",
500+
deepInfraConfigUseEnvVars: true,
501+
}
502+
503+
const handler = buildApiHandler(config) as any
504+
expect(handler.options.deepInfraApiKey).toBe("env-deepinfra-key")
505+
})
506+
})
507+
334508
describe("providers without environment variable support", () => {
335509
it("should not modify options for claude-code provider", () => {
336510
const config: ProviderSettings = {
@@ -382,6 +556,17 @@ describe("API Environment Variable Integration", () => {
382556
"GROQ_API_KEY",
383557
"CHUTES_API_KEY",
384558
"LITELLM_API_KEY",
559+
"CEREBRAS_API_KEY",
560+
"SAMBANOVA_API_KEY",
561+
"ZAI_API_KEY",
562+
"FIREWORKS_API_KEY",
563+
"FEATHERLESS_API_KEY",
564+
"IOINTELLIGENCE_API_KEY",
565+
"VERCEL_API_KEY",
566+
"DOUBAO_API_KEY",
567+
"MOONSHOT_API_KEY",
568+
"HUGGINGFACE_API_KEY",
569+
"DEEPINFRA_API_KEY",
385570
]
386571

387572
envVars.forEach((envVar, index) => {

src/api/index.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,16 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
153153
}
154154
return new DeepSeekHandler(options)
155155
case "doubao":
156+
if (options.doubaoConfigUseEnvVars) {
157+
options.doubaoApiKey = getEnvVar("DOUBAO_API_KEY", options.doubaoApiKey)
158+
}
156159
return new DoubaoHandler(options)
157160
case "qwen-code":
158161
return new QwenCodeHandler(options)
159162
case "moonshot":
163+
if (options.moonshotConfigUseEnvVars) {
164+
options.moonshotApiKey = getEnvVar("MOONSHOT_API_KEY", options.moonshotApiKey)
165+
}
160166
return new MoonshotHandler(options)
161167
case "vscode-lm":
162168
return new VsCodeLmHandler(options)
@@ -190,8 +196,14 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
190196
}
191197
return new GroqHandler(options)
192198
case "deepinfra":
199+
if (options.deepInfraConfigUseEnvVars) {
200+
options.deepInfraApiKey = getEnvVar("DEEPINFRA_API_KEY", options.deepInfraApiKey)
201+
}
193202
return new DeepInfraHandler(options)
194203
case "huggingface":
204+
if (options.huggingFaceConfigUseEnvVars) {
205+
options.huggingFaceApiKey = getEnvVar("HUGGINGFACE_API_KEY", options.huggingFaceApiKey)
206+
}
195207
return new HuggingFaceHandler(options)
196208
case "chutes":
197209
if (options.chutesConfigUseEnvVars) {
@@ -204,22 +216,43 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
204216
}
205217
return new LiteLLMHandler(options)
206218
case "cerebras":
219+
if (options.cerebrasConfigUseEnvVars) {
220+
options.cerebrasApiKey = getEnvVar("CEREBRAS_API_KEY", options.cerebrasApiKey)
221+
}
207222
return new CerebrasHandler(options)
208223
case "sambanova":
224+
if (options.sambaNovaConfigUseEnvVars) {
225+
options.sambaNovaApiKey = getEnvVar("SAMBANOVA_API_KEY", options.sambaNovaApiKey)
226+
}
209227
return new SambaNovaHandler(options)
210228
case "zai":
229+
if (options.zaiConfigUseEnvVars) {
230+
options.zaiApiKey = getEnvVar("ZAI_API_KEY", options.zaiApiKey)
231+
}
211232
return new ZAiHandler(options)
212233
case "fireworks":
234+
if (options.fireworksConfigUseEnvVars) {
235+
options.fireworksApiKey = getEnvVar("FIREWORKS_API_KEY", options.fireworksApiKey)
236+
}
213237
return new FireworksHandler(options)
214238
case "io-intelligence":
239+
if (options.ioIntelligenceConfigUseEnvVars) {
240+
options.ioIntelligenceApiKey = getEnvVar("IOINTELLIGENCE_API_KEY", options.ioIntelligenceApiKey)
241+
}
215242
return new IOIntelligenceHandler(options)
216243
case "roo":
217244
// Never throw exceptions from provider constructors
218245
// The provider-proxy server will handle authentication and return appropriate error codes
219246
return new RooHandler(options)
220247
case "featherless":
248+
if (options.featherlessConfigUseEnvVars) {
249+
options.featherlessApiKey = getEnvVar("FEATHERLESS_API_KEY", options.featherlessApiKey)
250+
}
221251
return new FeatherlessHandler(options)
222252
case "vercel-ai-gateway":
253+
if (options.vercelConfigUseEnvVars) {
254+
options.vercelAiGatewayApiKey = getEnvVar("VERCEL_API_KEY", options.vercelAiGatewayApiKey)
255+
}
223256
return new VercelAiGatewayHandler(options)
224257
default:
225258
apiProvider satisfies "gemini-cli" | undefined

0 commit comments

Comments
 (0)