fix(third-party): strip undocumented cache_control subfields for custom upstreams (#297)
* fix(third-party): strip undocumented cache_control subfields for custom upstreams
Claude Code sends a scope subfield inside cache_control that Anthropic
accepts but strict Anthropic-compatible backends reject with 400 unknown
parameter, breaking every request once such an account is selected.
Forward only the documented type/ttl there; Anthropic legs pass through
byte-identical.
* fix(third-party): forward only cache_control type to custom upstreams
Probed against api.meta.ai: scope is an unknown parameter and ttl:1h is
not supported; bare type:ephemeral and type+ttl:5m both return 200. Since
5m is the default window, dropping ttl is lossless except on backends
with 1h windows — and requests there still succeed.
* fix(third-party): make the cache_control strip opt-in, keep ttl, walk only breakpoints
Three changes from review:
- `ttl` is documented by Anthropic ("5m" | "1h") and a mirror that honours
"1h" must keep it, so it is no longer dropped by default.
- Nothing is dropped unless the account opts in, like every other body rewrite
keyed on `upstream`: `stripRequestFields` accepts `"cache_control.<sub>"`
entries (e.g. `["cache_control.scope"]`), and only those subfields go. A
first-party relay or regional mirror pointed at by `upstream` loses nothing.
- Only the documented breakpoint positions are walked — the root, `system[]`,
`messages[].content[]` (and a tool_result's own content blocks), `tools[]`.
A `cache_control` key inside a `tool_use.input`, a `tool_result` payload or
`metadata` is data, not a cache hint, and is left byte-identical.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Mark Karpeles <magicaltux@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> A
aram.eth committed
344ff383efca1791703fef920882a6619b7c43be
Parent: 73dc784
Committed by GitHub <noreply@github.com>
on 9/8/2026, 2:57:21 PM