Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
5.6 kB · 157 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158import type { PermissionMode } from '../permissions/PermissionMode.js'import { capitalize } from '../stringUtils.js'import { MODEL_ALIASES, type ModelAlias } from './aliases.js'import { applyBedrockRegionPrefix, getBedrockRegionPrefix } from './bedrock.js'import { getCanonicalName, getRuntimeMainLoopModel, parseUserSpecifiedModel,} from './model.js'import { getAPIProvider } from './providers.js'
export const AGENT_MODEL_OPTIONS = [...MODEL_ALIASES, 'inherit'] as constexport type AgentModelAlias = (typeof AGENT_MODEL_OPTIONS)[number]
export type AgentModelOption = { value: AgentModelAlias label: string description: string}
/** * Get the default subagent model. Returns 'inherit' so subagents inherit * the model from the parent thread. */export function getDefaultSubagentModel(): string { return 'inherit'}
/** * Get the effective model string for an agent. * * For Bedrock, if the parent model uses a cross-region inference prefix (e.g., "eu.", "us."), * that prefix is inherited by subagents using alias models (e.g., "sonnet", "haiku", "opus"). * This ensures subagents use the same region as the parent, which is necessary when * IAM permissions are scoped to specific cross-region inference profiles. */export function getAgentModel( agentModel: string | undefined, parentModel: string, toolSpecifiedModel?: ModelAlias, permissionMode?: PermissionMode,): string { if (process.env.CLAUDE_CODE_SUBAGENT_MODEL) { return parseUserSpecifiedModel(process.env.CLAUDE_CODE_SUBAGENT_MODEL) }
// Extract Bedrock region prefix from parent model to inherit for subagents. // This ensures subagents use the same cross-region inference profile (e.g., "eu.", "us.") // as the parent, which is required when IAM permissions only allow specific regions. const parentRegionPrefix = getBedrockRegionPrefix(parentModel)
// Helper to apply parent region prefix for Bedrock models. // `originalSpec` is the raw model string before resolution (alias or full ID). // If the user explicitly specified a full model ID that already carries its own // region prefix (e.g., "eu.anthropic.…"), we preserve it instead of overwriting // with the parent's prefix. This prevents silent data-residency violations when // an agent config intentionally pins to a different region than the parent. const applyParentRegionPrefix = ( resolvedModel: string, originalSpec: string, ): string => { if (parentRegionPrefix && getAPIProvider() === 'bedrock') { if (getBedrockRegionPrefix(originalSpec)) return resolvedModel return applyBedrockRegionPrefix(resolvedModel, parentRegionPrefix) } return resolvedModel }
// Prioritize tool-specified model if provided if (toolSpecifiedModel) { if (aliasMatchesParentTier(toolSpecifiedModel, parentModel)) { return parentModel } const model = parseUserSpecifiedModel(toolSpecifiedModel) return applyParentRegionPrefix(model, toolSpecifiedModel) }
const agentModelWithExp = agentModel ?? getDefaultSubagentModel()
if (agentModelWithExp === 'inherit') { // Apply runtime model resolution for inherit to get the effective model // This ensures agents using 'inherit' get opusplan→Opus resolution in plan mode return getRuntimeMainLoopModel({ permissionMode: permissionMode ?? 'default', mainLoopModel: parentModel, exceeds200kTokens: false, }) }
if (aliasMatchesParentTier(agentModelWithExp, parentModel)) { return parentModel } const model = parseUserSpecifiedModel(agentModelWithExp) return applyParentRegionPrefix(model, agentModelWithExp)}
/** * Check if a bare family alias (opus/sonnet/haiku) matches the parent model's * tier. When it does, the subagent inherits the parent's exact model string * instead of resolving the alias to a provider default. * * Prevents surprising downgrades: a Vertex user on Opus 4.6 (via /model) who * spawns a subagent with `model: opus` should get Opus 4.6, not whatever * getDefaultOpusModel() returns for 3P. * See https://github.com/anthropics/claude-code/issues/30815. * * Only bare family aliases match. `opus[1m]`, `best`, `opusplan` fall through * since they carry semantics beyond "same tier as parent". */function aliasMatchesParentTier(alias: string, parentModel: string): boolean { const canonical = getCanonicalName(parentModel) switch (alias.toLowerCase()) { case 'opus': return canonical.includes('opus') case 'sonnet': return canonical.includes('sonnet') case 'haiku': return canonical.includes('haiku') default: return false }}
export function getAgentModelDisplay(model: string | undefined): string { // When model is omitted, getDefaultSubagentModel() returns 'inherit' at runtime if (!model) return 'Inherit from parent (default)' if (model === 'inherit') return 'Inherit from parent' return capitalize(model)}
/** * Get available model options for agents */export function getAgentModelOptions(): AgentModelOption[] { return [ { value: 'sonnet', label: 'Sonnet', description: 'Balanced performance - best for most agents', }, { value: 'opus', label: 'Opus', description: 'Most capable for complex reasoning tasks', }, { value: 'haiku', label: 'Haiku', description: 'Fast and efficient for simple tasks', }, { value: 'inherit', label: 'Inherit from parent', description: 'Use the same model as the main conversation', }, ]}