Skip to content

Commit b2c02de

Browse files
committed
Update types
1 parent dbdc8e4 commit b2c02de

File tree

2 files changed

+80
-39
lines changed
  • packages/types/src/providers
  • src/api/providers/fetchers

2 files changed

+80
-39
lines changed

packages/types/src/providers/roo.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { z } from "zod"
2+
13
import type { ModelInfo } from "../model.js"
24

35
/**
@@ -11,3 +13,37 @@ export const rooDefaultModelId = "xai/grok-code-fast-1"
1113
* All model data comes dynamically from the API.
1214
*/
1315
export const rooModels = {} as const satisfies Record<string, ModelInfo>
16+
17+
/**
18+
* Roo Code Cloud API response schemas
19+
*/
20+
21+
export const RooPricingSchema = z.object({
22+
input: z.string(),
23+
output: z.string(),
24+
input_cache_read: z.string().optional(),
25+
input_cache_write: z.string().optional(),
26+
})
27+
28+
export const RooModelSchema = z.object({
29+
id: z.string(),
30+
object: z.literal("model"),
31+
created: z.number(),
32+
owned_by: z.string(),
33+
name: z.string(),
34+
description: z.string(),
35+
context_window: z.number(),
36+
max_tokens: z.number(),
37+
type: z.literal("language"),
38+
tags: z.array(z.string()).optional(),
39+
pricing: RooPricingSchema,
40+
deprecated: z.boolean().optional(),
41+
})
42+
43+
export const RooModelsResponseSchema = z.object({
44+
object: z.literal("list"),
45+
data: z.array(RooModelSchema),
46+
})
47+
48+
export type RooModel = z.infer<typeof RooModelSchema>
49+
export type RooModelsResponse = z.infer<typeof RooModelsResponseSchema>

src/api/providers/fetchers/roo.ts

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import axios from "axios"
22

3+
import { RooModelsResponseSchema } from "@roo-code/types"
4+
35
import type { ModelRecord } from "../../../shared/api"
46

57
import { DEFAULT_HEADERS } from "../constants"
@@ -37,49 +39,52 @@ export async function getRooModels(baseUrl: string, apiKey?: string): Promise<Mo
3739
// Added timeout to prevent indefinite hanging
3840
const response = await axios.get(url, { headers, timeout: 10000 })
3941
const models: ModelRecord = {}
40-
// Process the model info from the response
41-
// Expected format: { object: "list", data: [{ id, name, description, context_window, max_tokens, tags, pricing }] }
42-
if (response.data && response.data.data && Array.isArray(response.data.data)) {
43-
for (const model of response.data.data) {
44-
const modelId = model.id
45-
46-
if (!modelId) continue
47-
48-
// Extract model data from the API response
49-
const contextWindow = model.context_window || 262_144
50-
const maxTokens = model.max_tokens || 16_384
51-
const tags = model.tags || []
52-
const pricing = model.pricing || {}
53-
54-
// Determine if the model supports images based on tags
55-
const supportsImages = tags.includes("vision") || tags.includes("image")
56-
57-
// Parse pricing (API returns strings, convert to numbers)
58-
// Handle both direct pricing and cache pricing if available
59-
const inputPrice = pricing.input ? parseFloat(pricing.input) : 0
60-
const outputPrice = pricing.output ? parseFloat(pricing.output) : 0
61-
const cacheReadPrice = pricing.input_cache_read ? parseFloat(pricing.input_cache_read) : undefined
62-
const cacheWritePrice = pricing.input_cache_write ? parseFloat(pricing.input_cache_write) : undefined
63-
64-
models[modelId] = {
65-
maxTokens,
66-
contextWindow,
67-
supportsImages,
68-
supportsPromptCache: Boolean(cacheReadPrice !== undefined || cacheWritePrice !== undefined),
69-
inputPrice,
70-
outputPrice,
71-
cacheWritesPrice: cacheWritePrice,
72-
cacheReadsPrice: cacheReadPrice,
73-
description: model.description || model.name || `Model available through Roo Code Cloud`,
74-
deprecated: model.deprecated || false,
75-
}
76-
}
77-
} else {
78-
// If response.data.data is not in the expected format, consider it an error.
42+
43+
// Validate response against schema
44+
const parsed = RooModelsResponseSchema.safeParse(response.data)
45+
46+
if (!parsed.success) {
7947
console.error("Error fetching Roo Code Cloud models: Unexpected response format", response.data)
48+
console.error("Validation errors:", parsed.error.format())
8049
throw new Error("Failed to fetch Roo Code Cloud models: Unexpected response format.")
8150
}
8251

52+
// Process the validated model data
53+
for (const model of parsed.data.data) {
54+
const modelId = model.id
55+
56+
if (!modelId) continue
57+
58+
// Extract model data from the validated API response
59+
// All required fields are guaranteed by the schema
60+
const contextWindow = model.context_window
61+
const maxTokens = model.max_tokens
62+
const tags = model.tags || []
63+
const pricing = model.pricing
64+
65+
// Determine if the model supports images based on tags
66+
const supportsImages = tags.includes("vision")
67+
68+
// Parse pricing (API returns strings, convert to numbers)
69+
const inputPrice = parseFloat(pricing.input)
70+
const outputPrice = parseFloat(pricing.output)
71+
const cacheReadPrice = pricing.input_cache_read ? parseFloat(pricing.input_cache_read) : undefined
72+
const cacheWritePrice = pricing.input_cache_write ? parseFloat(pricing.input_cache_write) : undefined
73+
74+
models[modelId] = {
75+
maxTokens,
76+
contextWindow,
77+
supportsImages,
78+
supportsPromptCache: Boolean(cacheReadPrice !== undefined),
79+
inputPrice,
80+
outputPrice,
81+
cacheWritesPrice: cacheWritePrice,
82+
cacheReadsPrice: cacheReadPrice,
83+
description: model.description || model.name,
84+
deprecated: model.deprecated || false,
85+
}
86+
}
87+
8388
return models
8489
} catch (error: any) {
8590
console.error("Error fetching Roo Code Cloud models:", error.message ? error.message : error)

0 commit comments

Comments
 (0)