Files
oh-my-opencode/src/shared/model-resolver.ts
T
um1ng ec9ab6b239 fix(runtime-fallback): address cubic AI review issues
- Add normalizeFallbackModels helper to centralize string/array normalization (P3)
- Export RuntimeFallbackConfig and FallbackModels types from config/index.ts
- Fix agent detection regex to use word boundaries for sessionID matching
- Improve tests to verify actual fallback switching logic (not just log paths)
- Add SessionCategoryRegistry cleanup in executeSyncTask on completion/error (P2)
- All 24 runtime-fallback tests pass, 115 delegate-task tests pass
2026-02-21 02:37:57 +09:00

86 lines
2.3 KiB
TypeScript

import type { FallbackEntry } from "./model-requirements"
import { resolveModelPipeline } from "./model-resolution-pipeline"
export type ModelResolutionInput = {
userModel?: string
inheritedModel?: string
systemDefault?: string
}
/**
* Normalizes fallback_models to an array.
* Handles single string or array input, returns undefined for falsy values.
*/
export function normalizeFallbackModels(
fallbackModels: string | string[] | undefined | null
): string[] | undefined {
if (!fallbackModels) return undefined
return Array.isArray(fallbackModels) ? fallbackModels : [fallbackModels]
}
export type ModelSource =
| "override"
| "category-default"
| "provider-fallback"
| "system-default"
export type ModelResolutionResult = {
model: string
source: ModelSource
variant?: string
}
export type ExtendedModelResolutionInput = {
uiSelectedModel?: string
userModel?: string
userFallbackModels?: string[]
categoryDefaultModel?: string
fallbackChain?: FallbackEntry[]
availableModels: Set<string>
systemDefaultModel?: string
}
function normalizeModel(model?: string): string | undefined {
const trimmed = model?.trim()
return trimmed || undefined
}
export function resolveModel(input: ModelResolutionInput): string | undefined {
return (
normalizeModel(input.userModel) ??
normalizeModel(input.inheritedModel) ??
input.systemDefault
)
}
export function resolveModelWithFallback(
input: ExtendedModelResolutionInput,
): ModelResolutionResult | undefined {
const { uiSelectedModel, userModel, userFallbackModels, categoryDefaultModel, fallbackChain, availableModels, systemDefaultModel } = input
const resolved = resolveModelPipeline({
intent: { uiSelectedModel, userModel, userFallbackModels, categoryDefaultModel },
constraints: { availableModels },
policy: { fallbackChain, systemDefaultModel },
})
if (!resolved) {
return undefined
}
return {
model: resolved.model,
source: resolved.provenance,
variant: resolved.variant,
}
}
/**
* Normalizes fallback_models config (which can be string or string[]) to string[]
* Centralized helper to avoid duplicated normalization logic
*/
export function normalizeFallbackModels(models: string | string[] | undefined): string[] | undefined {
if (!models) return undefined
if (typeof models === "string") return [models]
return models
}