Skip to content

fix(claude): align beta assembly and Haiku helper detection with the 2.1.258 baseline - #5412

Open
HYEONMIN94 wants to merge 5 commits into
router-for-me:devfrom
HYEONMIN94:feat/claude-fable-5-1
Open

fix(claude): align beta assembly and Haiku helper detection with the 2.1.258 baseline#5412
HYEONMIN94 wants to merge 5 commits into
router-for-me:devfrom
HYEONMIN94:feat/claude-fable-5-1

Conversation

@HYEONMIN94

@HYEONMIN94 HYEONMIN94 commented Sep 2, 2026

Copy link
Copy Markdown

dev now advertises Claude Code 2.1.258 as the default baseline, which clears the version gate for claude-fable-5-1. The per-request Anthropic-Beta assembly, the Haiku helper detection and the count_tokens profile still follow the 2.1.220 measurements, so the outgoing fingerprint is User-Agent 2.1.258 with a 2.1.220 body. This PR aligns those with a measured 2.1.258, and keeps the 2.1.220 policy for an operator who pins the baseline below 2.1.258.

Related to #5402.

How 2.1.258 was measured

ANTHROPIC_BASE_URL was pointed at a local capture server and the installed claude 2.1.258 binary was run on the interactive cli entrypoint and the -p (sdk-cli) entrypoint with an OAuth login. A Read of a large file and a Bash call were used to trigger the count_tokens pre-check and the Haiku helpers. The beta assembly order, the billing-header hash and the header conditions were cross-checked against the code inside the 2.1.258 bundle.

What changed compared to 2.1.220

  • advanced-tool-use-2025-11-20: previously sent whenever the request had tools; now sent only while tool search is active. A request carrying 158 tools without tool search had no such beta.
  • afk-mode-2026-01-31: new. Sits between fast-mode and extended-cache-ttl on auto-mode sessions.
  • Haiku helper betas: the session-title helper sends advisor-tool, structured-outputs when the account's advisor feature flag is on and cache diagnostics are off.
  • Haiku helper transport: X-Stainless-Async is never sent. Accept-Encoding is gzip, deflate, br, zstd for both the minimal and the structured helper. x-client-request-id is attached only when the base URL is api.anthropic.com, so a request that reaches the proxy never carries one.
  • Unchanged: runtime version, header casing, x-app, anthropic-version, the billing-header hash algorithm (the captured suffixes are reproduced), context_management, cache_control ttl, the metadata.user_id shape, the constant beta set and order, and count_tokens (five betas, body of model/messages/tools, no X-Stainless-Timeout).

Changes

  • internal/runtime/executor/claude_executor_request.go: advanced-tool-use is sent only when the body has a tool_search_tool_* tool, defer_loading, input_examples or allowed_callers, or when the caller requested it. afk-mode is forwarded at its measured position when the caller sends it, and advisor-tool stays ahead of it. Helper Accept-Encoding default and comments updated.
  • internal/runtime/executor/helps/claude_client_detection.go: new sequence in the helper beta allowlist. Helper transport checks follow 2.1.258 (no async header, one compression set, no request id on requests reaching the proxy).
  • internal/runtime/executor/helps/claude_device_profile.go: ClaudeBaselineUsesLegacyWire reports whether the configured claude-header-defaults baseline predates 2.1.258. The beta assembly and the helper transport checks use it to fall back to the measured 2.1.220 shape, so a pinned legacy baseline keeps a consistent fingerprint.
  • internal/runtime/executor/claude_executor_tokens.go, config.example.yaml: comments.
  • Tests: native-client fixtures moved to 2.1.258/0.112.1 (native detection requires an exact baseline match), beta matrix extended with the captured 2.1.258 header and tool-search / afk-mode cases, helper detection tests updated, legacy-baseline cases for the beta policy and the helper transport, registry test for claude-fable-5-1, captured billing fingerprint suffix pinned.

Verification

  • gofmt -l . clean, go build ./cmd/server, go test ./... pass on top of current dev.
  • Built from this branch and run with --local-model and a Claude OAuth credential:
    • a claude-fable-5-1 request returns 200 and the response model is claude-fable-5-1; claude-fable-5 still returns 200
    • a real Claude Code 2.1.258 pointed at the proxy through ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN responds normally in both -p and interactive mode, every request 200
    • with claude-header-defaults pinned to 2.1.220 / 0.94.0, the beta assembly and the helper transport checks return to the 2.1.220 shape (covered by tests)

Notes

  • 2.1.258 sends advisor-tool-2026-03-01 on every main-thread request when the account's advisor feature flag is on. That is account dependent, so the existing rule (only when requested or when the body declares an advisor tool) is kept.
  • 2.1.258 adds cc_prev_req= / cc_prompt_id= to the billing header, and a few headers, only when the base URL is api.anthropic.com. They cannot be observed through a custom base URL and are not synthesised here.

@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: 32b9d94eea

ℹ️ 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 +150 to +152
if requested[claudeAFKModeBeta] {
betas = append(betas, claudeAFKModeBeta)
}

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 Insert advisor beta before AFK mode

When a caller-owned or confirmed-native request supplies afk-mode-2026-01-31 and the body declares an advisor tool without already supplying the advisor beta, withClaudeAdvisorToolBeta does not recognize AFK as a later-position beta and therefore produces ...,afk-mode-2026-01-31,advisor-tool-2026-03-01. This contradicts the newly documented Claude Code wire order, where advisor precedes AFK, and defeats the exact fingerprint reconstruction this path is intended to provide; add AFK to that helper's insertion boundaries.

Useful? React with 👍 / 👎.

@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: 23528a4c37

ℹ️ 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 +289 to +295
if headerValue(headers, "X-Stainless-Async") != "" {
return false
}
compression := headerValue(headers, "Accept-Encoding")
if (shape == claudeCodeHelperShapeStructured && compression != "gzip, deflate, br, zstd") ||
(shape == claudeCodeHelperShapeMinimal && compression != "gzip") {
if headerValue(headers, "Accept-Encoding") != "gzip, deflate, br, zstd" {
return false
}
requestID := headerValue(headers, "X-Client-Request-Id")
_, errRequestID := uuid.Parse(requestID)
return errRequestID == nil
return headerValue(headers, "X-Client-Request-Id") == ""

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 Match helper transport to the configured baseline

When an operator pins claude-header-defaults to the previously supported 2.1.220/0.94.0 baseline, the software tuple passes meetsClaudeDeviceProfileBaseline, but genuine 2.1.220 helpers still carry a request UUID and use the older shape-specific compression/async headers. These unconditional 2.1.258 checks therefore reject every such markerless helper; because helpers omit claude-code-20250219, they have no standard-signal fallback and are classified as unconfirmed and cloaked. Select the transport checks from the configured baseline or retain acceptance of the measured 2.1.220 envelope.

Useful? React with 👍 / 👎.

@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: cc79527e06

ℹ️ 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 135 to 136
if requested[claudeAdvancedToolUseBeta] || claudeBodyUsesAdvancedToolUse(body) {
betas = append(betas, claudeAdvancedToolUseBeta)

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 beta assembly for configured legacy baselines

When an operator pins claude-header-defaults to the supported 2.1.220/0.94.0 baseline, the outgoing User-Agent and package headers use that legacy tuple, but claudeCodeCLIBetas still unconditionally applies 2.1.258 behavior here and omits advanced-tool-use-2025-11-20 for ordinary non-empty tool lists. This creates a mixed fingerprint that no 2.1.220 client emitted; the new helper-transport branch preserves the configured legacy envelope, but the main request beta assembly has no equivalent version selection. Choose the beta policy from the configured baseline as well.

Useful? React with 👍 / 👎.

@realies

realies commented Sep 2, 2026

Copy link
Copy Markdown

errors out with

● API Error: 400 messages.4: role 'system' must precede an 'assistant' message or end the array; the directive-only form (content: [] with output_config) is accepted at any position

@mardausdennis

Copy link
Copy Markdown
Contributor

chicken noodle soup chicken noodle

@realies

realies commented Sep 2, 2026

Copy link
Copy Markdown

Follow-up on the 400 I reported here: I traced it to base behaviour in the signature sanitizer, not to this PR. Claude Fable 5.1 emits a thinking-signature generation the CAIS validator does not recognise, so every thinking block is dropped, and a thinking-only assistant turn vanishes, which breaks the system-message placement rule. The fix is in a separate PR against dev: #5422. This PR is not at fault and is not blocked by it; the two were exercised together on a private build and work as expected.

…e measured Claude Code 2.1.258

The default baseline now advertises claude-cli/2.1.258 with
@anthropic-ai/sdk 0.112.1, but the per-request Anthropic-Beta assembly
and the Haiku helper detection still follow the 2.1.220 measurements,
so the outgoing fingerprint is one a real 2.1.258 never produces.

Align the Anthropic-Beta assembly with 2.1.258: advanced-tool-use-2025-11-20
is sent only while tool search or another advanced tool-use feature is
on the wire (or when the caller asks for it), and afk-mode-2026-01-31 is
forwarded between fast-mode and extended-cache-ttl when the caller sends it.

Re-measure the Haiku helper and count_tokens profiles on 2.1.258: add the
advisor-tool + structured-outputs helper sequence, stop expecting
X-Stainless-Async and x-client-request-id on helper requests (the SDK no
longer sends the former, and the latter is attached only on a first-party
base URL), and unify Accept-Encoding. count_tokens is unchanged.

Refresh the config.example.yaml baseline comments and the test fixtures;
add a registry test for claude-fable-5-1 and the captured 2.1.258 billing
fingerprint.
withClaudeAdvisorToolBeta did not treat afk-mode-2026-01-31 as an
insertion boundary, so a confirmed-native or caller-owned request that
carried afk-mode and declared an advisor tool without the advisor beta
ended up with "..., afk-mode, advisor-tool". Add afk-mode to the
boundaries and pin the order in a test.
… drop unused helper parameters

Place claude-fable-5-1 after claude-fable-5 and use the description from
the router-for-me/models catalog so the embedded fallback matches the
live one. Remove the shape parameter from
measuredClaudeCodeHelperHeadersMatch and the transport parameters from
the test header builders; they stopped varying once the 2.1.258 helper
envelope became a single shape.
…aseline

When an operator pins claude-header-defaults to 2.1.220, genuine 2.1.220
helpers still carry a UUID request id and the shape-specific async and
compression headers, so applying the 2.1.258 checks unconditionally
rejected every such helper and cloaked it. Check the measured 2.1.220
envelope when the baseline version is below 2.1.258 and the 2.1.258
envelope otherwise, and pin both cases in tests.
An operator who pins claude-header-defaults to 2.1.220 already gets the
2.1.220 helper transport checks, but the main-request beta assembly
still applied the 2.1.258 policy and dropped advanced-tool-use from
ordinary tool lists, producing a fingerprint no 2.1.220 client emitted.
Move the version split into a shared helper, let claudeCodeCLIBetas
emit the 2.1.220 policy (advanced-tool-use with any non-empty tool
list, no afk-mode) below 2.1.258, and use the same split for the helper
Accept-Encoding fallback. The helper beta sequence first observed on
2.1.258 is not accepted under an older baseline, and
config.example.yaml documents the behaviour.
@HYEONMIN94
HYEONMIN94 force-pushed the feat/claude-fable-5-1 branch from c6ba1aa to 1fbbda8 Compare September 3, 2026 08:44
@HYEONMIN94 HYEONMIN94 changed the title feat(claude): add claude-fable-5-1 and measure the Claude Code 2.1.258 baseline fix(claude): align beta assembly and Haiku helper detection with the 2.1.258 baseline Sep 3, 2026
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.

3 participants