refactor(model-core): remove src back-imports via core utilities and adapter
- move fuzzyMatchModel and transformModelForProvider into model-core - replace connected-providers re-export with adapter contract - route shared wrappers through model-core exports Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -5,6 +5,12 @@ import { getOpenCodeCacheDir } from "./data-path"
|
||||
import * as connectedProvidersCache from "./connected-providers-cache"
|
||||
import { normalizeSDKResponse } from "./normalize-sdk-response"
|
||||
|
||||
function normalizeModelName(name: string): string {
|
||||
return name
|
||||
.toLowerCase()
|
||||
.replace(/claude-(opus|sonnet|haiku)-(\d+)[.-](\d+)/g, "claude-$1-$2.$3")
|
||||
}
|
||||
|
||||
/**
|
||||
* Fuzzy match a target model name against available models
|
||||
*
|
||||
@@ -25,12 +31,6 @@ import { normalizeSDKResponse } from "./normalize-sdk-response"
|
||||
* fuzzyMatchModel("gpt-5.4", available) // → "openai/gpt-5.4"
|
||||
* fuzzyMatchModel("claude", available, ["openai"]) // → null (provider filter excludes anthropic)
|
||||
*/
|
||||
function normalizeModelName(name: string): string {
|
||||
return name
|
||||
.toLowerCase()
|
||||
.replace(/claude-(opus|sonnet|haiku)-(\d+)[.-](\d+)/g, "claude-$1-$2.$3")
|
||||
}
|
||||
|
||||
export function fuzzyMatchModel(
|
||||
target: string,
|
||||
available: Set<string>,
|
||||
@@ -45,7 +45,6 @@ export function fuzzyMatchModel(
|
||||
|
||||
const targetNormalized = normalizeModelName(target)
|
||||
|
||||
// Filter by providers if specified
|
||||
let candidates = Array.from(available)
|
||||
if (providers && providers.length > 0) {
|
||||
const providerSet = new Set(providers)
|
||||
@@ -61,7 +60,6 @@ export function fuzzyMatchModel(
|
||||
return null
|
||||
}
|
||||
|
||||
// Find all matches (case-insensitive substring match with normalization)
|
||||
const matches = candidates.filter((model) =>
|
||||
normalizeModelName(model).includes(targetNormalized),
|
||||
)
|
||||
@@ -73,16 +71,12 @@ export function fuzzyMatchModel(
|
||||
return null
|
||||
}
|
||||
|
||||
// Priority 1: Exact match (normalized full model string)
|
||||
const exactMatch = matches.find((model) => normalizeModelName(model) === targetNormalized)
|
||||
if (exactMatch) {
|
||||
log("[fuzzyMatchModel] exact match found", { exactMatch })
|
||||
return exactMatch
|
||||
}
|
||||
|
||||
// Priority 2: Exact model ID match (part after provider/)
|
||||
// This ensures "big-pickle" matches "zai-coding-plan/big-pickle" over "zai-coding-plan/glm-5"
|
||||
// Use filter + shortest to handle multi-provider cases (e.g., openai/gpt-5.4 + opencode/gpt-5.4)
|
||||
const exactModelIdMatches = matches.filter((model) => {
|
||||
const modelId = model.split("/").slice(1).join("/")
|
||||
return normalizeModelName(modelId) === targetNormalized
|
||||
@@ -95,7 +89,6 @@ export function fuzzyMatchModel(
|
||||
return result
|
||||
}
|
||||
|
||||
// Priority 3: Shorter model name (more specific, fallback for partial matches)
|
||||
const result = matches.reduce((shortest, current) =>
|
||||
current.length < shortest.length ? current : shortest,
|
||||
)
|
||||
@@ -103,13 +96,6 @@ export function fuzzyMatchModel(
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a target model is available (fuzzy match by model name, no provider filtering)
|
||||
*
|
||||
* @param targetModel - Model name to check (e.g., "gpt-5.3-codex")
|
||||
* @param availableModels - Set of available models in "provider/model" format
|
||||
* @returns true if model is available, false otherwise
|
||||
*/
|
||||
export function isModelAvailable(
|
||||
targetModel: string,
|
||||
availableModels: Set<string>,
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
import {
|
||||
resolveModel,
|
||||
resolveModelWithFallback as resolveModelWithFallbackFromCore,
|
||||
normalizeFallbackModels,
|
||||
flattenToFallbackModelStrings,
|
||||
} from "@oh-my-opencode/model-core"
|
||||
import type {
|
||||
ModelResolutionInput,
|
||||
ExtendedModelResolutionInput,
|
||||
} from "@oh-my-opencode/model-core"
|
||||
import * as connectedProvidersCache from "./connected-providers-cache"
|
||||
|
||||
export { resolveModel, normalizeFallbackModels, flattenToFallbackModelStrings }
|
||||
|
||||
type CoreModelResolutionResult = ReturnType<typeof resolveModelWithFallbackFromCore>
|
||||
export type ModelResolutionResult = Exclude<CoreModelResolutionResult, undefined>
|
||||
export type ModelSource = ModelResolutionResult["source"]
|
||||
|
||||
export function resolveModelWithFallback(
|
||||
input: ExtendedModelResolutionInput,
|
||||
): CoreModelResolutionResult {
|
||||
return resolveModelWithFallbackFromCore(input, connectedProvidersCache)
|
||||
}
|
||||
|
||||
export type {
|
||||
ModelResolutionInput,
|
||||
ModelSource,
|
||||
ModelResolutionResult,
|
||||
ExtendedModelResolutionInput,
|
||||
} from "@oh-my-opencode/model-core"
|
||||
export {
|
||||
resolveModel,
|
||||
resolveModelWithFallback,
|
||||
normalizeFallbackModels,
|
||||
flattenToFallbackModelStrings,
|
||||
} from "@oh-my-opencode/model-core"
|
||||
ModelResolutionInput,
|
||||
ExtendedModelResolutionInput,
|
||||
}
|
||||
|
||||
@@ -23,18 +23,13 @@ function applyGatewayTransforms(model: string): string {
|
||||
}
|
||||
|
||||
export function transformModelForProvider(provider: string, model: string): string {
|
||||
// Vercel AI Gateway expects <sub-provider>/<model> (e.g. anthropic/claude-opus-4.7).
|
||||
// Canonical names in model-requirements.ts may be bare (claude-opus-4-7) or
|
||||
// already prefixed (anthropic/claude-opus-4-7). Both need gateway-specific transforms.
|
||||
if (provider === "vercel") {
|
||||
// Already prefixed — transform only the model part
|
||||
const slashIndex = model.indexOf("/")
|
||||
if (slashIndex !== -1) {
|
||||
const subProvider = model.substring(0, slashIndex)
|
||||
const subModel = model.substring(slashIndex + 1)
|
||||
return `${subProvider}/${applyGatewayTransforms(subModel)}`
|
||||
}
|
||||
// Bare name — infer sub-provider from model prefix (claude- → anthropic, etc.)
|
||||
const subProvider = inferSubProvider(model)
|
||||
if (subProvider) {
|
||||
return `${subProvider}/${applyGatewayTransforms(model)}`
|
||||
|
||||
Reference in New Issue
Block a user