Skip to content

feat(claude): upgrade Claude Code 2.1.258 wire fingerprint and model behavioral parity - #5456

Open
sususu98 wants to merge 8 commits into
router-for-me:devfrom
sususu98:feat/claude-code-cli-fingerprint
Open

feat(claude): upgrade Claude Code 2.1.258 wire fingerprint and model behavioral parity#5456
sususu98 wants to merge 8 commits into
router-for-me:devfrom
sususu98:feat/claude-code-cli-fingerprint

Conversation

@sususu98

@sususu98 sususu98 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrade CPA's built-in Claude Code CLI wire fingerprint from 2.1.220 to 2.1.258, aligning request headers, body parameters, and session continuity with measured native wire behavior.

Key Changes

  1. P0 Billing Header Continuity Chain:

    • Align x-anthropic-billing-header strictly to the native Bun byte order: cc_version -> cc_entrypoint -> cch -> cc_workload -> cc_is_subagent -> cc_prev_req -> cc_prompt_id.
    • Link cc_prev_req to upstream request-id: req_... headers with continuity cache.
    • Enforce RFC 4122 UUIDv4 semantic validation for cc_prompt_id, with automatic healing for malformed/non-v4 IDs.
    • Isolate probe requests (max_tokens: 1) and side-queries to prevent session poisoning.
    • Pass incoming headers to claudeCCHFallbackBillingHeader to preserve subagent flags during CCH regeneration.
  2. P1 Dynamic Anthropic-Beta Pruning & Fallbacks:

    • Suppress effort-2025-11-24 on Haiku models, probe requests, and when thinking is disabled.
    • Add thinking-display-updates-2026-08-18 beta and automatically drop redact-thinking-2026-02-12 when thinking display is updates or summarized.
    • Auto-attach server-side-fallback-2026-06-01 whenever the body contains fallbacks.
    • Suppress extended-cache-ttl-2025-04-11 on subagents and probes.
  3. P2 Model Cloaking Parity:

    • Inject "fallbacks": [{"model": "claude-opus-5"}] and default display: updates when cloaking claude-fable-5-1.
    • Inject # Reporting outcomes as System[2] without cache control for Fable 5.1 / Mythos models when cloaking is enabled.
    • Retain complete pass-through for confirmed native Claude Code and when disable-claude-cloak-mode is true.
    • Fallback to ClaudeContinuityContext in claudeCCHFallbackBillingHeader when payload transformations strip billing tags.

Verification

  • Full test suites passing: go test -count=1 ./internal/runtime/executor/... and go test ./cmd/... ./internal/api/....
  • Live wire verification using Codex CLI and Pi coding agent against local mitmproxy interceptor on 38082/38081.
  • Clean compilation: go build -ldflags="-s -w" -o /dev/null ./cmd/server.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6861da0cac

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1141 to +1143
if strings.Contains(model, "fable") && !helps.IsClaudeProbeOrHelperRequest(payload) {
if !gjson.GetBytes(payload, "fallbacks").Exists() {
payload, _ = sjson.SetRawBytes(payload, "fallbacks", []byte(`[{"model":"claude-opus-5"}]`))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restrict fallback injection to Fable 5.1

When cloaking is enabled for the separately registered claude-fable-5 model, this substring check also injects fallbacks: [{"model":"claude-opus-5"}] and the server-side-fallback beta, even though the captured behavior documented immediately above is specific to claude-fable-5-1. If fallback is activated, a request for Fable 5 can silently execute as Opus 5; match the normalized Fable 5.1 model IDs rather than every model containing fable.

Useful? React with 👍 / 👎.

Comment on lines +164 to +169
explicitPromptID = strings.TrimSpace(explicitPromptID)
if explicitPromptID != "" && IsValidClaudePromptID(explicitPromptID) {
entry.promptID = strings.ToLower(explicitPromptID)
} else if isNewPromptTurn || entry.promptID == "" {
entry.promptID = uuid.NewString()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep prompt IDs scoped to their request generation

When two new prompt turns for the same credential/session overlap, the second BeginClaudeContinuity overwrites entry.promptID before either response commits. If the first response then completes and its tool continuation starts before the second completes (or after the second fails), the cache combines the first response's previousRequestID/previousMessageID with the second request's prompt ID. The prompt ID should be associated with the sequence and advanced atomically with that generation's successful commit.

Useful? React with 👍 / 👎.

Comment on lines +104 to +105
diagnosticsState := claudeDiagnosticsRequestState{}
isProbeOrHelper := helps.IsClaudeProbeOrHelperRequest(body)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve helper classification before replacing the system prompt

For a title helper recognized only by the system text containing Return a short title rather than by the exact output schema, applyCloaking initially recognizes it but then replaces that top-level system field. This post-cloaking check therefore returns false, causing diagnostics to be injected and committed for a request that is meant to be isolated; subsequent beta and Fable checks misclassify it as well. Compute the helper/probe classification from the pre-cloaking body and reuse it throughout the request.

Useful? React with 👍 / 👎.

Comment on lines +129 to +130
parsed, err := uuid.Parse(id)
return err == nil && parsed.Version() == 4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate the RFC 4122 variant of prompt UUIDs

For an incoming UUID such as 3c6489dc-badc-42b2-0d28-49f8ebabfedd, uuid.Parse succeeds and Version() is 4 even though the variant bits are not RFC 4122. This validator consequently accepts and forwards an identifier that contradicts its strict UUIDv4 contract instead of healing it; also require parsed.Variant() == uuid.RFC4122.

Useful? React with 👍 / 👎.

…int chain

- Assemble x-anthropic-billing-header strictly following official 2.1.258 binary order: cc_version, cc_entrypoint, cch, cc_workload, cc_is_subagent, cc_prev_req, and cc_prompt_id.
- Track upstream request-id (/^req_[A-Za-z0-9_-]{1,36}$/) in thread-safe, bounded session continuity state and inject into subsequent turns as cc_prev_req.
- Generate UUIDv4 cc_prompt_id per user prompt turn, preserving it across tool-use continuation loops while suppressing it on probes (max_tokens: 1) and title helpers.
- Detect subagents via agent headers or parent_session_id metadata and emit cc_is_subagent=true.
- Harmonize diagnostics and continuity lifecycles to prevent auxiliary/probe turns or truncated streams from corrupting conversation state.
- Add end-to-end multi-turn continuity and predicate tests in runtime executor.
…backs

- Gate effort-2025-11-24 so it is omitted on Haiku models, probe requests (max_tokens: 1), and when thinking is disabled.
- Add thinking-display-updates-2026-08-18 beta and emit it when thinking.display is updates.
- Automatically emit server-side-fallback-2026-06-01 when the body contains a fallbacks array.
- Suppress extended-cache-ttl-2025-04-11 on subagent and probe requests.
- Inject fallbacks: [{"model": "claude-opus-5"}] and set display: updates for claude-fable-5-1 during cloaking.
- Update and extend CLI betas matrix tests.
…ble models

- Add claudeCodeFableReportingOutcomes constant matching Claude Code 2.1.258 binary.
- Inject as System[2] without cache_control for fable and mythos models during cloaking.
- Retain passthrough behavior for confirmed native Claude Code and when cloaking is disabled.
- Add unit tests for Fable injection, non-Fable omission, DisableClaudeCloakMode, and native Claude Code.
…ty context fallback

- Validate cc_prompt_id strictly as RFC 4122 UUIDv4 in BeginClaudeContinuity and ExtractClaudeBillingTags.
- Sanitize and heal invalid or non-v4 prompt IDs by generating compliant UUIDv4 values instead of propagating malformed tags.
- Fallback to ClaudeContinuityContext in claudeCCHFallbackBillingHeader when payload rules or upstream transformations strip billing tags.
- Add comprehensive unit test suite for IsValidClaudePromptID.
…iant, probe isolation, and atomic prompt ID commit

- Restrict fallback injection and Reporting outcomes system block strictly to Fable 5.1 / Mythos 5.1 (isClaudeFable51Model), preventing unexpected Opus fallback on claude-fable-5.
- Require uuid.RFC4122 variant check in IsValidClaudePromptID to heal non-standard UUIDv4 variants.
- Compute isProbeOrHelper from pre-cloaking body to preserve title helper detection when system prompt is replaced.
- Make BeginClaudeContinuity return generation prompt ID without prematurely overwriting cached state, and commit prompt ID atomically in CommitClaudeContinuity.
@sususu98
sususu98 force-pushed the feat/claude-code-cli-fingerprint branch from 6861da0 to 7cfa992 Compare September 3, 2026 10:14

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7cfa992ffe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +157 to 158
if oauthToken && !helps.IsClaudeSubagentRequest(nil, body) && !helps.IsClaudeProbeOrHelperRequest(body) {
betas = append(betas, claudeExtendedCacheTTLBeta)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep the cache TTL paired with its beta

For OAuth cloaked subagent, probe, and title-helper requests, this new condition removes extended-cache-ttl-2025-04-11, but both Execute and ExecuteStream still call upgradeClaudeCacheControlTTL(..., "1h") whenever CPA owns cache placement and the credential uses the Claude Code profile. Because cloaking already installs a cache marker, these requests carry cache_control.ttl: "1h" without the beta required to enable it, breaking the pairing invariant and potentially causing Anthropic to reject the request; gate the TTL upgrade with the same request predicates or retain the beta.

Useful? React with 👍 / 👎.

…l beta

- Only upgrade cache_control TTL to 1h when the request is eligible for extended-cache-ttl-2025-04-11 (!isSubagent && !isProbeOrHelper).
- In native Claude Code 2.1.258, 1h cache is restricted to main interaction threads (repl_main_thread*), while subagents, probes, and side queries omit both the beta and 1h TTL.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d3dafe1f5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1148 to +1149
model := strings.ToLower(strings.TrimSpace(gjson.GetBytes(payload, "model").String()))
if isClaudeFable51Model(model) && !isProbeOrHelper {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Apply Fable additions after payload model overrides

When an operator uses a payload override to change model, this decision is made from the pre-override model because both Execute and ExecuteStream call ApplyPayloadConfigWithRequestTracked only after applyCloaking. Rewriting Fable 5.1 to another model therefore leaves its Opus fallback, thinking.display, and reporting system block attached, allowing an unexpected Opus fallback; rewriting another model to Fable 5.1 omits all of those required additions. Reconcile these model-dependent fields after payload rules have established the final upstream model.

Useful? React with 👍 / 👎.

…er payload model overrides

- When payload rules rewrite a request model across Fable 5.1 and non-Fable models, reconcile the Fable-exclusive fields (Opus fallback, thinking.display=updates, and # Reporting outcomes system block).
- Prevent sending unexpected Opus fallback or reporting outcomes on non-Fable models (e.g. Sonnet 5).
- Ensure required Fable 5.1 wire properties are attached when a model is rewritten to Fable 5.1.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fd4609144

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +157 to 158
if oauthToken && !helps.IsClaudeSubagentRequest(nil, body) && !helps.IsClaudeProbeOrHelperRequest(body) {
betas = append(betas, claudeExtendedCacheTTLBeta)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Prune the cache beta on confirmed subagent requests

When a confirmed native Claude Code subagent is forwarded using an OAuth credential, applyClaudeHeadersWithNativeProfile bypasses this rebuilt list, restores the caller's betas, and then calls withClaudeOAuthCredentialBetas, which unconditionally appends extended-cache-ttl-2025-04-11. Consequently, header-identified native subagents still receive the beta even though their body is left without the new 1h TTL; apply the subagent/probe predicate to the confirmed-client credential-restoration path as well.

Useful? React with 👍 / 👎.

Comment on lines +816 to +819
if !gjson.GetBytes(originalBody, "fallbacks").Exists() {
fallbacks := gjson.GetBytes(body, "fallbacks")
if fallbacks.IsArray() && len(fallbacks.Array()) == 1 && fallbacks.Array()[0].Get("model").String() == "claude-opus-5" {
body, _ = sjson.DeleteBytes(body, "fallbacks")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve explicit payload fallback overrides

When a payload rule changes Fable 5.1 to another model while explicitly retaining fallbacks: [{"model":"claude-opus-5"}], this branch deletes the configured fallback because originalBody predates both cloaking and ApplyPayloadConfigWithRequestTracked. The same provenance problem affects an explicit thinking.display: "updates" override below; track which fields were injected by cloaking or touched by payload rules rather than inferring ownership solely from their final values.

Useful? React with 👍 / 👎.

Comment on lines +209 to +211
if requestID != "" && claudeRequestIDPattern.MatchString(requestID) {
entry.previousRequestID = requestID
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear stale request IDs when a response has none

If a normal successful response lacks a valid request-id header—for example because an Anthropic-compatible gateway omits it—this commit advances previousMessageID and the prompt generation but leaves the prior response's previousRequestID intact. The next request then emits a stale cc_prev_req referring to an older response rather than omitting the unavailable immediate predecessor, producing an inconsistent continuity chain.

Useful? React with 👍 / 👎.

…ng, explicit fallback overrides, and stale request ID clearing

- Prune extended-cache-ttl beta for confirmed native Claude Code subagents and probes in withClaudeOAuthCredentialBetas.
- Track Fable field provenance and check payload rule overrides so explicit operator-configured fallbacks/display are never deleted.
- Clear previousRequestID in CommitClaudeContinuity when upstream response provides no valid request-id.
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