[pull] main from danny-avila:main - #244
Merged
Merged
Conversation
* feat: add safe default approvals for BYOM code * fix: preserve safe BYOM approval baseline
* 🔁 fix: Recover Keyv Redis Client From READONLY Replica After Failover When a Sentinel failover demotes the master a pod is connected to, the ioredis client recovers through `reconnectOnError`, but the Keyv/node-redis client never does: `socket.reconnectStrategy` only runs when the socket closes, and a demoted replica keeps existing sockets open while rejecting every write with `READONLY`. Every cache write through the Keyv client (USER_PRINCIPALS, MCP catalog, server configs) then fails until restart. - Add a READONLY recovery hook for the standalone node-redis client that tears the socket down and reconnects, re-resolving to the current master - Debounce attempts with `REDIS_READONLY_RECOVERY_INTERVAL` (5s default) and retry on the next error, since a reconnect issued before the topology settles can land on the demoted node again - Route all three surfaces where READONLY replies appear through the hook: the client error event, the Keyv cache error funnel, and Lua scripts evaluated via `evalKeyvRedisScript`, which reject straight to callers - Skip cluster clients, which follow MOVED to the owning master already - Cover the hook with a fake RESP server so real node-redis and Keyv code paths are exercised against a node whose role flips mid-connection Fixes #15500 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WNbgMeR2aZDyhsqAy4L8gF * 🛟 fix: Harden READONLY Recovery Retry, Clear Path, and Clock Address review findings on the READONLY failover recovery: - Retry on the next error of any kind after a failed reconnect. A failed `connect()` leaves the client closed, so later failures surface as ClientClosedError rather than READONLY and the hook never fired again - Route the namespace `clear()` override through recovery. It deletes through the raw client, bypassing the Keyv error funnel, so a READONLY rejection there previously left the pod stranded - Debounce on an injectable monotonic clock (`performance.now`) instead of `Date.now`, so wall-clock steps cannot suppress or duplicate attempts; the interval test drives the clock instead of sleeping - Reuse `isReadonlyReplicaError` in the ioredis `reconnectOnError` hook so READONLY detection has one definition - Document the in-flight command rejection that a socket teardown implies Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WNbgMeR2aZDyhsqAy4L8gF * 🛟 fix: Gate READONLY Recovery on Client State Address the second review pass on the READONLY failover recovery: - Act only on a client the hook can reason about: a READONLY reply on a ready socket, or a client its own failed reconnect left closed. While node-redis runs its own reconnect loop (open but not ready) the hook stays out, since a second `connect()` would start a concurrent loop that leaks sockets into one shared reply decoder - Clear the pending retry whenever an error arrives on a ready client, so a client that Keyv auto-connected after a failed attempt is never torn down by a later unrelated error - Drop the client error-event wiring: node-redis rejects command error replies straight to the command promise and emits `error` only from its socket and connect loop, so that listener could never see a READONLY reply and only fed connect-loop errors back into the hook - Cover the connect-loop, self-recovered, and Keyv auto-connect outage cases, and a rejected namespace clear, with a SCAN-aware RESP server - Add the new export to the `redisClients` mocks in the cacheFactory specs
Queue a message during a run — queue, not steer — and the row is server-owned: `useQueueDrain` deliberately declines the boundary (`serverOwnsBoundary`) and the backend admits the successor itself. So the client has to hear about that run through the active-job list, exactly like a background-tool continuation. It cannot. Finishing a run empties the list — the client removes its own job optimistically the moment FINAL lands — and the poll is disabled on an empty list, so it goes quiet at precisely the moment the successor is admitted. With the tab already focused there is no focus refetch either, which is why this reproduces on desktop and not only on mobile. The announcement never arrives, so the re-arm never runs and the pane sits on the previous turn until a reload. Keep asking for a bounded window after the last known job ends. The window is module-scoped rather than per-observer because this is one shared query and a component mounting mid-handover should inherit the grace, not restart it. This is the other half of the previous commits: without the re-arm the announcement lands on a pane that still reads its finished submission as an attachment, and without this the announcement never lands at all. Neither half is observable alone.
* feat: add audit-only content filter action * refactor: align filter action typing and tests * fix: preserve audit-only filter behavior * fix: enforce audit mode across content paths * fix: honor audit mode for canonical files
* test: add mobile chat performance benchmark * fix: isolate mobile benchmark measurements
* feat: add configurable BYOM permissions * test: cover BYOM permission settings live * fix: harden BYOM permission settings * perf: reuse principals for environment discovery * chore: normalize BYOM settings style * fix: Align BYOM Discovery and Admission * fix: Harden BYOM Permission Boundaries * fix: Align BYOM Skill Approval Routing * fix: Preserve Lazy BYOM Approval Capabilities * perf: Parallelize Cached Environment Reads
Claude Fable 5.1 (`claude-fable-5-1`, GA 2026-09-01) succeeds Claude Fable 5
at the same input/output prices, with a 1M context window and 128K max output.
The Mythos-class helpers added for Fable 5 already match it — `isMythosClassModel`
tests `claude-(?:fable|mythos)[-.]?\d`, so adaptive thinking, summarized-display
opt-in, sampling omission, 1M context, the 128K output clamp, prompt caching,
the Vertex multi-region gate, and the Bedrock PDF exemption all cover 5.1
without a code change. What was missing was registration and pricing.
Cache reads are the one rate that differs, and the substring matcher would have
silently gotten it wrong: `claude-fable-5-1` falls through to the `claude-fable-5`
key, which prices cache hits at the usual 0.1x base input ($1/MTok). Fable 5.1
and Mythos 5.1 price them at 0.025x ($0.25/MTok), so every cache read would have
billed 4x — on exactly the long agentic sessions this model is built for.
- Register `claude-fable-5-1` in the shared Anthropic list and
`global.anthropic.claude-fable-5-1` in the Bedrock list
- Add 1M context / 128K output entries for `claude-fable-5-1` and
`claude-mythos-5-1`
- Add $10/$50 rates and `{ write: 12.5, read: 0.25 }` cache rates for both
- Update the `.env.example` and Vertex `librechat.example.yaml` examples
- Test that 5.1 resolves to its own key rather than collapsing onto 5.0, across
token maps, pricing, cache rates, and Mythos-class detection
The three documented breaking changes from Fable 5 need no handling here:
LibreChat never sends a forced `tool_choice` on the Anthropic path (the agents
SDK omits the param when unset, so the API default `auto` applies); thinking
blocks an earlier model can't read are dropped server-side, unbilled; and
history is rebuilt from stored content parts rather than replayed signed
thinking blocks, so the prefix-binding check has nothing to reject.
Refs #15506
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )