feat: add Claude Code identity transforms for standalone OAuth usage

When proxying with OAuth (no auth plugin), applies the same body
transforms as opencode-anthropic-auth:
- Prepend 'You are Claude Code' identity to system prompt
- Replace 'OpenCode' with 'Claude Code' in system text
- Prefix tool names with 'mcp_' in tools and tool_use blocks
These are only applied when ANTHROPIC_AUTH_TOKEN is set.
This commit is contained in:
Joey Yakimowich-Payne 2026-03-19 07:19:25 -06:00
commit 2c14ec09b2

View file

@ -2561,6 +2561,7 @@ def create_app(
adapter = app.state.adapters[provider]
client: httpx.Client = app.state.clients[provider]
oauth_token = os.environ.get("ANTHROPIC_AUTH_TOKEN")
request_id = str(uuid.uuid4())
started = time.perf_counter()
@ -2572,6 +2573,68 @@ def create_app(
session.token_state["model"] = req.model
duplication_score = _duplication_score(req)
outgoing_body = adapter.denormalize_request(req)
# When proxying for OAuth (no auth plugin doing transforms),
# apply Claude Code identity transforms to the outbound body.
# Ref: rmk40/opencode-anthropic-auth transformRequestBody()
if oauth_token and provider == "anthropic":
_CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude."
system = outgoing_body.get("system")
if isinstance(system, list):
# Strip "OpenCode" identity line, replace OpenCode→Claude Code
for i, item in enumerate(system):
if isinstance(item, dict) and item.get("type") == "text" and item.get("text"):
import re as _re_sys
text = item["text"]
text = _re_sys.sub(
r"^You are OpenCode, the best coding agent on the planet\.\n*",
"",
text,
flags=_re_sys.MULTILINE,
)
text = text.replace("OpenCode", "Claude Code")
text = _re_sys.sub(
r"(?<!/)opencode", "Claude", text, flags=_re_sys.IGNORECASE
)
system[i] = {**item, "text": text}
# Prepend Claude Code identity if not already there
has_identity = any(
isinstance(s, str) and s == _CLAUDE_CODE_IDENTITY for s in system
)
if not has_identity:
system.insert(0, _CLAUDE_CODE_IDENTITY)
elif isinstance(system, str):
system = system.replace("OpenCode", "Claude Code")
if not system.startswith(_CLAUDE_CODE_IDENTITY):
system = f"{_CLAUDE_CODE_IDENTITY}\n{system}"
outgoing_body["system"] = system
# Prefix tool names with mcp_
tools = outgoing_body.get("tools")
if isinstance(tools, list):
for tool in tools:
if (
isinstance(tool, dict)
and tool.get("name")
and not tool["name"].startswith("mcp_")
):
tool["name"] = f"mcp_{tool['name']}"
# Prefix tool_use names in messages
messages = outgoing_body.get("messages")
if isinstance(messages, list):
for msg in messages:
content = msg.get("content")
if isinstance(content, list):
for block in content:
if (
isinstance(block, dict)
and block.get("type") == "tool_use"
and block.get("name")
and not block["name"].startswith("mcp_")
):
block["name"] = f"mcp_{block['name']}"
if endpoint == "count_tokens":
outgoing_body.pop("stream", None)
outgoing_body.pop("max_tokens", None)
@ -2590,7 +2653,6 @@ def create_app(
# 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)