Skip to content

fix(core): align request fidelity with genuine Claude Code CLI (2.1.177)#75

Open
iceteaSA wants to merge 3 commits into
cortexkit:mainfrom
iceteaSA:fix/claude-code-cli-fidelity
Open

fix(core): align request fidelity with genuine Claude Code CLI (2.1.177)#75
iceteaSA wants to merge 3 commits into
cortexkit:mainfrom
iceteaSA:fix/claude-code-cli-fidelity

Conversation

@iceteaSA

@iceteaSA iceteaSA commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Aligns the plugin's Anthropic request fingerprint with genuine Claude Code interactive-CLI traffic, captured + live-verified via MITM on 2026-06-14. Three independently-reviewed commits.

1. anthropic-beta correctness (packages/core/src/claude-code.ts)

  • Removed context-1m-2025-08-07 and effort-2025-11-24 from the full-agent set — verified: context-1m returns 400 "long context beta is not yet available for this subscription" on Max.
  • Added thinking-token-count-2026-05-13 as always-on (BASE/FULL/structured).
  • Added advanced-tool-use-2025-11-20 + extended-cache-ttl-2025-04-11 to BASE (genuine simple turns send them).
  • Reordered both sets to the captured sequence: lead with oauth-2025-04-20; claude-code-20250219 sits after prompt-caching-scope-2026-01-05 and only on tool-bearing turns.
  • Deliberate divergence: redact-thinking-2026-02-12 is intentionally NOT sent (product decision), even though genuine CLI includes it. A test pins its absence.

2. OAuth refresh + login fidelity (packages/core/src/{constants,auth}.ts)

  • axios/1.13.6axios/1.15.2 (extracted to AXIOS_USER_AGENT), on both refresh and code-exchange.
  • Refresh: Accept: application/json, text/plain, */* + body scope (REFRESH_SCOPE, which omits org:create_api_key — matches genuine refresh; login keeps it).
  • AUTHORIZE_URLS.maxhttps://claude.com/cai/oauth/authorize (genuine post-rebrand host; verified 307→claude.ai preserving PKCE code_challenge/state).

3. Interactive-CLI identity (packages/core/src/constants.ts)

All-or-nothing fingerprint swap from the Agent-SDK persona to the interactive CLI:

  • USER_AGENTclaude-cli/2.1.177 (external, cli), CLAUDE_CODE_VERSION2.1.177, CLAUDE_CODE_BUILD_HASH3bf, CLAUDE_CODE_ENTRYPOINTcli, identity → "You are Claude Code, Anthropic's official CLI for Claude."
  • Emitted billing header is now cc_version=2.1.177.3bf; cc_entrypoint=cli. cch signing mechanism untouched.
  • ⚠️ 3bf is a per-build hash that churns; re-confirm against a fresh capture on future bumps.

Test isolation fix (index.test.ts)

The provider.models suite read the real ~/.config/opencode/anthropic-auth.json instead of an isolated temp file, so the cost-zeroing test failed on any machine that opted out of cost-zeroing (passed only in clean CI). Added beforeEach/afterEach config isolation mirroring the auth.loader block.

Testing

  • bun run build / bun run typecheck clean
  • bun test: 496 pass / 0 fail
  • Cross-family independent review: correctness + security, both APPROVED for all three commits

Out of scope

  • cch signing internals (unchanged), the full Claude Code system-prompt body (only the identity block gates OAuth), any "cowork route" for quota (verified dead-end — same unified pool).

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Aligns our Anthropic request and identity to the genuine Claude Code interactive CLI 2.1.177 for higher fidelity and fewer auth/feature mismatches. Updates beta headers, OAuth requests, and CLI identity; fixes flaky test config isolation.

  • Bug Fixes

    • Betas: reordered to start with oauth-2025-04-20; added thinking-token-count-2026-05-13; moved claude-code-20250219 after prompt-caching-scope-2026-01-05 only on tool turns; added advanced-tool-use-2025-11-20 and extended-cache-ttl-2025-04-11 to BASE; removed context-1m-2025-08-07 and effort-2025-11-24; intentionally omit redact-thinking-2026-02-12.
    • OAuth: refresh/login use Accept: application/json, text/plain, */* and AXIOS_USER_AGENT (axios/1.15.2); refresh body includes scope (REFRESH_SCOPE); AUTHORIZE_URLS.max now https://claude.com/cai/oauth/authorize.
    • Identity: switch to CLI persona (USER_AGENT claude-cli/2.1.177 (external, cli); CLAUDE_CODE_VERSION=2.1.177, CLAUDE_CODE_BUILD_HASH=3bf, CLAUDE_CODE_ENTRYPOINT=cli); system identity updated; billing header now uses cc_entrypoint=cli.
  • Tests

    • Isolated provider.models from real user config (temp files in beforeEach/afterEach).
    • Updated snapshots and expectations for new headers, identity text, and URLs.

Written for commit 18c4649. Summary will update on new commits.

Review in cubic

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iceteaSA has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 10 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant Plugin as OpenCode Plugin
    participant Core as anthropic-auth-core
    participant Constants as Constants Module
    participant Betas as Beta Selector
    participant Identity as Identity Builder
    participant HTTP as Fetch / Axios
    participant API as Anthropic API

    Note over Plugin,API: Claude Code Interactive-CLI Request Fidelity

    Plugin->>Core: request LLM completion
    Core->>Constants: read fingerprint constants
    Constants-->>Core: USER_AGENT, CLAUDE_CODE_VERSION, etc.

    Core->>Betas: selectClaudeCodeBetas(request)
    alt Full agent turn (tools present)
        Betas->>Betas: build FULL beta set
        Note over Betas: oauth-2025-04-20<br/>interleaved-thinking-2025-05-14<br/>thinking-token-count-2026-05-13<br/>context-management-2025-06-27<br/>prompt-caching-scope-2026-01-05<br/>claude-code-20250219<br/>advisor-tool-2026-03-01<br/>advanced-tool-use-2025-11-20<br/>extended-cache-ttl-2025-04-11<br/>cache-diagnosis-2026-04-07
    else Structured output turn
        Betas->>Betas: build STRUCTURED beta set
        Note over Betas: oauth-2025-04-20<br/>interleaved-thinking-2025-05-14<br/>thinking-token-count-2026-05-13<br/>context-management-2025-06-27<br/>prompt-caching-scope-2026-01-05<br/>advisor-tool-2026-03-01<br/>structured-outputs-2025-12-15
    else Simple turn (no tools)
        Betas->>Betas: build BASE beta set
        Note over Betas: oauth-2025-04-20<br/>interleaved-thinking-2025-05-14<br/>thinking-token-count-2026-05-13<br/>context-management-2025-06-27<br/>prompt-caching-scope-2026-01-05<br/>advisor-tool-2026-03-01<br/>advanced-tool-use-2025-11-20<br/>extended-cache-ttl-2025-04-11<br/>cache-diagnosis-2026-04-07
    end
    Betas-->>Core: beta header string

    Core->>Identity: build system identity
    Identity-->>Core: "You are Claude Code, Anthropic's official CLI for Claude."

    Core->>Core: compute billing header
    Note over Core: cc_version=2.1.177.3bf<br/>cc_entrypoint=cli

    Core->>HTTP: POST /messages
    Note over HTTP: anthropic-beta: <selected betas><br/>user-agent: claude-cli/2.1.177 (external, cli)<br/>x-claude-code-session-id: <uuid>

    HTTP-->>Core: response

    Note over Plugin,API: OAuth Token Refresh

    Plugin->>Core: refreshClaudeOAuthToken(refreshToken)
    Core->>HTTP: POST /v1/oauth/token
    Note over HTTP: Accept: application/json, text/plain, */*<br/>User-Agent: axios/1.15.2
    Note over HTTP: body: grant_type=refresh_token<br/>refresh_token=<token><br/>client_id=9d1c250a-...<br/>scope=user:profile user:inference ...

    HTTP-->>Core: token response
    Core-->>Plugin: new access token

    Note over Plugin,API: OAuth Authorize Flow

    Plugin->>Core: authorize(provider="max")
    Core->>Constants: get AUTHORIZE_URLS.max
    Constants-->>Core: https://claude.com/cai/oauth/authorize
    Core->>Core: generate PKCE challenge
    Core-->>Plugin: { url, verifier }

    Plugin->>HTTP: GET https://claude.com/cai/oauth/authorize?...
    Note over HTTP: 307 redirect preserves PKCE params
    HTTP-->>API: redirected to claude.ai/oauth/authorize
    API-->>Plugin: auth page

    Note over Plugin,API: Bootstrap Session

    Plugin->>Core: bootstrapCLI(entrypoint="cli")
    Core->>HTTP: GET /api/claude_cli/bootstrap?entrypoint=cli&model=...
    Note over HTTP: user-agent: claude-code/2.1.177<br/>anthropic-beta: oauth-2025-04-20
    HTTP-->>Core: session config
Loading

Re-trigger cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant