fix: update OAuth headers and betas to match Claude CLI 2.1.75

Updated from the rmk40/opencode-anthropic-auth plugin profile.
Adds all required beta headers (claude-code, context-1m, interleaved
thinking, redact-thinking, prompt-caching-scope, advanced-tool-use,
effort), opus-specific context-management beta, ?beta=true URL param,
and correct user-agent/x-app headers.
This commit is contained in:
Joey Yakimowich-Payne 2026-03-19 07:07:48 -06:00
commit 63307c70be

View file

@ -2587,24 +2587,43 @@ def create_app(
}
# OAuth: replace dummy x-api-key with Bearer token when available.
# Anthropic requires the "oauth-2025-04-20" beta header and a
# Claude-CLI-style user-agent for OAuth Bearer auth to be accepted.
# See: treplay/server.mjs proxyAnthropicContinuation()
# Anthropic requires specific beta headers and a Claude-CLI-style
# user-agent for OAuth Bearer auth to be accepted.
# Ref: rmk40/opencode-anthropic-auth request-headers.mjs
oauth_token = os.environ.get("ANTHROPIC_AUTH_TOKEN")
if oauth_token and provider == "anthropic":
headers.pop("x-api-key", None)
headers.pop("X-Api-Key", None)
headers["authorization"] = f"Bearer {oauth_token}"
# Beta flag is REQUIRED — without it, Anthropic returns
# "OAuth authentication is currently not supported"
# Required beta flags — must match Claude CLI expectations.
_OAUTH_BETAS = [
"claude-code-20250219",
"oauth-2025-04-20",
"context-1m-2025-08-07",
"interleaved-thinking-2025-05-14",
"redact-thinking-2026-02-12",
"prompt-caching-scope-2026-01-05",
"advanced-tool-use-2025-11-20",
"effort-2025-11-24",
]
# Add opus-specific betas if model is opus
model_name = req.model.lower() if req.model else ""
if "opus" in model_name:
_OAUTH_BETAS.append("context-management-2025-06-27")
existing_beta = headers.get("anthropic-beta", "")
oauth_beta = "oauth-2025-04-20"
if oauth_beta not in existing_beta:
if existing_beta:
headers["anthropic-beta"] = f"{existing_beta},{oauth_beta}"
else:
headers["anthropic-beta"] = oauth_beta
headers["user-agent"] = "claude-cli/2.1.2 (external, cli)"
existing_set = set(b.strip() for b in existing_beta.split(",") if b.strip())
merged = list(dict.fromkeys(list(existing_set) + _OAUTH_BETAS)) # preserve order, dedup
headers["anthropic-beta"] = ",".join(merged)
headers["user-agent"] = "claude-cli/2.1.75 (external, cli)"
headers.setdefault("anthropic-dangerous-direct-browser-access", "true")
headers.setdefault("x-app", "cli")
# Add ?beta=true to /v1/messages URL
if endpoint == "messages" and "beta=true" not in upstream_path:
sep = "&" if "?" in upstream_path else "?"
upstream_path = f"{upstream_path}{sep}beta=true"
if req.stream:
@ -2831,13 +2850,21 @@ def create_app(
oauth_token = os.environ.get("ANTHROPIC_AUTH_TOKEN")
if oauth_token:
headers["authorization"] = f"Bearer {oauth_token}"
existing_beta = headers.get("anthropic-beta", "")
oauth_beta = "oauth-2025-04-20"
if oauth_beta not in existing_beta:
headers["anthropic-beta"] = (
f"{existing_beta},{oauth_beta}" if existing_beta else oauth_beta
)
headers["user-agent"] = "claude-cli/2.1.2 (external, cli)"
headers["anthropic-beta"] = ",".join(
[
"claude-code-20250219",
"oauth-2025-04-20",
"context-1m-2025-08-07",
"interleaved-thinking-2025-05-14",
"redact-thinking-2026-02-12",
"prompt-caching-scope-2026-01-05",
"advanced-tool-use-2025-11-20",
"effort-2025-11-24",
]
)
headers["user-agent"] = "claude-cli/2.1.75 (external, cli)"
headers["anthropic-dangerous-direct-browser-access"] = "true"
headers["x-app"] = "cli"
else:
headers["x-api-key"] = api_key
url = f"https://api.anthropic.com/v1/{path}"