diff --git a/packages/ai/src/providers/anthropic.ts b/packages/ai/src/providers/anthropic.ts index 8bdd61662..2af158fe7 100644 --- a/packages/ai/src/providers/anthropic.ts +++ b/packages/ai/src/providers/anthropic.ts @@ -1870,15 +1870,17 @@ const streamAnthropicOnce = ( // `context_management.clear_thinking_20251015` requires this beta. OAuth // requests carry it in `claudeCodeAgentBetaDefaults`; API-key requests // need it added explicitly so the field is honored instead of rejected - // (#3288). Skip transports where this package cannot deliver the beta - // in the form their adapter accepts: Copilot strips Anthropic betas, - // and Vertex rawPredict needs betas in the body (`anthropic_beta`), - // not as an `anthropic-beta` HTTP header. + // (#3288). Skip transports where this package cannot deliver or the + // provider cannot accept the beta: Copilot strips Anthropic betas; + // Vertex rawPredict needs betas in the body (`anthropic_beta`), not as + // an `anthropic-beta` HTTP header; and OpenCode Zen rejects the related + // `context_management` field (#6510). if ( model.reasoning && options?.thinkingEnabled && model.provider !== "github-copilot" && model.provider !== "google-vertex" && + model.provider !== "opencode-zen" && !extraBetas.includes(contextManagementBeta) ) { extraBetas.push(contextManagementBeta); diff --git a/packages/ai/test/issue-6510-repro.test.ts b/packages/ai/test/issue-6510-repro.test.ts index 1385b9e33..e56921119 100644 --- a/packages/ai/test/issue-6510-repro.test.ts +++ b/packages/ai/test/issue-6510-repro.test.ts @@ -47,18 +47,26 @@ describe("issue #6510 — opencode-zen Anthropic auth + context_management", () expect(options.defaultHeaders.Authorization).toBeUndefined(); }); - it("omits context_management on Zen thinking requests", async () => { + it("omits context_management and its beta on Zen thinking requests", async () => { + let capturedBeta: string | null = null; + const fetchMock = (async (_input: string | URL | Request, init?: RequestInit) => { + capturedBeta = new Headers(init?.headers).get("anthropic-beta"); + return new Response( + JSON.stringify({ type: "error", error: { type: "invalid_request_error", message: "captured" } }), + { status: 400, headers: { "Content-Type": "application/json" } }, + ); + }) as typeof fetch; const { promise, resolve } = Promise.withResolvers(); - streamAnthropic( + await streamAnthropic( ZEN_ANTHROPIC_MODEL, { systemPrompt: [], messages: [{ role: "user", content: "continue", timestamp: 0 }] }, { apiKey: "sk-zen-test", - signal: AbortSignal.abort(), thinkingEnabled: true, + fetch: fetchMock, onPayload: payload => resolve(payload), }, - ); + ).result(); const payload = (await promise) as { thinking?: { type?: string }; @@ -66,5 +74,6 @@ describe("issue #6510 — opencode-zen Anthropic auth + context_management", () }; expect(payload.thinking?.type).toBe("enabled"); expect(payload.context_management).toBeUndefined(); + expect(capturedBeta ?? "").not.toContain("context-management-2025-06-27"); }); });