Sync upstream v7.2.73 → v7.2.140 (retire Patch 3, keep Patches 1/2/4) - #5
Merged
Conversation
A cloaked direct-Anthropic count_tokens request skipped applyCloaking entirely while still reporting cloaked=true, so two guarantees that hold on the Messages path were silently dropped on this endpoint: - configured sensitive words reached Anthropic verbatim, even though the same words are obfuscated on the Messages request - a third-party caller's system prompt was forwarded in the system slot, which measured Claude Code 2.1.220 count_tokens traffic never carries Skipping the full Messages cloaking is still correct here, because native count_tokens sends only model, messages and tools and must not gain the Claude Code system blocks. Apply the two parts that do have to hold instead: relocate the caller's system prompt into messages with the same positional mapping the Messages path uses, so its tokens stay counted without leaking it as a system prompt, and obfuscate sensitive words. Strict mode keeps dropping caller prompts, matching the Messages path.
Classify malformed caller metadata and Fast failures as request-scoped, reuse the strict Anthropic origin gate, bound diagnostics and proxy caches, and remove the unrelated translator test change.
Use advanced-tool-use for OAuth requests with tools and stop synthesizing cache-diagnosis. Two isolated Claude Code 2.1.220 OAuth accounts reproduced the same current profile.
Route count_tokens upstream only for the strict first-party Anthropic origin. Custom base URLs now use local estimation for both OAuth and API-key credentials.
…print-2.1.220 feat(claude): align OAuth wire with Claude Code 2.1.220
Derive cache-diagnosis from the final Messages body so cloaked OAuth requests reproduce Claude Code's exact diagnostics trailer instead of receiving an Anthropic 400.
…ties" A Claude Messages request carrying MCP-style tool schemas failed before inference when routed to Antigravity/Gemini: the private backend parses function declarations as a limited proto-JSON Schema and rejects unknown fields, so `propertyNames` produced Unknown name "propertyNames" at 'request.tools[0].function_declarations[0].parameters.properties[0].value' The cleaner already lists `propertyNames` as unsupported, but every cleaning pass is skipped for nodes classified as property maps, and that classification matched any path ending in ".properties". A tool may declare a property named "properties" — Notion's page tools do — and the schema for that property then sits at ".properties.properties", so it was mistaken for a property map and nothing inside it was cleaned. The 400 above points at exactly that node. Replace the suffix match with a parity check over the trailing run of name-map keywords: the node a keyword names is a map only when its own parent is a schema, so "properties" is a map, "properties.properties" is the schema of a property named "properties", and a third repetition is a map again. Only the trailing run is inspected, so a schema nested under any prefix by the caller is classified the same way. Codex/OpenAI egress is untouched: it converts input_schema separately, uses non-strict tool mode, and accepts this shape.
…trip-property-names fix(antigravity): strip propertyNames inside a property named "properties"
OpenAI callers can raise instructions above user content in three ways and Claude has one system slot for all of them, but the translators disagreed on where each one landed. Responses instructions became a leading user turn, a role=system item was only demoted for the first item, role=developer silently became user text, and the Chat translator dropped developer messages outright. An operator instruction could therefore lose its authority or disappear without any signal. All five sources now become separate top-level Claude system blocks in source order, so the executor cloak decides the final placement on its own: a mid-conversation role=system message on models that accept one, an individual <system-reminder> block on legacy models. Blocks are never merged, trimmed, reordered or demoted. Anthropic only accepts text in a system slot. Verified against api.anthropic.com: the top-level system field rejects anything else with "system.<i>.type: Input should be 'text'", and a role=system message accepts text, tool_addition and tool_removal only. A non-text system part is therefore kept as a typed marker without its payload and rejected by the cloak with a request-scoped 400 that names the offending type. That keeps the failure local, spends no upstream call on a request that cannot succeed, and stops caller content from ever reaching the top-level system field where it would break the Claude Code fingerprint shape.
A Responses caller that asked for reasoning summaries got an empty chain of thought back: every reasoning item carried a signature and no text, so replaying it produced a Claude thinking block with an empty thinking field. The cause was the beta list, not the translator. Cloaked requests always sent redact-thinking-2026-02-12, which makes Anthropic withhold the summary text even when thinking.display is summarized. Native Claude Code 2.1.220 treats the two as mutually exclusive: the beta is only appended while thinking summaries are off, and the request builder removes it again whenever a display value is attached. An isolated 2.1.220 profile with showThinkingSummaries enabled confirms it on the wire, still on cc_entrypoint=cli, sending display=summarized without the beta and receiving thinking text. A direct A/B against claude-opus-4-8 pins the effect down: with the beta the thinking text is empty for every display value, without it and with display=summarized the text comes back. The beta is now dropped whenever the request carries thinking.display, which is exactly the native rule. Two translation gaps kept the chain lossy on the way back. redacted_thinking blocks had no Responses representation at all and vanished, even though Anthropic requires them to be replayed verbatim; they now ride in encrypted_content behind a marker prefix and are restored as redacted_thinking blocks. Reasoning text was only read from summary[], so a caller whose SDK models the text in content[] lost it; content[] is now used as a fallback, and only as a fallback so a client that mirrors both arrays does not replay the text twice. An item whose encrypted_content is missing or belongs to another provider is still dropped rather than replayed, because Anthropic rejects a thinking block without a signature and there is nothing to synthesize.
…-refresh-recovery fix(auth): retry Home OAuth requests once after upstream 401
… boundary for Codex clients
…ng-tokens-usage fix(usage): account for Claude thinking tokens
…sing in response conversion` Closes: router-for-me#5105
…ll pairing in Codex/Claude conversions Closes: router-for-me#5107
…ens` - Add `max_completion_tokens` fallback handling in OpenAI→Antigravity request conversion. - Keep `max_tokens` as the preferred source when both fields are present. Closes: router-for-me#5108
…-incomplete fix(xai): treat response.incomplete as terminal success (router-for-me#5113)
…tem.done` message content Closes: router-for-me#5116
…x executors (router-for-me#5110) Ensure all Gemini and Gemini Vertex execution and token count pathways invoke SanitizeGeminiRequestThoughtSignatures before dispatching upstream requests. This prevents raw non-Gemini (e.g. Claude CAIS) thought signatures from leaking to upstream Gemini endpoints while preserving valid native protobuf signatures and setting appropriate validator bypass sentinels for function calls. Co-authored-by: W ARELIK <warelik@WARELIK-MB.local>
…esponse and streaming payloads Closes: router-for-me#5122
Redefine request-retry as additional credential retry rounds and enforce max-retry-credentials per round. Home dispatch now carries excluded and pinned auth constraints, supports remote retry limits, and propagates cooldown retry-after metadata across exhausted rounds. Move Antigravity upstream retries under conductor ownership to avoid double-consuming retry attempts. Update configuration comments and add coverage for Home retry rounds, cooldown handling, pinned credentials, and legacy dispatcher compatibility.
Canonicalize legacy config-style credential keys across stores, management handlers, plugin auth, and file synthesis while preserving explicit canonical values. Expose per-auth request_retry in auth file management and add max-retry-credentials management routes.
normalizeXAITool still strips Codex hosted image tools on older Grok conversation models. grok-4.6 and later accept xAI native Imagine tool, so keep client-supplied image_generation there and rewrite a forced choice into allowed_tools. grok-4.20-* stays on the old strip because that product line is not comparable to grok-4.6. Closes: router-for-me#5173
Compact deletes tools after prepareResponsesRequestTo. On grok-4.6+ image_generation is now kept and rewritten to allowed_tools, so the leftover choice would be sent without tools. Reuse the existing normalizer to drop that orphaned selection. Closes: router-for-me#5173
…non-stream conversion tests Closes: router-for-me#5147
…and stream/non-stream parity Closes: router-for-me#5148
…for-me#5175) Cloud Code resolves newer Antigravity models only for clients reporting at least 2.9.0; below that it answers 404 Requested entity was not found. The offline fallback still reported 2.9.0's predecessor 2.2.1, so every request sent before the hub manifest is first fetched — or from a deployment that cannot reach the manifest at all — asked for models such as gemini-3.7-flash-high with a version the backend rejects. The hub manifest the updater already polls currently publishes 2.9.1, so this only aligns the offline floor with what the online path resolves. The test now asserts the floor rather than a literal, so a future downgrade below 2.9.0 fails instead of silently reintroducing the 404.
…nd response conversion Closes: router-for-me#5151
Normalize credential metadata and enhance registry interactions
- Add Grok client detection via User-Agent (including Gin context fallback) in a new `grokbuild` helper. - Transform keepalive SSE `event`/`data` frames into `: keepalive` comments when streaming to Grok clients. - Keep keepalive frames untouched for non-Grok clients while preserving existing stream translation behavior. Closes: router-for-me#5171
…e-generation-grok-46 fix(xai): keep image_generation on grok-4.6+ conversation requests
…fallback-version fix(antigravity): raise the fallback client version to 2.9.1 (router-for-me#5175)
- Added a preprocessing pass to repair malformed MCP-style JSON schemas. - Wraps bare property maps as object schemas, promotes `required: true` flags to parent `required` arrays, and removes boolean `required` from properties. - Recurses through nested schema containers and skips known API request envelopes to avoid rewriting non-schema docs. - Switched schema decoding/serialization path to preserve large numeric values and avoid HTML-escaping side effects. Closes: router-for-me#5178
# Conflicts: # README.md # internal/registry/models/models.json # internal/runtime/executor/claude_executor.go # internal/runtime/executor/claude_executor_test.go # internal/translator/openai/claude/openai_claude_request.go # internal/translator/openai/claude/openai_claude_request_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v7.2.140into the fork (previous base:v7.2.73, synced Jul 14). 505 upstream commits / 67 releases, ~6 weeks of upstream fixes.Patch survival (per-patch "still needed?" review)
reasoningfallback, OpenAI→Claude response): still needed — v7.2.140 still reads onlyreasoning_contentat all three sites. Auto-merged, tests pass.cache_controlstrip, Claude→OpenAI request): still needed — upstream still has no cache_control handling on this path. Upstream refactoredConvertClaudeRequestToOpenAIinto a privateconvertClaudeRequestToOpenAIwith aWithCompatwrapper; the strip now applies inside the private function so both entry points are covered. Test-file conflict resolved keeping both our cache_control tests and upstream's new StopSequences test.sk-ant-oat01-*in api-key entries): RETIRED — doubly obsolete: (a) upstream v7.2.140 detects OAuth tokens natively (isClaudeOAuthToken→ Bearer inclaude_executor_request.go), (b) the AMPECO deployment migrated fromclaude-api-key:token entries to OAuth credential files (--claude-login), so this code path no longer carries OAuth tokens. Patch and its tests dropped; upstream's executor taken wholesale (upstream split the 2,663-lineclaude_executor.gointo ~15 files).models.jsonhad re-grown 2 Claude antigravity entries; strip re-applied (13 → 11). The.github/scripts/refresh-model-catalogs.shguard and the release.yaml build steps survived the merge untouched.f23fb122that arrived via the v7.2.15 sync. Nothing to preserve.Verification
go build ./...clean,go vetclean on touched packages,gofmtclean.go test ./...passes locally (exit 0).🤖 Generated with Claude Code