Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
6.9 kB · 221 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reorderedimport { CONTEXT_1M_BETA_HEADER } from '../constants/betas.js'import { getGlobalConfig } from './config.js'import { isEnvTruthy } from './envUtils.js'import { getCanonicalName } from './model/model.js'import { getModelCapability } from './model/modelCapabilities.js'
// Model context window size (200k tokens for all models right now)export const MODEL_CONTEXT_WINDOW_DEFAULT = 200_000
// Maximum output tokens for compact operationsexport const COMPACT_MAX_OUTPUT_TOKENS = 20_000
// Default max output tokensconst MAX_OUTPUT_TOKENS_DEFAULT = 32_000const MAX_OUTPUT_TOKENS_UPPER_LIMIT = 64_000
// Capped default for slot-reservation optimization. BQ p99 output = 4,911// tokens, so 32k/64k defaults over-reserve 8-16× slot capacity. With the cap// enabled, <1% of requests hit the limit; those get one clean retry at 64k// (see query.ts max_output_tokens_escalate). Cap is applied in// claude.ts:getMaxOutputTokensForModel to avoid the growthbook→betas→context// import cycle.export const CAPPED_DEFAULT_MAX_TOKENS = 8_000export const ESCALATED_MAX_TOKENS = 64_000
/** * Check if 1M context is disabled via environment variable. * Used by C4E admins to disable 1M context for HIPAA compliance. */export function is1mContextDisabled(): boolean { return isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_1M_CONTEXT)}
export function has1mContext(model: string): boolean { if (is1mContextDisabled()) { return false } return /\[1m\]/i.test(model)}
// @[MODEL LAUNCH]: Update this pattern if the new model supports 1M contextexport function modelSupports1M(model: string): boolean { if (is1mContextDisabled()) { return false } const canonical = getCanonicalName(model) return canonical.includes('claude-sonnet-4') || canonical.includes('opus-4-6')}
export function getContextWindowForModel( model: string, betas?: string[],): number { // Allow override via environment variable (ant-only) // This takes precedence over all other context window resolution, including 1M detection, // so users can cap the effective context window for local decisions (auto-compact, etc.) // while still using a 1M-capable endpoint. if ( process.env.USER_TYPE === 'ant' && process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS ) { const override = parseInt(process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS, 10) if (!isNaN(override) && override > 0) { return override } }
// [1m] suffix — explicit client-side opt-in, respected over all detection if (has1mContext(model)) { return 1_000_000 }
const cap = getModelCapability(model) if (cap?.max_input_tokens && cap.max_input_tokens >= 100_000) { if ( cap.max_input_tokens > MODEL_CONTEXT_WINDOW_DEFAULT && is1mContextDisabled() ) { return MODEL_CONTEXT_WINDOW_DEFAULT } return cap.max_input_tokens }
if (betas?.includes(CONTEXT_1M_BETA_HEADER) && modelSupports1M(model)) { return 1_000_000 } if (getSonnet1mExpTreatmentEnabled(model)) { return 1_000_000 } if (process.env.USER_TYPE === 'ant') { const antModel = resolveAntModel(model) if (antModel?.contextWindow) { return antModel.contextWindow } } return MODEL_CONTEXT_WINDOW_DEFAULT}
export function getSonnet1mExpTreatmentEnabled(model: string): boolean { if (is1mContextDisabled()) { return false } // Only applies to sonnet 4.6 without an explicit [1m] suffix if (has1mContext(model)) { return false } if (!getCanonicalName(model).includes('sonnet-4-6')) { return false } return getGlobalConfig().clientDataCache?.['coral_reef_sonnet'] === 'true'}
/** * Calculate context window usage percentage from token usage data. * Returns used and remaining percentages, or null values if no usage data. */export function calculateContextPercentages( currentUsage: { input_tokens: number cache_creation_input_tokens: number cache_read_input_tokens: number } | null, contextWindowSize: number,): { used: number | null; remaining: number | null } { if (!currentUsage) { return { used: null, remaining: null } }
const totalInputTokens = currentUsage.input_tokens + currentUsage.cache_creation_input_tokens + currentUsage.cache_read_input_tokens
const usedPercentage = Math.round( (totalInputTokens / contextWindowSize) * 100, ) const clampedUsed = Math.min(100, Math.max(0, usedPercentage))
return { used: clampedUsed, remaining: 100 - clampedUsed, }}
/** * Returns the model's default and upper limit for max output tokens. */export function getModelMaxOutputTokens(model: string): { default: number upperLimit: number} { let defaultTokens: number let upperLimit: number
if (process.env.USER_TYPE === 'ant') { const antModel = resolveAntModel(model.toLowerCase()) if (antModel) { defaultTokens = antModel.defaultMaxTokens ?? MAX_OUTPUT_TOKENS_DEFAULT upperLimit = antModel.upperMaxTokensLimit ?? MAX_OUTPUT_TOKENS_UPPER_LIMIT return { default: defaultTokens, upperLimit } } }
const m = getCanonicalName(model)
if (m.includes('opus-4-6')) { defaultTokens = 64_000 upperLimit = 128_000 } else if (m.includes('sonnet-4-6')) { defaultTokens = 32_000 upperLimit = 128_000 } else if ( m.includes('opus-4-5') || m.includes('sonnet-4') || m.includes('haiku-4') ) { defaultTokens = 32_000 upperLimit = 64_000 } else if (m.includes('opus-4-1') || m.includes('opus-4')) { defaultTokens = 32_000 upperLimit = 32_000 } else if (m.includes('claude-3-opus')) { defaultTokens = 4_096 upperLimit = 4_096 } else if (m.includes('claude-3-sonnet')) { defaultTokens = 8_192 upperLimit = 8_192 } else if (m.includes('claude-3-haiku')) { defaultTokens = 4_096 upperLimit = 4_096 } else if (m.includes('3-5-sonnet') || m.includes('3-5-haiku')) { defaultTokens = 8_192 upperLimit = 8_192 } else if (m.includes('3-7-sonnet')) { defaultTokens = 32_000 upperLimit = 64_000 } else { defaultTokens = MAX_OUTPUT_TOKENS_DEFAULT upperLimit = MAX_OUTPUT_TOKENS_UPPER_LIMIT }
const cap = getModelCapability(model) if (cap?.max_tokens && cap.max_tokens >= 4_096) { upperLimit = cap.max_tokens defaultTokens = Math.min(defaultTokens, upperLimit) }
return { default: defaultTokens, upperLimit }}
/** * Returns the max thinking budget tokens for a given model. The max * thinking tokens should be strictly less than the max output tokens. * * Deprecated since newer models use adaptive thinking rather than a * strict thinking token budget. */export function getMaxThinkingTokensForModel(model: string): number { return getModelMaxOutputTokens(model).upperLimit - 1}