mpfaffenberger / mpfaffenberger/code_puppy
ClaudeCacheAsyncClient applies Claude-Code-OAuth header/URL transforms unconditionally — vanilla anthropic/custom_anthropic requests get claude-cli UA, oauth beta flags, ?beta=true; x-api-key removal is a no-op
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 814
- Forks
- 278
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 76
Description
Problem
ClaudeCacheAsyncClient.send() (code_puppy/claude_cache_client.py, lines ~318-345) applies the Claude Code OAuth transformations to every request hitting /v1/messages, regardless of whether the client belongs to an OAuth model:
if is_messages_endpoint:
...
# 1. Transform headers for Claude Code OAuth
self._transform_headers_for_claude_code(headers)
headers_modified = True
# 2. Add ?beta=true query param
url = self._add_beta_query_param(url)
But model_factory.py also uses ClaudeCacheAsyncClient for the plain anthropic (line ~590) and custom_anthropic (line ~640) model types — API-key based, no OAuth. For those models every request now gets:
user-agent: claude-cli/2.1.2 (external, cli)(misrepresents the client to Anthropic),anthropic-beta: oauth-2025-04-20,interleaved-thinking-2025-05-14,...force-injected (these beta flags are OAuth/Claude-Code specific and override the carefully constructed_build_anthropic_beta_header()defaults),?beta=trueappended to the URL.
Only the tool-name prefixing and httpx-level cache injection are correctly gated behind the _apply_claude_code_prefix constructor flag; the header/URL transforms are not.
Bonus bug: x-api-key removal is a silent no-op
_transform_headers_for_claude_code deletes x-api-key from the local headers dict, but the rebuild logic only sets headers back:
# Update headers
for key, value in headers.items():
request.headers[key] = value
Deletions are never propagated to request.headers, so the removal does nothing. (This is accidentally what saves vanilla anthropic auth from breaking today — the API key survives only because the delete silently fails.) Either intent or implementation is wrong; right now both are.
Suggested fix
Gate steps 1-2 behind the same opt-in flag as the prefixing:
if is_messages_endpoint and self._apply_claude_code_prefix:
self._transform_headers_for_claude_code(headers)
url = self._add_beta_query_param(url)
and, when rebuilding, replace the header set wholesale (e.g. request.headers = httpx.Headers(headers)) so deletions actually take effect.
Filed by Zen Reviewer A (code-puppy-60635a)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in code_puppy/claude_cache_client.py at ClaudeCacheAsyncClient.send() and inspect how _apply_claude_code_prefix controls request handling. Verify that OAuth header and URL transforms apply only when that flag is enabled, and that rebuilding request headers propagates deletions. Done means vanilla anthropic and custom_anthropic requests retain their normal headers and URL while OAuth requests keep the intended transforms.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100