Compare commits

...

5 Commits

Author SHA1 Message Date
abeatrix 569f5cf4bc supports 2025-11-13 13:11:38 -08:00
abeatrix 159bf5c19e reasoning check 2025-11-13 12:56:40 -08:00
abeatrix 9864279635 typo 2025-11-13 12:38:32 -08:00
abeatrix 6ee0ebeb45 add protos 2025-11-13 12:36:06 -08:00
abeatrix 095fcd70f3 fix: respect reasoning and temperature support flags
Ensure temperature is only supplied when the model advertises support and expose reasoning/temperature capabilities when refreshing OpenRouter models so reasoning and temperature settings are handled correctly.
2025-11-13 12:27:44 -08:00
5 changed files with 29 additions and 8 deletions
+2
View File
@@ -97,6 +97,8 @@ message OpenRouterModelInfo {
optional bool supports_global_endpoint = 11;
repeated ModelTier tiers = 12;
optional string name = 13;
optional bool supports_reasoning = 14;
optional bool supports_temperature = 15;
}
// Shared response message for model information
+15 -6
View File
@@ -34,6 +34,10 @@ export async function createOpenRouterStream(
model.id = model.id.slice(0, -CLAUDE_SONNET_1M_SUFFIX.length)
}
const { supportsTemperature, supportsReasoning } = model.info
const budget_tokens = thinkingBudgetTokens || 0
const reasoningOn = budget_tokens !== 0
// prompt caching: https://openrouter.ai/docs/prompt-caching
// this was initially specifically for claude models (some models may 'support prompt caching' automatically without this)
// handles direct model.id match logic
@@ -124,7 +128,9 @@ export async function createOpenRouterStream(
maxTokens = 8_192
break
}
// NOTE: Extended thinking does not support non-1 temperature
// Some models do not support temperatures, some do not support 0,
// so only set them for models that are known to support them.
let temperature: number | undefined = 0
let topP: number | undefined
if (
@@ -153,21 +159,24 @@ export async function createOpenRouterStream(
case "anthropic/claude-3.7-sonnet:thinking":
case "anthropic/claude-3-7-sonnet":
case "anthropic/claude-3-7-sonnet:beta":
const budget_tokens = thinkingBudgetTokens || 0
const reasoningOn = budget_tokens !== 0
if (reasoningOn) {
temperature = undefined // extended thinking does not support non-1 temperature
temperature = undefined
reasoning = { max_tokens: budget_tokens }
}
break
default:
if (thinkingBudgetTokens && model.info?.thinkingConfig && thinkingBudgetTokens > 0) {
temperature = undefined // extended thinking does not support non-1 temperature
reasoning = { max_tokens: thinkingBudgetTokens }
temperature = undefined
break
}
}
// Disable temperature when reasoning is on or not supported
if (supportsReasoning || reasoningOn || !supportsTemperature) {
temperature = undefined
}
const providerPreferences = OPENROUTER_PROVIDER_PREFERENCES[model.id]
if (providerPreferences) {
openRouterProviderSorting = undefined
@@ -177,7 +186,7 @@ export async function createOpenRouterStream(
const stream = await client.chat.completions.create({
model: model.id,
max_tokens: maxTokens,
temperature: temperature,
temperature,
top_p: topP,
messages: openAiMessages,
stream: true,
@@ -91,7 +91,9 @@ export async function refreshOpenRouterModels(controller: Controller): Promise<R
return undefined
}
for (const rawModel of rawModels as OpenRouterRawModelInfo[]) {
const supportThinking = rawModel.supported_parameters?.some((p) => p === "include_reasoning" || p === "reasoning")
// Matches "include_reasoning" and "reasoning"
const supportsReasoning = rawModel.supported_parameters?.some((p) => p.includes("reasoning")) ?? false
const supportsTemperature = rawModel.supported_parameters?.includes("temperature") ?? false
const modelInfo: ModelInfo = {
name: rawModel.name,
@@ -99,6 +101,8 @@ export async function refreshOpenRouterModels(controller: Controller): Promise<R
contextWindow: rawModel.context_length ?? 0,
supportsImages: rawModel.architecture?.modality?.includes("image") ?? false,
supportsPromptCache: false,
supportsReasoning,
supportsTemperature,
inputPrice: parsePrice(rawModel.pricing?.prompt) ?? 0,
outputPrice: parsePrice(rawModel.pricing?.completion) ?? 0,
cacheWritesPrice: parsePrice(rawModel.pricing?.input_cache_write),
@@ -106,7 +110,7 @@ export async function refreshOpenRouterModels(controller: Controller): Promise<R
description: rawModel.description ?? "",
// If thinking is supported, set maxBudget with a default value as a placeholder
// to ensure it has a valid thinkingConfig that lets the application know thinking is supported.
thinkingConfig: supportThinking ? { maxBudget: ANTHROPIC_MAX_THINKING_BUDGET } : undefined,
thinkingConfig: supportsReasoning ? { maxBudget: ANTHROPIC_MAX_THINKING_BUDGET } : undefined,
supportsGlobalEndpoint: rawModel.supports_global_endpoint ?? undefined,
tiers: rawModel.tiers ?? undefined,
}
+2
View File
@@ -242,6 +242,8 @@ export interface ModelInfo {
outputPriceTiers?: PriceTier[] // Optional: Tiered output price when budget > 0
}
supportsGlobalEndpoint?: boolean // Whether the model supports a global endpoint with Vertex AI
supportsTemperature?: boolean // Whether the model supports temperature parameter
supportsReasoning?: boolean // Whether the model is a reasoning model
cacheWritesPrice?: number
cacheReadsPrice?: number
description?: string
@@ -56,6 +56,8 @@ export function fromProtobufModelInfo(protoInfo: OpenRouterModelInfo): ModelInfo
thinkingConfig: convertThinkingConfig(protoInfo.thinkingConfig),
supportsGlobalEndpoint: protoInfo.supportsGlobalEndpoint,
tiers: protoInfo.tiers.length > 0 ? protoInfo.tiers : undefined,
supportsReasoning: protoInfo.supportsReasoning,
supportsTemperature: protoInfo.supportsTemperature,
}
}
@@ -76,6 +78,8 @@ export function toProtobufModelInfo(modelInfo: ModelInfo): OpenRouterModelInfo {
thinkingConfig: toProtobufThinkingConfig(modelInfo.thinkingConfig),
supportsGlobalEndpoint: modelInfo.supportsGlobalEndpoint,
tiers: modelInfo.tiers || [],
supportsReasoning: modelInfo.supportsReasoning,
supportsTemperature: modelInfo.supportsTemperature,
})
}