Files
oh-my-opencode/src/shared/agent-variant.ts
T
YeonGyu-Kim 62c60ae9d8 fix: numeric skill names, ultrawork missing run_in_background, ZWSP agent lookups
- #3354: Coerce data.name to String in loadSkillFromPath/loadSkillFromPathAsync
  to prevent crash when YAML parses numeric skill names (e.g., name: 12306)

- #3416: Add required run_in_background parameter to all task() examples in
  ultrawork prompts (default, gpt, gemini, planner) to match tool schema

- #3379/#3417/#3418/#3337/#3335: Strip ZWSP (U+200B) before agent name
  comparisons in agent-tool-restrictions, sync-prompt-sender, tool-execute-after,
  tool-execute-before, oracle-verification-detector, call-omo-agent,
  recovery-prompt-config, and agent-variant to prevent ZWSP-prefixed display
  names from breaking exact-match lookups
2026-04-15 10:46:41 +09:00

102 lines
3.0 KiB
TypeScript

import type { OhMyOpenCodeConfig } from "../config"
import { stripInvisibleAgentCharacters } from "./agent-display-names"
import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "./model-requirements"
export function resolveAgentVariant(
config: OhMyOpenCodeConfig,
agentName?: string
): string | undefined {
if (!agentName) {
return undefined
}
const stripped = stripInvisibleAgentCharacters(agentName)
const agentOverrides = config.agents as
| Record<string, { variant?: string; category?: string }>
| undefined
const agentOverride = agentOverrides
? agentOverrides[stripped]
?? Object.entries(agentOverrides).find(([key]) => key.toLowerCase() === stripped.toLowerCase())?.[1]
: undefined
if (!agentOverride) {
return undefined
}
if (agentOverride.variant) {
return agentOverride.variant
}
const categoryName = agentOverride.category
if (!categoryName) {
return undefined
}
return config.categories?.[categoryName]?.variant
}
export function resolveVariantForModel(
config: OhMyOpenCodeConfig,
agentName: string,
currentModel: { providerID: string; modelID: string },
): string | undefined {
const stripped = stripInvisibleAgentCharacters(agentName)
const agentOverrides = config.agents as
| Record<string, { variant?: string; category?: string }>
| undefined
const agentOverride = agentOverrides
? agentOverrides[stripped]
?? Object.entries(agentOverrides).find(([key]) => key.toLowerCase() === stripped.toLowerCase())?.[1]
: undefined
if (agentOverride?.variant) {
return agentOverride.variant
}
const agentRequirement = AGENT_MODEL_REQUIREMENTS[stripped]
if (agentRequirement) {
return findVariantInChain(agentRequirement.fallbackChain, currentModel)
}
const categoryName = agentOverride?.category
if (categoryName) {
const categoryRequirement = CATEGORY_MODEL_REQUIREMENTS[categoryName]
if (categoryRequirement) {
return findVariantInChain(categoryRequirement.fallbackChain, currentModel)
}
}
return undefined
}
function findVariantInChain(
fallbackChain: { providers: string[]; model: string; variant?: string }[],
currentModel: { providerID: string; modelID: string },
): string | undefined {
for (const entry of fallbackChain) {
if (
entry.providers.includes(currentModel.providerID)
&& entry.model === currentModel.modelID
) {
return entry.variant
}
}
// Some providers expose identical model IDs (e.g. OpenAI models via different providers).
// If we didn't find an exact provider+model match, fall back to model-only matching.
for (const entry of fallbackChain) {
if (entry.model === currentModel.modelID) {
return entry.variant
}
}
return undefined
}
export function applyAgentVariant(
config: OhMyOpenCodeConfig,
agentName: string | undefined,
message: { variant?: string }
): void {
const variant = resolveAgentVariant(config, agentName)
if (variant !== undefined && message.variant === undefined) {
message.variant = variant
}
}