@@ -3,6 +3,7 @@ import type OpenAI from 'openai'
33import type { ChatCompletionChunk } from 'openai/resources/chat/completions'
44import type { CompletionUsage } from 'openai/resources/completions'
55import { env } from '@/lib/core/config/env'
6+ import { isHosted } from '@/lib/core/config/feature-flags'
67import {
78 buildCanonicalIndex ,
89 type CanonicalGroup ,
@@ -37,6 +38,7 @@ import {
3738 updateOllamaModels as updateOllamaModelsInDefinitions ,
3839} from '@/providers/models'
3940import type { ProviderId , ProviderToolConfig } from '@/providers/types'
41+ import { useProvidersStore } from '@/stores/providers/store'
4042import { mergeToolParameters } from '@/tools/params'
4143
4244const logger = createLogger ( 'ProviderUtils' )
@@ -715,6 +717,60 @@ export function shouldBillModelUsage(model: string): boolean {
715717 return hostedModels . some ( ( hostedModel ) => model . toLowerCase ( ) === hostedModel . toLowerCase ( ) )
716718}
717719
720+ /**
721+ * Get an API key for a specific provider, handling rotation and fallbacks
722+ * For use server-side only
723+ */
724+ export function getApiKey ( provider : string , model : string , userProvidedKey ?: string ) : string {
725+ const hasUserKey = ! ! userProvidedKey
726+
727+ const isOllamaModel =
728+ provider === 'ollama' || useProvidersStore . getState ( ) . providers . ollama . models . includes ( model )
729+ if ( isOllamaModel ) {
730+ return 'empty'
731+ }
732+
733+ const isVllmModel =
734+ provider === 'vllm' || useProvidersStore . getState ( ) . providers . vllm . models . includes ( model )
735+ if ( isVllmModel ) {
736+ return userProvidedKey || 'empty'
737+ }
738+
739+ const isBedrockModel = provider === 'bedrock' || model . startsWith ( 'bedrock/' )
740+ if ( isBedrockModel ) {
741+ return 'bedrock-uses-own-credentials'
742+ }
743+
744+ const isOpenAIModel = provider === 'openai'
745+ const isClaudeModel = provider === 'anthropic'
746+ const isGeminiModel = provider === 'google'
747+
748+ if ( isHosted && ( isOpenAIModel || isClaudeModel || isGeminiModel ) ) {
749+ const hostedModels = getHostedModels ( )
750+ const isModelHosted = hostedModels . some ( ( m ) => m . toLowerCase ( ) === model . toLowerCase ( ) )
751+
752+ if ( isModelHosted ) {
753+ try {
754+ const { getRotatingApiKey } = require ( '@/lib/core/config/api-keys' )
755+ const serverKey = getRotatingApiKey ( isGeminiModel ? 'gemini' : provider )
756+ return serverKey
757+ } catch ( _error ) {
758+ if ( hasUserKey ) {
759+ return userProvidedKey !
760+ }
761+
762+ throw new Error ( `No API key available for ${ provider } ${ model } ` )
763+ }
764+ }
765+ }
766+
767+ if ( ! hasUserKey ) {
768+ throw new Error ( `API key is required for ${ provider } ${ model } ` )
769+ }
770+
771+ return userProvidedKey !
772+ }
773+
718774/**
719775 * Prepares tool configuration for provider requests with consistent tool usage control behavior
720776 *
0 commit comments