Skip to content

Commit b7fcc39

Browse files
committed
Try to clean up some dynamic model stuff
1 parent f332589 commit b7fcc39

File tree

15 files changed

+224
-275
lines changed

15 files changed

+224
-275
lines changed

packages/types/src/provider-settings.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,44 @@ export const providerNamesSchema = z.enum(providerNames)
8080

8181
export type ProviderName = z.infer<typeof providerNamesSchema>
8282

83+
export const isProviderName = (key: unknown): key is ProviderName =>
84+
typeof key === "string" && providerNames.includes(key as ProviderName)
85+
8386
/**
8487
* DynamicProvider
8588
*
8689
* Dynamic provider requires external API calls in order to get the model list.
8790
*/
8891

8992
export const dynamicProviders = [
90-
"glama",
93+
"openrouter",
94+
"vercel-ai-gateway",
9195
"huggingface",
9296
"litellm",
93-
"openrouter",
97+
"deepinfra",
98+
"io-intelligence",
9499
"requesty",
95100
"unbound",
96-
"deepinfra",
97-
"vercel-ai-gateway",
101+
"glama",
98102
] as const satisfies readonly ProviderName[]
99103

100104
export type DynamicProvider = (typeof dynamicProviders)[number]
101105

102106
export const isDynamicProvider = (key: string): key is DynamicProvider =>
103107
dynamicProviders.includes(key as DynamicProvider)
104108

109+
/**
110+
* LocalProvider
111+
*
112+
* Local providers require localhost API calls in order to get the model list.
113+
*/
114+
115+
export const localProviders = ["ollama", "lmstudio"] as const satisfies readonly ProviderName[]
116+
117+
export type LocalProvider = (typeof localProviders)[number]
118+
119+
export const isLocalProvider = (key: string): key is LocalProvider => localProviders.includes(key as LocalProvider)
120+
105121
/**
106122
* FauxProvider
107123
*

src/api/providers/fetchers/huggingface.ts

Lines changed: 22 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import axios from "axios"
22
import { z } from "zod"
3-
import type { ModelInfo } from "@roo-code/types"
3+
44
import {
5+
type ModelInfo,
56
HUGGINGFACE_API_URL,
67
HUGGINGFACE_CACHE_DURATION,
78
HUGGINGFACE_DEFAULT_MAX_TOKENS,
89
HUGGINGFACE_DEFAULT_CONTEXT_WINDOW,
910
} from "@roo-code/types"
11+
1012
import type { ModelRecord } from "../../../shared/api"
1113

12-
/**
13-
* HuggingFace Provider Schema
14-
*/
1514
const huggingFaceProviderSchema = z.object({
1615
provider: z.string(),
1716
status: z.enum(["live", "staging", "error"]),
@@ -27,7 +26,8 @@ const huggingFaceProviderSchema = z.object({
2726
})
2827

2928
/**
30-
* Represents a provider that can serve a HuggingFace model
29+
* Represents a provider that can serve a HuggingFace model.
30+
*
3131
* @property provider - The provider identifier (e.g., "sambanova", "together")
3232
* @property status - The current status of the provider
3333
* @property supports_tools - Whether the provider supports tool/function calling
@@ -37,9 +37,6 @@ const huggingFaceProviderSchema = z.object({
3737
*/
3838
export type HuggingFaceProvider = z.infer<typeof huggingFaceProviderSchema>
3939

40-
/**
41-
* HuggingFace Model Schema
42-
*/
4340
const huggingFaceModelSchema = z.object({
4441
id: z.string(),
4542
object: z.literal("model"),
@@ -50,6 +47,7 @@ const huggingFaceModelSchema = z.object({
5047

5148
/**
5249
* Represents a HuggingFace model available through the router API
50+
*
5351
* @property id - The unique identifier of the model
5452
* @property object - The object type (always "model")
5553
* @property created - Unix timestamp of when the model was created
@@ -58,26 +56,13 @@ const huggingFaceModelSchema = z.object({
5856
*/
5957
export type HuggingFaceModel = z.infer<typeof huggingFaceModelSchema>
6058

61-
/**
62-
* HuggingFace API Response Schema
63-
*/
6459
const huggingFaceApiResponseSchema = z.object({
6560
object: z.string(),
6661
data: z.array(huggingFaceModelSchema),
6762
})
6863

69-
/**
70-
* Represents the response from the HuggingFace router API
71-
* @property object - The response object type
72-
* @property data - Array of available models
73-
*/
7464
type HuggingFaceApiResponse = z.infer<typeof huggingFaceApiResponseSchema>
7565

76-
/**
77-
* Cache entry for storing fetched models
78-
* @property data - The cached model records
79-
* @property timestamp - Unix timestamp of when the cache was last updated
80-
*/
8166
interface CacheEntry {
8267
data: ModelRecord
8368
rawModels?: HuggingFaceModel[]
@@ -87,27 +72,28 @@ interface CacheEntry {
8772
let cache: CacheEntry | null = null
8873

8974
/**
90-
* Parse a HuggingFace model into ModelInfo format
75+
* Parse a HuggingFace model into ModelInfo format.
76+
*
9177
* @param model - The HuggingFace model to parse
9278
* @param provider - Optional specific provider to use for capabilities
9379
* @returns ModelInfo object compatible with the application's model system
9480
*/
9581
function parseHuggingFaceModel(model: HuggingFaceModel, provider?: HuggingFaceProvider): ModelInfo {
96-
// Use provider-specific values if available, otherwise find first provider with values
82+
// Use provider-specific values if available, otherwise find first provider with values.
9783
const contextLength =
9884
provider?.context_length ||
9985
model.providers.find((p) => p.context_length)?.context_length ||
10086
HUGGINGFACE_DEFAULT_CONTEXT_WINDOW
10187

10288
const pricing = provider?.pricing || model.providers.find((p) => p.pricing)?.pricing
10389

104-
// Include provider name in description if specific provider is given
90+
// Include provider name in description if specific provider is given.
10591
const description = provider ? `${model.id} via ${provider.provider}` : `${model.id} via HuggingFace`
10692

10793
return {
10894
maxTokens: Math.min(contextLength, HUGGINGFACE_DEFAULT_MAX_TOKENS),
10995
contextWindow: contextLength,
110-
supportsImages: false, // HuggingFace API doesn't provide this info yet
96+
supportsImages: false, // HuggingFace API doesn't provide this info yet.
11197
supportsPromptCache: false,
11298
supportsComputerUse: false,
11399
inputPrice: pricing?.input,
@@ -125,7 +111,6 @@ function parseHuggingFaceModel(model: HuggingFaceModel, provider?: HuggingFacePr
125111
export async function getHuggingFaceModels(): Promise<ModelRecord> {
126112
const now = Date.now()
127113

128-
// Check cache
129114
if (cache && now - cache.timestamp < HUGGINGFACE_CACHE_DURATION) {
130115
return cache.data
131116
}
@@ -144,7 +129,7 @@ export async function getHuggingFaceModels(): Promise<ModelRecord> {
144129
Pragma: "no-cache",
145130
"Cache-Control": "no-cache",
146131
},
147-
timeout: 10000, // 10 second timeout
132+
timeout: 10000,
148133
})
149134

150135
const result = huggingFaceApiResponseSchema.safeParse(response.data)
@@ -157,38 +142,31 @@ export async function getHuggingFaceModels(): Promise<ModelRecord> {
157142
const validModels = result.data.data.filter((model) => model.providers.length > 0)
158143

159144
for (const model of validModels) {
160-
// Add the base model
145+
// Add the base model.
161146
models[model.id] = parseHuggingFaceModel(model)
162147

163-
// Add provider-specific variants for all live providers
148+
// Add provider-specific variants for all live providers.
164149
for (const provider of model.providers) {
165150
if (provider.status === "live") {
166151
const providerKey = `${model.id}:${provider.provider}`
167152
const providerModel = parseHuggingFaceModel(model, provider)
168153

169-
// Always add provider variants to show all available providers
154+
// Always add provider variants to show all available providers.
170155
models[providerKey] = providerModel
171156
}
172157
}
173158
}
174159

175-
// Update cache
176-
cache = {
177-
data: models,
178-
rawModels: validModels,
179-
timestamp: now,
180-
}
160+
cache = { data: models, rawModels: validModels, timestamp: now }
181161

182162
return models
183163
} catch (error) {
184164
console.error("Error fetching HuggingFace models:", error)
185165

186-
// Return cached data if available
187166
if (cache) {
188167
return cache.data
189168
}
190169

191-
// Re-throw with more context
192170
if (axios.isAxiosError(error)) {
193171
if (error.response) {
194172
throw new Error(
@@ -208,45 +186,35 @@ export async function getHuggingFaceModels(): Promise<ModelRecord> {
208186
}
209187

210188
/**
211-
* Get cached models without making an API request
189+
* Get cached models without making an API request.
212190
*/
213191
export function getCachedHuggingFaceModels(): ModelRecord | null {
214192
return cache?.data || null
215193
}
216194

217195
/**
218-
* Get cached raw models for UI display
196+
* Get cached raw models for UI display.
219197
*/
220198
export function getCachedRawHuggingFaceModels(): HuggingFaceModel[] | null {
221199
return cache?.rawModels || null
222200
}
223201

224-
/**
225-
* Clear the cache
226-
*/
227202
export function clearHuggingFaceCache(): void {
228203
cache = null
229204
}
230205

231-
/**
232-
* HuggingFace Models Response Interface
233-
*/
234206
export interface HuggingFaceModelsResponse {
235207
models: HuggingFaceModel[]
236208
cached: boolean
237209
timestamp: number
238210
}
239211

240-
/**
241-
* Get HuggingFace models with response metadata
242-
* This function provides a higher-level API that includes cache status and timestamp
243-
*/
244212
export async function getHuggingFaceModelsWithMetadata(): Promise<HuggingFaceModelsResponse> {
245213
try {
246-
// First, trigger the fetch to populate cache
214+
// First, trigger the fetch to populate cache.
247215
await getHuggingFaceModels()
248216

249-
// Get the raw models from cache
217+
// Get the raw models from cache.
250218
const cachedRawModels = getCachedRawHuggingFaceModels()
251219

252220
if (cachedRawModels) {
@@ -257,7 +225,7 @@ export async function getHuggingFaceModelsWithMetadata(): Promise<HuggingFaceMod
257225
}
258226
}
259227

260-
// If no cached raw models, fetch directly from API
228+
// If no cached raw models, fetch directly from API.
261229
const response = await axios.get(HUGGINGFACE_API_URL, {
262230
headers: {
263231
"Upgrade-Insecure-Requests": "1",
@@ -281,10 +249,6 @@ export async function getHuggingFaceModelsWithMetadata(): Promise<HuggingFaceMod
281249
}
282250
} catch (error) {
283251
console.error("Failed to get HuggingFace models:", error)
284-
return {
285-
models: [],
286-
cached: false,
287-
timestamp: Date.now(),
288-
}
252+
return { models: [], cached: false, timestamp: Date.now() }
289253
}
290254
}

0 commit comments

Comments
 (0)