135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
import {
|
|
CLI_AGENT_MODEL_REQUIREMENTS,
|
|
CLI_CATEGORY_MODEL_REQUIREMENTS,
|
|
} from "./model-fallback-requirements"
|
|
import type { InstallConfig } from "./types"
|
|
|
|
import type { AgentConfig, CategoryConfig, GeneratedOmoConfig } from "./model-fallback-types"
|
|
import { toProviderAvailability } from "./provider-availability"
|
|
import {
|
|
getSisyphusFallbackChain,
|
|
isAnyFallbackEntryAvailable,
|
|
isRequiredModelAvailable,
|
|
isRequiredProviderAvailable,
|
|
resolveModelFromChain,
|
|
} from "./fallback-chain-resolution"
|
|
|
|
export type { GeneratedOmoConfig } from "./model-fallback-types"
|
|
|
|
const ZAI_MODEL = "zai-coding-plan/glm-4.7"
|
|
|
|
const ULTIMATE_FALLBACK = "opencode/glm-4.7-free"
|
|
const SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/dev/assets/oh-my-opencode.schema.json"
|
|
|
|
|
|
|
|
export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
|
|
const avail = toProviderAvailability(config)
|
|
const hasAnyProvider =
|
|
avail.native.claude ||
|
|
avail.native.openai ||
|
|
avail.native.gemini ||
|
|
avail.opencodeZen ||
|
|
avail.copilot ||
|
|
avail.zai ||
|
|
avail.kimiForCoding
|
|
|
|
if (!hasAnyProvider) {
|
|
return {
|
|
$schema: SCHEMA_URL,
|
|
agents: Object.fromEntries(
|
|
Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)
|
|
.filter(([role, req]) => !(role === "sisyphus" && req.requiresAnyModel))
|
|
.map(([role]) => [role, { model: ULTIMATE_FALLBACK }])
|
|
),
|
|
categories: Object.fromEntries(
|
|
Object.keys(CLI_CATEGORY_MODEL_REQUIREMENTS).map((cat) => [cat, { model: ULTIMATE_FALLBACK }])
|
|
),
|
|
}
|
|
}
|
|
|
|
const agents: Record<string, AgentConfig> = {}
|
|
const categories: Record<string, CategoryConfig> = {}
|
|
|
|
for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
|
|
if (role === "librarian" && avail.zai) {
|
|
agents[role] = { model: ZAI_MODEL }
|
|
continue
|
|
}
|
|
|
|
if (role === "explore") {
|
|
if (avail.native.claude) {
|
|
agents[role] = { model: "anthropic/claude-haiku-4-5" }
|
|
} else if (avail.opencodeZen) {
|
|
agents[role] = { model: "opencode/claude-haiku-4-5" }
|
|
} else if (avail.copilot) {
|
|
agents[role] = { model: "github-copilot/gpt-5-mini" }
|
|
} else {
|
|
agents[role] = { model: "opencode/gpt-5-nano" }
|
|
}
|
|
continue
|
|
}
|
|
|
|
if (role === "sisyphus") {
|
|
const fallbackChain = getSisyphusFallbackChain()
|
|
if (req.requiresAnyModel && !isAnyFallbackEntryAvailable(fallbackChain, avail)) {
|
|
continue
|
|
}
|
|
const resolved = resolveModelFromChain(fallbackChain, avail)
|
|
if (resolved) {
|
|
const variant = resolved.variant ?? req.variant
|
|
agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model }
|
|
}
|
|
continue
|
|
}
|
|
|
|
if (req.requiresModel && !isRequiredModelAvailable(req.requiresModel, req.fallbackChain, avail)) {
|
|
continue
|
|
}
|
|
if (req.requiresProvider && !isRequiredProviderAvailable(req.requiresProvider, avail)) {
|
|
continue
|
|
}
|
|
|
|
const resolved = resolveModelFromChain(req.fallbackChain, avail)
|
|
if (resolved) {
|
|
const variant = resolved.variant ?? req.variant
|
|
agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model }
|
|
} else {
|
|
agents[role] = { model: ULTIMATE_FALLBACK }
|
|
}
|
|
}
|
|
|
|
for (const [cat, req] of Object.entries(CLI_CATEGORY_MODEL_REQUIREMENTS)) {
|
|
// Special case: unspecified-high downgrades to unspecified-low when not isMaxPlan
|
|
const fallbackChain =
|
|
cat === "unspecified-high" && !avail.isMaxPlan
|
|
? CLI_CATEGORY_MODEL_REQUIREMENTS["unspecified-low"].fallbackChain
|
|
: req.fallbackChain
|
|
|
|
if (req.requiresModel && !isRequiredModelAvailable(req.requiresModel, req.fallbackChain, avail)) {
|
|
continue
|
|
}
|
|
if (req.requiresProvider && !isRequiredProviderAvailable(req.requiresProvider, avail)) {
|
|
continue
|
|
}
|
|
|
|
const resolved = resolveModelFromChain(fallbackChain, avail)
|
|
if (resolved) {
|
|
const variant = resolved.variant ?? req.variant
|
|
categories[cat] = variant ? { model: resolved.model, variant } : { model: resolved.model }
|
|
} else {
|
|
categories[cat] = { model: ULTIMATE_FALLBACK }
|
|
}
|
|
}
|
|
|
|
return {
|
|
$schema: SCHEMA_URL,
|
|
agents,
|
|
categories,
|
|
}
|
|
}
|
|
|
|
export function shouldShowChatGPTOnlyWarning(config: InstallConfig): boolean {
|
|
return !config.hasClaude && !config.hasGemini && config.hasOpenAI
|
|
}
|