Fix chutes model fetching (#9854)

This commit is contained in:
Chris Estreich 2025-12-04 21:57:06 -08:00 • committed by GitHub
parent e633c62e70
commit 6bdefb8de3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,19 +1,19 @@
import axios from "axios"
import { z } from "zod"
import { type ModelInfo, TOOL_PROTOCOL, chutesModels } from "@roo-code/types"
import { type ModelInfo, chutesModels } from "@roo-code/types"
import { DEFAULT_HEADERS } from "../constants"
// Chutes models endpoint follows OpenAI /models shape with additional fields
// Chutes models endpoint follows OpenAI /models shape with additional fields.
const ChutesModelSchema = z.object({
id: z.string(),
object: z.literal("model").optional(),
owned_by: z.string().optional(),
created: z.number().optional(),
context_length: z.number(),
context_length: z.number().optional(),
max_model_len: z.number(),
input_modalities: z.array(z.string()),
input_modalities: z.array(z.string()).optional(),
supported_features: z.array(z.string()).optional(),
})
@ -21,42 +21,49 @@ const ChutesModelsResponseSchema = z.object({ data: z.array(ChutesModelSchema) }
export async function getChutesModels(apiKey?: string): Promise<Record<string, ModelInfo>> {
const headers: Record<string, string> = { ...DEFAULT_HEADERS }
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`
if (apiKey) {
headers["Authorization"] = `Bearer ${apiKey}`
}
const url = "https://llm.chutes.ai/v1/models"
// Start with hardcoded models as the base
// Start with hardcoded models as the base.
const models: Record<string, ModelInfo> = { ...chutesModels }
try {
const response = await axios.get(url, { headers })
const parsed = ChutesModelsResponseSchema.safeParse(response.data)
const data = parsed.success ? parsed.data.data : response.data?.data || []
for (const m of data as Array<z.infer<typeof ChutesModelSchema>>) {
// Extract from API response (all fields are required)
const contextWindow = m.context_length
const maxTokens = m.max_model_len
const supportsImages = m.input_modalities.includes("image")
const supportsNativeTools = m.supported_features?.includes("tools") ?? false
if (parsed.success) {
for (const m of parsed.data.data) {
const contextWindow = m.context_length
const info: ModelInfo = {
maxTokens,
contextWindow,
supportsImages,
supportsPromptCache: false,
supportsNativeTools,
inputPrice: 0,
outputPrice: 0,
description: `Chutes AI model: ${m.id}`,
if (!contextWindow) {
console.error(`Context length is required for Chutes model: ${m.id}`)
continue
}
const info: ModelInfo = {
maxTokens: m.max_model_len,
contextWindow,
supportsImages: (m.input_modalities || []).includes("image"),
supportsPromptCache: false,
supportsNativeTools: (m.supported_features || []).includes("tools"),
inputPrice: 0,
outputPrice: 0,
description: `Chutes AI model: ${m.id}`,
}
// Union: dynamic models override hardcoded ones if they have the same ID.
models[m.id] = info
}
// Union: dynamic models override hardcoded ones if they have the same ID
models[m.id] = info
} else {
console.error(`Error parsing Chutes models: ${JSON.stringify(parsed.error.format(), null, 2)}`)
}
} catch (error) {
console.error(`Error fetching Chutes models: ${error instanceof Error ? error.message : String(error)}`)
// On error, still return hardcoded models
// On error, still return hardcoded models.
}
return models