@@ -7,7 +7,7 @@ import NodeCache from "node-cache"
77import { z } from "zod"
88
99import type { ProviderName , ModelRecord } from "@roo-code/types"
10- import { modelInfoSchema , TelemetryEventName } from "@roo-code/types"
10+ import { modelInfoSchema , providerIdentifiers , TelemetryEventName } from "@roo-code/types"
1111import { TelemetryService } from "@roo-code/telemetry"
1212
1313import { safeWriteJson } from "../../../utils/safeWriteJson"
@@ -43,37 +43,32 @@ const modelRecordSchema = z.record(z.string(), modelInfoSchema)
4343// deduplicate each other's in-flight refreshes.
4444const inFlightRefresh = new Map < string , Promise < ModelRecord > > ( )
4545
46- // Providers whose model lists are scoped to the signed-in user (e.g. per-account
47- // allowlists or org policies). For these we MUST NOT cache results on disk or
48- // in memory: a sign-in/out cycle could otherwise serve a previous user's model
49- // list to the next user, and stale data could mask backend allowlist updates.
50- const AUTH_SCOPED_PROVIDERS : ReadonlySet < RouterName > = new Set ( [ "zoo-gateway" , "kimi-code" ] )
51-
5246// Providers whose model list is determined by the server URL, not just by the provider name.
5347// Each unique baseUrl must be cached independently so that switching endpoints never serves
5448// stale results from a previously-cached server.
5549const URL_SCOPED_PROVIDERS : ReadonlySet < RouterName > = new Set ( [
56- " litellm" ,
57- " poe" ,
58- " deepseek" ,
59- " moonshot" ,
60- " ollama" ,
61- " lmstudio" ,
62- " requesty" ,
50+ providerIdentifiers . litellm ,
51+ providerIdentifiers . poe ,
52+ providerIdentifiers . deepseek ,
53+ providerIdentifiers . moonshot ,
54+ providerIdentifiers . ollama ,
55+ providerIdentifiers . lmstudio ,
56+ providerIdentifiers . requesty ,
6357] )
6458
6559// Providers where the API key itself determines which models are visible (e.g. per-key
6660// allowlists). For these the cache key also includes a short hash of
6761// the API key so that two different keys on the same server never share a cache entry.
6862const KEY_SCOPED_PROVIDERS : ReadonlySet < RouterName > = new Set ( [
69- " litellm" , // Per-key model allowlists are a first-class LiteLLM proxy feature
70- " poe" , // Per-account model availability
71- " requesty" , // Per-account custom model policies
72- " moonshot" , // Per-key model visibility (api.moonshot.ai vs api.moonshot.cn)
63+ providerIdentifiers . litellm , // Per-key model allowlists are a first-class LiteLLM proxy feature
64+ providerIdentifiers . poe , // Per-account model availability
65+ providerIdentifiers . requesty , // Per-account custom model policies
66+ providerIdentifiers . moonshot , // Per-key model visibility (api.moonshot.ai vs api.moonshot.cn)
7367] )
7468
7569function isAuthScopedProvider ( provider : RouterName ) : boolean {
76- return AUTH_SCOPED_PROVIDERS . has ( provider )
70+ // Signed-in model lists must never cross users through memory, disk, or in-flight caching.
71+ return provider === providerIdentifiers . zooGateway || provider === providerIdentifiers . kimiCode
7772}
7873
7974// Memoize derived digests so the deliberately-structureless KDF runs at most once per
@@ -191,47 +186,47 @@ async function fetchModelsFromProvider(options: GetModelsOptions): Promise<Model
191186 let models : ModelRecord
192187
193188 switch ( provider ) {
194- case " openrouter" :
189+ case providerIdentifiers . openrouter :
195190 models = await getOpenRouterModels ( )
196191 break
197- case " requesty" :
192+ case providerIdentifiers . requesty :
198193 // Requesty models endpoint requires an API key for per-user custom policies.
199194 models = await getRequestyModels ( options . baseUrl , options . apiKey )
200195 break
201- case " unbound" :
196+ case providerIdentifiers . unbound :
202197 models = await getUnboundModels ( options . apiKey )
203198 break
204- case " litellm" :
199+ case providerIdentifiers . litellm :
205200 models = await getLiteLLMModels ( options . apiKey ?? "" , options . baseUrl )
206201 break
207- case " ollama" :
202+ case providerIdentifiers . ollama :
208203 models = await getOllamaModels ( options . baseUrl , options . apiKey )
209204 break
210- case " lmstudio" :
205+ case providerIdentifiers . lmstudio :
211206 models = await getLMStudioModels ( options . baseUrl )
212207 break
213- case "vercel-ai-gateway" :
208+ case providerIdentifiers . vercelAiGateway :
214209 models = await getVercelAiGatewayModels ( )
215210 break
216- case "opencode-go" :
211+ case providerIdentifiers . opencodeGo :
217212 models = await getOpencodeGoModels ( options . apiKey )
218213 break
219- case " kenari" :
214+ case providerIdentifiers . kenari :
220215 models = await getKenariModels ( options . apiKey )
221216 break
222- case " poe" :
217+ case providerIdentifiers . poe :
223218 models = await getPoeModels ( options . apiKey , options . baseUrl )
224219 break
225- case " deepseek" :
220+ case providerIdentifiers . deepseek :
226221 models = await getDeepSeekModels ( options . baseUrl , options . apiKey )
227222 break
228- case " moonshot" :
223+ case providerIdentifiers . moonshot :
229224 models = await getMoonshotModels ( options . baseUrl , options . apiKey )
230225 break
231- case "zoo-gateway" :
226+ case providerIdentifiers . zooGateway :
232227 models = await getZooGatewayModels ( { zooSessionToken : options . apiKey , zooGatewayBaseUrl : options . baseUrl } )
233228 break
234- case "kimi-code" :
229+ case providerIdentifiers . kimiCode :
235230 models = await getKimiCodeModels ( options . apiKey )
236231 break
237232 default : {
@@ -399,8 +394,14 @@ export async function initializeModelCacheRefresh(): Promise<void> {
399394 setTimeout ( async ( ) => {
400395 // Providers that work without API keys
401396 const publicProviders : Array < { provider : RouterName ; options : GetModelsOptions } > = [
402- { provider : "openrouter" , options : { provider : "openrouter" } } ,
403- { provider : "vercel-ai-gateway" , options : { provider : "vercel-ai-gateway" } } ,
397+ {
398+ provider : providerIdentifiers . openrouter ,
399+ options : { provider : providerIdentifiers . openrouter } ,
400+ } ,
401+ {
402+ provider : providerIdentifiers . vercelAiGateway ,
403+ options : { provider : providerIdentifiers . vercelAiGateway } ,
404+ } ,
404405 ]
405406
406407 // Refresh each provider in background (fire and forget)
0 commit comments