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:
YeonGyu-Kim
2026-05-21 11:36:01 +09:00
parent 819bf0d11f
commit 2462d7af29
9 changed files with 222 additions and 51 deletions
+6 -20
View File
@@ -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>,