mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
- Update parseOpenRouterModel to always use actual max_completion_tokens from OpenRouter API - Remove artificial restriction that only reasoning budget and Anthropic models get their actual max tokens - Fall back to 20% of context window when max_completion_tokens is null - Update getModelMaxOutputTokens to use same fallback logic for consistency - Update tests to reflect new behavior - Fixes issue where reserved tokens showed ~209k instead of actual model limits (e.g. GPT-4o: 16,384)
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
import { type ModelInfo, type ProviderSettings, ANTHROPIC_DEFAULT_MAX_TOKENS } from "@roo-code/types"
|
|
|
|
// ApiHandlerOptions
|
|
|
|
export type ApiHandlerOptions = Omit<ProviderSettings, "apiProvider">
|
|
|
|
// RouterName
|
|
|
|
const routerNames = ["openrouter", "requesty", "glama", "unbound", "litellm", "ollama", "lmstudio"] as const
|
|
|
|
export type RouterName = (typeof routerNames)[number]
|
|
|
|
export const isRouterName = (value: string): value is RouterName => routerNames.includes(value as RouterName)
|
|
|
|
export function toRouterName(value?: string): RouterName {
|
|
if (value && isRouterName(value)) {
|
|
return value
|
|
}
|
|
|
|
throw new Error(`Invalid router name: ${value}`)
|
|
}
|
|
|
|
// RouterModels
|
|
|
|
export type ModelRecord = Record<string, ModelInfo>
|
|
|
|
export type RouterModels = Record<RouterName, ModelRecord>
|
|
|
|
// Reasoning
|
|
|
|
export const shouldUseReasoningBudget = ({
|
|
model,
|
|
settings,
|
|
}: {
|
|
model: ModelInfo
|
|
settings?: ProviderSettings
|
|
}): boolean => !!model.requiredReasoningBudget || (!!model.supportsReasoningBudget && !!settings?.enableReasoningEffort)
|
|
|
|
export const shouldUseReasoningEffort = ({
|
|
model,
|
|
settings,
|
|
}: {
|
|
model: ModelInfo
|
|
settings?: ProviderSettings
|
|
}): boolean => (!!model.supportsReasoningEffort && !!settings?.reasoningEffort) || !!model.reasoningEffort
|
|
|
|
export const DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS = 16_384
|
|
export const DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS = 8_192
|
|
|
|
// Max Tokens
|
|
|
|
export const getModelMaxOutputTokens = ({
|
|
modelId,
|
|
model,
|
|
settings,
|
|
}: {
|
|
modelId: string
|
|
model: ModelInfo
|
|
settings?: ProviderSettings
|
|
}): number | undefined => {
|
|
if (shouldUseReasoningBudget({ model, settings })) {
|
|
return settings?.modelMaxTokens || DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS
|
|
}
|
|
|
|
const isAnthropicModel = modelId.includes("claude")
|
|
|
|
// For "Hybrid" reasoning models, we should discard the model's actual
|
|
// `maxTokens` value if we're not using reasoning. We do this for Anthropic
|
|
// models only for now. Should we do this for Gemini too?
|
|
if (model.supportsReasoningBudget && isAnthropicModel) {
|
|
return ANTHROPIC_DEFAULT_MAX_TOKENS
|
|
}
|
|
|
|
// If maxTokens is 0 or undefined, fall back to 20% of context window
|
|
// This matches the sliding window logic
|
|
return model.maxTokens || Math.ceil(model.contextWindow * 0.2)
|
|
}
|
|
|
|
// GetModelsOptions
|
|
|
|
export type GetModelsOptions =
|
|
| { provider: "openrouter" }
|
|
| { provider: "glama" }
|
|
| { provider: "requesty"; apiKey?: string }
|
|
| { provider: "unbound"; apiKey?: string }
|
|
| { provider: "litellm"; apiKey: string; baseUrl: string }
|
|
| { provider: "ollama"; baseUrl?: string }
|
|
| { provider: "lmstudio"; baseUrl?: string }
|