mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-06 02:47:56 +00:00
fix(openai-native): consolidate loaders + tolerant validation; surface custom models in OpenAI/OpenAI Native UI; fix lint types
This commit is contained in:
parent
27f404426c
commit
cc7c50c959
3 changed files with 30 additions and 21 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import type { ModelInfo } from "../model.js"
|
||||
import { modelInfoSchema, type ModelInfo } from "../model.js"
|
||||
|
||||
// https://openai.com/api/pricing/
|
||||
export type OpenAiNativeModelId = keyof typeof openAiNativeModels
|
||||
|
|
@ -328,12 +328,7 @@ function loadUserOpenAiNativeModels(): Record<string, ModelInfo> {
|
|||
try {
|
||||
const parsed = JSON.parse(inlineJson)
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
const envResult: Record<string, ModelInfo> = {}
|
||||
for (const [modelId, info] of Object.entries(parsed)) {
|
||||
if (info && typeof info === "object" && !Array.isArray(info)) {
|
||||
envResult[modelId] = info as ModelInfo
|
||||
}
|
||||
}
|
||||
const envResult = validateModelInfoRecord(parsed)
|
||||
return envResult
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -363,20 +358,32 @@ function loadUserOpenAiNativeModels(): Record<string, ModelInfo> {
|
|||
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {}
|
||||
|
||||
// Best-effort shallow validation; only keep object entries
|
||||
const result: Record<string, ModelInfo> = {}
|
||||
for (const [modelId, info] of Object.entries(parsed)) {
|
||||
if (info && typeof info === "object" && !Array.isArray(info)) {
|
||||
result[modelId] = info as ModelInfo
|
||||
}
|
||||
}
|
||||
return result
|
||||
// Use shared validator (merges sane defaults and accepts partials)
|
||||
return validateModelInfoRecord(parsed)
|
||||
} catch {
|
||||
// On any error (missing file, invalid JSON, restricted env), fall back to empty extras
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an arbitrary record of model info objects, keeping only entries that conform.
|
||||
*/
|
||||
export function validateModelInfoRecord(input: unknown): Record<string, ModelInfo> {
|
||||
if (!input || typeof input !== "object" || Array.isArray(input)) return {}
|
||||
const out: Record<string, ModelInfo> = {}
|
||||
for (const [id, info] of Object.entries(input as Record<string, unknown>)) {
|
||||
if (info && typeof info === "object" && !Array.isArray(info)) {
|
||||
const parsedInfo = modelInfoSchema.partial().safeParse(info)
|
||||
const merged = parsedInfo.success
|
||||
? { ...openAiModelInfoSaneDefaults, ...parsedInfo.data }
|
||||
: { ...openAiModelInfoSaneDefaults, ...(info as Record<string, unknown>) }
|
||||
out[id] = merged as ModelInfo
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns built-in OpenAI native models merged with user-defined additions.
|
||||
* User models override built-ins on key collision.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
openAiNativeDefaultModelId,
|
||||
OpenAiNativeModelId,
|
||||
openAiNativeModels,
|
||||
validateModelInfoRecord,
|
||||
OPENAI_NATIVE_DEFAULT_TEMPERATURE,
|
||||
GPT5_DEFAULT_TEMPERATURE,
|
||||
type ReasoningEffort,
|
||||
|
|
@ -47,7 +48,7 @@ function loadMergedOpenAiNativeModelsOnHostSync(): Record<string, ModelInfo> {
|
|||
if (inline) {
|
||||
const parsed = JSON.parse(inline)
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
extras = parsed as Record<string, ModelInfo>
|
||||
extras = validateModelInfoRecord(parsed)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -64,7 +65,7 @@ function loadMergedOpenAiNativeModelsOnHostSync(): Record<string, ModelInfo> {
|
|||
const raw = fsSync.readFileSync(customPath, "utf8")
|
||||
const parsed = JSON.parse(raw)
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
extras = parsed as Record<string, ModelInfo>
|
||||
extras = validateModelInfoRecord(parsed)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
type ClineMessage,
|
||||
type TelemetrySetting,
|
||||
type ModelInfo,
|
||||
validateModelInfoRecord,
|
||||
TelemetryEventName,
|
||||
UserSettingsConfig,
|
||||
DEFAULT_CHECKPOINT_TIMEOUT_SECONDS,
|
||||
|
|
@ -114,7 +115,7 @@ export const webviewMessageHandler = async (
|
|||
try {
|
||||
const parsed = JSON.parse(inline)
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
extras = parsed
|
||||
extras = validateModelInfoRecord(parsed)
|
||||
}
|
||||
} catch {
|
||||
// ignore malformed env json
|
||||
|
|
@ -130,7 +131,7 @@ export const webviewMessageHandler = async (
|
|||
const raw = await fs.readFile(customPath, "utf8")
|
||||
const parsed = JSON.parse(raw)
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
extras = parsed
|
||||
extras = validateModelInfoRecord(parsed)
|
||||
}
|
||||
} catch {
|
||||
// missing/invalid file: ignore
|
||||
|
|
@ -1030,8 +1031,8 @@ export const webviewMessageHandler = async (
|
|||
case "requestOpenAiNativeModels": {
|
||||
// Return merged built-ins + user-defined from ~/.roo/models/openai-native.json
|
||||
try {
|
||||
const openAiNativeModels = await getMergedOpenAiNativeModelsOnHost()
|
||||
provider.postMessageToWebview({ type: "openAiNativeModels", openAiNativeModels })
|
||||
const mergedModels = await getMergedOpenAiNativeModelsOnHost()
|
||||
provider.postMessageToWebview({ type: "openAiNativeModels", openAiNativeModels: mergedModels })
|
||||
} catch (error) {
|
||||
console.error("Failed to load OpenAI Native models:", error)
|
||||
provider.postMessageToWebview({ type: "openAiNativeModels", openAiNativeModels: {} })
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue