From f900eb591df53485555a8bffa2dcb9416edc4c23 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 16 Jan 2026 12:41:23 +0100 Subject: [PATCH] Fix provider feature detection to use model.provider, not just URL Previously, OpenAI-compatible provider settings (like developer role support) were detected only from the baseUrl. When using custom URLs (e.g., proxies), detection failed. Now checks model.provider first, then falls back to URL. Fixes #774 --- packages/ai/CHANGELOG.md | 4 ++++ .../ai/src/providers/openai-completions.ts | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 65478df6..8f24f4d3 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed OpenAI-compatible provider feature detection to use `model.provider` in addition to URL, allowing custom base URLs (e.g., proxies) to work correctly with provider-specific settings ([#774](https://github.com/badlogic/pi-mono/issues/774)) + ## [0.47.0] - 2026-01-16 ### Fixed diff --git a/packages/ai/src/providers/openai-completions.ts b/packages/ai/src/providers/openai-completions.ts index 3edeca45..d194d7ab 100644 --- a/packages/ai/src/providers/openai-completions.ts +++ b/packages/ai/src/providers/openai-completions.ts @@ -679,25 +679,33 @@ function mapStopReason(reason: ChatCompletionChunk.Choice["finish_reason"]): Sto } /** - * Detect compatibility settings from baseUrl for known providers. + * Detect compatibility settings from provider and baseUrl for known providers. + * Provider takes precedence over URL-based detection since it's explicitly configured. * Returns a fully resolved OpenAICompat object with all fields set. */ -function detectCompatFromUrl(baseUrl: string): Required { - const isZai = baseUrl.includes("api.z.ai"); +function detectCompat(model: Model<"openai-completions">): Required { + const provider = model.provider; + const baseUrl = model.baseUrl; + + const isZai = provider === "zai" || baseUrl.includes("api.z.ai"); const isNonStandard = + provider === "cerebras" || baseUrl.includes("cerebras.ai") || + provider === "xai" || baseUrl.includes("api.x.ai") || + provider === "mistral" || baseUrl.includes("mistral.ai") || baseUrl.includes("chutes.ai") || isZai || + provider === "opencode" || baseUrl.includes("opencode.ai"); - const useMaxTokens = baseUrl.includes("mistral.ai") || baseUrl.includes("chutes.ai"); + const useMaxTokens = provider === "mistral" || baseUrl.includes("mistral.ai") || baseUrl.includes("chutes.ai"); - const isGrok = baseUrl.includes("api.x.ai"); + const isGrok = provider === "xai" || baseUrl.includes("api.x.ai"); - const isMistral = baseUrl.includes("mistral.ai"); + const isMistral = provider === "mistral" || baseUrl.includes("mistral.ai"); return { supportsStore: !isNonStandard, @@ -715,10 +723,10 @@ function detectCompatFromUrl(baseUrl: string): Required { /** * Get resolved compatibility settings for a model. - * Uses explicit model.compat if provided, otherwise auto-detects from URL. + * Uses explicit model.compat if provided, otherwise auto-detects from provider/URL. */ function getCompat(model: Model<"openai-completions">): Required { - const detected = detectCompatFromUrl(model.baseUrl); + const detected = detectCompat(model); if (!model.compat) return detected; return {