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:
parent
63307c70be
commit
2c14ec09b2
1 changed files with 63 additions and 1 deletions
|
|
@ -2561,6 +2561,7 @@ def create_app(
|
||||||
|
|
||||||
adapter = app.state.adapters[provider]
|
adapter = app.state.adapters[provider]
|
||||||
client: httpx.Client = app.state.clients[provider]
|
client: httpx.Client = app.state.clients[provider]
|
||||||
|
oauth_token = os.environ.get("ANTHROPIC_AUTH_TOKEN")
|
||||||
|
|
||||||
request_id = str(uuid.uuid4())
|
request_id = str(uuid.uuid4())
|
||||||
started = time.perf_counter()
|
started = time.perf_counter()
|
||||||
|
|
@ -2572,6 +2573,68 @@ def create_app(
|
||||||
session.token_state["model"] = req.model
|
session.token_state["model"] = req.model
|
||||||
duplication_score = _duplication_score(req)
|
duplication_score = _duplication_score(req)
|
||||||
outgoing_body = adapter.denormalize_request(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":
|
if endpoint == "count_tokens":
|
||||||
outgoing_body.pop("stream", None)
|
outgoing_body.pop("stream", None)
|
||||||
outgoing_body.pop("max_tokens", None)
|
outgoing_body.pop("max_tokens", None)
|
||||||
|
|
@ -2590,7 +2653,6 @@ def create_app(
|
||||||
# Anthropic requires specific beta headers and a Claude-CLI-style
|
# Anthropic requires specific beta headers and a Claude-CLI-style
|
||||||
# user-agent for OAuth Bearer auth to be accepted.
|
# user-agent for OAuth Bearer auth to be accepted.
|
||||||
# Ref: rmk40/opencode-anthropic-auth request-headers.mjs
|
# Ref: rmk40/opencode-anthropic-auth request-headers.mjs
|
||||||
oauth_token = os.environ.get("ANTHROPIC_AUTH_TOKEN")
|
|
||||||
if oauth_token and provider == "anthropic":
|
if oauth_token and provider == "anthropic":
|
||||||
headers.pop("x-api-key", None)
|
headers.pop("x-api-key", None)
|
||||||
headers.pop("X-Api-Key", None)
|
headers.pop("X-Api-Key", None)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue