From 9b78d475becf58cb33a3cd049672c15eda1017b3 Mon Sep 17 00:00:00 2001 From: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Date: Tue, 15 Sep 2026 15:39:58 -0300 Subject: [PATCH] fix(providers): stop zed-hosted claude-haiku-4-5 thinking from inflating max_tokens (#13364) zed-hosted's passthrough catalog exposes the short hyphenated id "claude-haiku-4-5", but modelSpecs' registered alias is the dotted "claude-haiku-4.5" - a spelling mismatch, not a missing spec. With no zed-hosted entry in PROVIDER_MODEL_ALIASES, capMaxOutputTokens() resolved no cap for this model, so fitThinkingToMaxTokens added the response headroom directly to the requested thinking budget (32000 + 131072 = 163072) instead of fitting under the real 64000 output cap - Zed's proxy rejects the inflated request. Same class of fix already applied for the "kiro" provider in the same table. Regression test: tests/unit/issue-13364-zed-hosted-haiku-thinking-inflation.test.ts Co-Authored-By: Claude Sonnet 5 --- ...364-zed-hosted-haiku-thinking-inflation.md | 1 + open-sse/services/model.ts | 8 ++++ ...ed-hosted-haiku-thinking-inflation.test.ts | 39 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 changelog.d/fixes/13364-zed-hosted-haiku-thinking-inflation.md create mode 100644 tests/unit/issue-13364-zed-hosted-haiku-thinking-inflation.test.ts diff --git a/changelog.d/fixes/13364-zed-hosted-haiku-thinking-inflation.md b/changelog.d/fixes/13364-zed-hosted-haiku-thinking-inflation.md new file mode 100644 index 000000000000..9b6ec3a649d5 --- /dev/null +++ b/changelog.d/fixes/13364-zed-hosted-haiku-thinking-inflation.md @@ -0,0 +1 @@ +- **fix(providers):** stop zed-hosted `claude-haiku-4-5` extended-thinking requests from inflating `max_tokens` past the model's real 64000 output cap (#13364) — thanks @ThiagoMafra-Integrare diff --git a/open-sse/services/model.ts b/open-sse/services/model.ts index ec0080ef8387..ad90495558b2 100644 --- a/open-sse/services/model.ts +++ b/open-sse/services/model.ts @@ -102,6 +102,14 @@ const PROVIDER_MODEL_ALIASES: ProviderModelAliasMap = { "claude-sonnet-4-5": "claude-sonnet-4.5", "claude-haiku-4-5": "claude-haiku-4.5", }, + // #13364: zed-hosted's passthrough catalog exposes short hyphenated Claude ids + // that don't match modelSpecs' dotted canonical alias, so capMaxOutputTokens() + // resolves no cap and thinking+tools requests inflate max_tokens unbounded. + // Scoped to claude-haiku-4-5 (the reported/reproduced model) — add Sonnet/Opus + // entries only once confirmed against the live Zed catalog. + "zed-hosted": { + "claude-haiku-4-5": "claude-haiku-4.5", + }, }; const CROSS_PROXY_MODEL_ALIASES: Record = { diff --git a/tests/unit/issue-13364-zed-hosted-haiku-thinking-inflation.test.ts b/tests/unit/issue-13364-zed-hosted-haiku-thinking-inflation.test.ts new file mode 100644 index 000000000000..43df02bb6ebe --- /dev/null +++ b/tests/unit/issue-13364-zed-hosted-haiku-thinking-inflation.test.ts @@ -0,0 +1,39 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { openaiToClaudeRequest } from "../../open-sse/translator/request/openai-to-claude.ts"; + +// #13364 — zed-hosted/claude-haiku-4-5: extended thinking + tools inflates +// max_tokens to 163072 (> Anthropic's real 64000 cap for this model), causing +// Zed's proxy to reject the request in-stream with: +// "max_tokens: 163072 > 64000, which is the maximum allowed number of +// output tokens for claude-haiku-4-5-20251001" +// +// Root cause: zed-hosted's passthrough catalog exposes the short hyphenated id +// "claude-haiku-4-5", but modelSpecs' registered alias for that model is the +// dotted "claude-haiku-4.5" — a spelling mismatch (not a missing spec) means +// capMaxOutputTokens() resolves no cap for zed-hosted, so fitThinkingToMaxTokens +// adds the requested budget instead of fitting it under the model's real ceiling. +test("zed-hosted/claude-haiku-4-5 thinking+tools must not inflate max_tokens past the real 64000 output cap", () => { + const body = { + model: "claude-haiku-4-5", + max_tokens: 16000, + reasoning_effort: "high", // what claude-to-openai produces for the client's budget_tokens:15999 + tools: [ + { + type: "function", + function: { name: "read_file", parameters: { type: "object", properties: {} } }, + }, + ], + messages: [{ role: "user", content: "hello" }], + }; + const credentials = { _provider: "zed-hosted" }; + + const result = openaiToClaudeRequest("claude-haiku-4-5", body, false, credentials); + const claudeHaiku45OutputCap = 64000; // src/shared/constants/modelSpecs.ts "claude-haiku-4-5-20251001" + + assert.ok( + (result.max_tokens as number) <= claudeHaiku45OutputCap, + `max_tokens (${result.max_tokens}) must not exceed the model's real output cap ` + + `(${claudeHaiku45OutputCap}) — Anthropic/Zed rejects the request otherwise` + ); +});