Commit Graph

13 Commits

Author SHA1 Message Date
sususu
b3ed702e3a fix(claude): harden OAuth identity and native routing 2026-08-03 14:47:26 +08:00
sususu
fa6bc77f28 fix(claude): decode stacked response encodings 2026-08-03 14:47:26 +08:00
sususu
f63a925d15 fix(claude): replay measured OAuth wire, Fast and diagnostic profiles
Align the remaining measured OAuth wire profiles, including the ordered
connection writer in internal/httpwire that reproduces the observed header
sequence, and the refresh/profile response shapes in internal/auth/claude.

Replay the measured Fast path and keep diagnostic continuity across cloaked and
native requests.

Preserve the native direct token-counting shape so a caller that reaches
count_tokens itself is not reshaped into the cloaked form.

Scope cloak dates to the credential's timezone rather than the host's, so
currentDate matches what the real client would have sent for that account.
2026-08-03 14:47:26 +08:00
sususu
a20626f1ee fix(claude): send Anthropic header names with the real client's casing
CPA negotiates ALPN http/1.1 with Anthropic, so header names are not lowercased
by HPACK and reach the server verbatim. The casing is therefore part of the
fingerprint, and six of the eighteen names CPA emits were wrong because Go
canonicalises everything passed through Header.Set: anthropic-beta,
anthropic-dangerous-direct-browser-access, anthropic-version, x-app,
x-client-request-id and X-Stainless-OS. Writing the map keys directly is the
only way to keep the original casing.

This also fixes ordering at no extra cost. Go sorts header names bytewise when
it serialises a request, and the captured order of the real client is exactly
that same bytewise sort. Host, User-Agent and Content-Length stay misplaced
because Go writes them ahead of the sorted block; a test records that gap and
will fail if it ever closes.

The pass runs at the send boundary rather than inside applyClaudeHeaders: the
rewritten keys are unreachable through Header.Get, and doing it earlier hid
these headers from the rest of the pipeline. The boundary is a single
doClaudeUpstreamRequest helper pinned by a structural test, after a mutation
check showed that dropping the call from the streaming path alone was otherwise
undetectable. Expected order is pinned by serialising the request and reading
the header lines back, not by inspecting the header map.
2026-08-03 14:47:26 +08:00
sususu
6912a74064 fix(claude): keep a fast-mode refusal request-scoped
An account without the fast-mode entitlement answers speed:"fast" with HTTP 429
and "Usage credits are required for fast mode." The generic pipeline treats any
429 as quota exhaustion: it marks the credential Quota.Exceeded, assigns an
exponential cooldown up to 30 minutes and rotates to the next credential, so a
single request could walk and cool down the entire Claude pool over a
capability the account will never have.

Classify it through the existing RequestScopedError contract instead, which
already suppresses cooldown, rotation and retry. The status and body are then
returned verbatim: the classifier exists to stop the generic pipeline from
handling the error, not to handle it.

Detection deliberately requires both "fast mode" and a credits phrase, so a
genuine rate limit, which never mentions fast mode, keeps its cooldown. Tests
cover both observed wordings, byte-exact pass-through, and the negative cases.
2026-08-03 14:47:26 +08:00
sususu
a2933c7737 fix(claude): scope Anthropic beta and count_tokens policies
Claude Code builds Anthropic-Beta per request instead of sending a fixed list.
Captured from an isolated 2.1.220 profile pointed at api.anthropic.com through
a local proxy, over two rounds covering 11 model IDs and the [1m] variants:

  constant  claude-code, interleaved-thinking, redact-thinking,
            thinking-token-count, context-management, prompt-caching-scope
  tools     advanced-tool-use-2025-11-20 only when tools are declared
  model     mid-conversation-system-2026-04-07 only on models that accept a
            role=system turn
  [1m]      context-1m-2025-08-07, directly after claude-code-20250219 rather
            than at the end
  trailing  effort-2025-11-24, then server-side-fallback-2026-06-01

claude-sonnet-5 emits mid-conversation-system-2026-04-07, so it accepts a
role=system turn and must not sit in the legacy reminder whitelist.

count_tokens does not reuse the inference fingerprint. Running /context in an
interactive session issues 37 identical calls, which made the endpoint
observable for the first time: four betas only, and 21 headers rather than 22
because X-Stainless-Timeout is absent. The profile is selected from the request
path so no call site has to thread another flag.
2026-08-03 14:47:26 +08:00
sususu
f3e25ab2ba feat(claude): align OAuth wire identity and TLS with Claude Code 2.1.220
Detect confirmed CLI, sdk-cli and VSCode callers before mutation so native
software, system, tool, cache and beta shapes pass through, while unconfirmed
OAuth clients receive a coherent minimum CLI identity.

Persist each Claude OAuth credential's upstream account metadata and one stable
device ID, derive one stable session per agent conversation, and keep body and
header identity synchronized across Messages, streaming and count_tokens.

Alias every cloaked third-party custom tool through caller-stable opaque MCP
names and restore declarations, choices, history, references, non-stream
responses and SSE events without changing tool ownership.

Implement the Claude Code 2.1.220 CCH algorithm over the final serialized
request bytes, align currentDate and first-user cache layout, update the
official beta/header baseline, and use upstream count_tokens for OAuth and
first-party Anthropic credentials.

Match the 2.1.220 TLS ClientHello so the transport fingerprint agrees with the
identity the request now claims, and document the CLI defaults and automatic
OAuth signing / tool alias behaviour in config.example.yaml.
2026-08-03 14:47:26 +08:00
Luis Pater
3d4e160495 feat(executor): add conditional support for Claude fast mode beta
- Introduced `claudeFastModeBeta` constant and logic to append it conditionally based on the `speed` attribute in the request body.
- Ensured `fast-mode-2026-02-01` beta inclusion only when explicitly requested or if the `speed` is set to `fast`.
- Updated `applyClaudeHeaders` to dynamically handle fast-mode beta and adjust headers accordingly.
- Enhanced beta extraction and addition with a new helper `appendClaudeFastModeBeta`.
- Improved flexibility in beta handling by preserving requested overrides while ensuring compatibility with default configurations.

Closes: #4703
2026-08-01 10:17:36 +08:00
sususu
b3046d29b9 feat(thinking): preserve cross-protocol summary visibility 2026-07-30 21:53:30 +08:00
Luis Pater
f32291436a refactor(executor): consolidate thinking.ApplyThinking into helps.ApplyRequestThinking
- Replaced instances of `thinking.ApplyThinking` with `helps.ApplyRequestThinking` across all executors for consistency.
- Updated `applyGeminiInteractionsThinking` to accept `cliproxyexecutor.Request` and `Options`.
- Centralized logic for request thinking application to `helps` package for improved maintainability.

Closes: #4618
2026-07-29 14:14:18 +08:00
Randi
c405398a48 fix: align Claude headers with upstream streaming 2026-07-27 19:07:57 -04:00
cyclopentadiene6
08e5515703 fix(executor): restore OAuth tool names from SSE responses 2026-07-26 23:28:18 +10:00
Luis Pater
fe4ae4989c chore(pluginhost): refactor and remove unused interceptors and executor methods
- Removed deprecated interceptor and executor-related methods, including `callRequestInterceptor`, `callResponseInterceptor`, and `callStreamChunkInterceptor`.
- Consolidated unused logic and pruned redundant imports to streamline `adapters.go`.
- No functional changes.
2026-07-26 14:31:45 +08:00