Skip to content

Sync upstream v7.2.73 → v7.2.140 (retire Patch 3, keep Patches 1/2/4) - #5

Merged
sash merged 506 commits into
mainfrom
chore/sync-upstream-v7.2.140
Aug 24, 2026
Merged

Sync upstream v7.2.73 → v7.2.140 (retire Patch 3, keep Patches 1/2/4)#5
sash merged 506 commits into
mainfrom
chore/sync-upstream-v7.2.140

Conversation

@sash

@sash sash commented Aug 24, 2026

Copy link
Copy Markdown

Summary

  • Merge upstream v7.2.140 into the fork (previous base: v7.2.73, synced Jul 14). 505 upstream commits / 67 releases, ~6 weeks of upstream fixes.
  • Motivation: routine upstream sync; deployed proxy on mm007 is 6 weeks behind upstream.

Patch survival (per-patch "still needed?" review)

  • Patch 1 (reasoning fallback, OpenAI→Claude response): still needed — v7.2.140 still reads only reasoning_content at all three sites. Auto-merged, tests pass.
  • Patch 2 (cache_control strip, Claude→OpenAI request): still needed — upstream still has no cache_control handling on this path. Upstream refactored ConvertClaudeRequestToOpenAI into a private convertClaudeRequestToOpenAI with a WithCompat wrapper; 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.
  • Patch 3 (Bearer auth for sk-ant-oat01-* in api-key entries): RETIRED — doubly obsolete: (a) upstream v7.2.140 detects OAuth tokens natively (isClaudeOAuthToken → Bearer in claude_executor_request.go), (b) the AMPECO deployment migrated from claude-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-line claude_executor.go into ~15 files).
  • Patch 4 (strip Claude from antigravity catalog): still needed — upstream's refreshed in-tree models.json had re-grown 2 Claude antigravity entries; strip re-applied (13 → 11). The .github/scripts/refresh-model-catalogs.sh guard and the release.yaml build steps survived the merge untouched.
  • Patch 5 (tool uses adjacent to tool results): not actually an ampeco patch — it was upstream commit f23fb122 that arrived via the v7.2.15 sync. Nothing to preserve.

Verification

  • go build ./... clean, go vet clean on touched packages, gofmt clean.
  • Full go test ./... passes locally (exit 0).

🤖 Generated with Claude Code

sususu98 and others added 30 commits August 3, 2026 14:47
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
…ng-tokens-usage

fix(usage): account for Claude thinking tokens
luispater and others added 29 commits August 21, 2026 02:16
…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)
…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>
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
…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.
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
@sash
sash merged commit 521bf38 into main Aug 24, 2026
2 checks passed
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.