Conversation
…ndencies (LibreChat-AI#15754) * 🧶 docs: Keep the Breadcrumb Carve-Out in AGENTS.md The template and CLAUDE.md both say that naming the merged pull request which caused a bug is history the reader needs, not a breadcrumb. The condensed AGENTS.md version dropped that half, leaving a flat rule against referencing earlier work, which is the file most agents actually read. * 🧱 docs: Hold the Database Boundary and Make New Levers Configurable Workspace Boundaries said where database logic lives but not what may cross the line, so Mongoose types travel outward in exported signatures and make the storage engine part of each module's public API. That is the tax a second engine would pay, and it is cheaper to stop widening than to unwind: packages/api already imports mongoose in dozens of non-test files, while client carries none. Nothing in either file mentioned configSchema or librechat.yaml either, so a new limit or toggle lands as a constant by default and an operator cannot reach it. Both rules now sit in Workspace Boundaries, with the configurability half cross-referenced from the definition of done. Condensed into AGENTS.md as Module boundaries and configuration. * 🔌 docs: Take Dependencies, Do Not Reach for Them Client State Ownership already tells a frontend feature to accept app-global state through props rather than reaching into the store, and gives the reason: it is what lets the feature move to its own workspace later without a rewrite. The backend had no equivalent, and neither file mentioned dependency injection at all. Backend modules now carry the same rule one layer down, with createModels(mongoose) as the shape to copy and the static singletons under packages/api/src/mcp as the shape to stop extending. Integrations get it explicitly: an injected provider SDK, storage backend, vector store or OAuth server makes a second implementation a new argument instead of a new branch, and lets a test substitute at the boundary rather than mocking the module that holds it.
* fix: Settle Background Tool Polls Reliably * fix: recover interrupted background result delivery * fix: preserve independent background fallbacks * fix: align background claim types * chore: sort background task imports * fix: preserve claimed result narrowing
Both migration rules described an end state and left the trigger implicit, which is why they get skipped. "Keep /api changes to the absolute minimum" reads as "make a small edit here", the opposite of what it means, and it is phrased for new code while the common case is editing an existing CJS file. It now says /api holds wiring and not behavior, that minimum describes how much behavior /api gains rather than diff size, and that lifting the function out is the larger and correct diff. MCPRequestContext.js is named as the shape. "Convert the areas you touch" never defined an area, and never said an atom cannot be half converted, so mixed Recoil and Jotai imports in one file read as permission. The rule now states that new state is always Jotai, that the unit of conversion is one atom plus every reader and writer, and that an atom with a consumer outside the feature stays on Recoil and gets passed in. jotai-utils.ts is named for persisted atoms.
* fix: Skip test modules during structured tool discovery * fix: Keep tool discovery validation in TypeScript
* fix: expose tenant index upgrade migration * fix: retry tenant migration index builds * docs: run tenant migration from the image root
Covers the one leg the credential-free mock suite cannot fake: a file attached through the UI's Code Environment target must land in the live Code API, get delivered into the sandbox, and stay readable across turns. - fake-model: E2E_EXEC_UPLOADED:/E2E_EXEC_PERSIST: markers emit real bash_tool calls through the production tool pipeline (the sandbox surface stateful agents register; execute_code stays host-wired and never appears in the tool registry), plus an env-gated dump of each run's advertised tools for future spec authoring - spec: attach uploads a CSV to the Code API, turn 1 reads it back from /mnt/data and drops a proof file no upload contained, turn 2 (sent without an attachment) reads both — only possible when the run reuses the same stateful runtime session - e2e config: agents capabilities gain stateful_code_sessions, and the mock profile pins CHECK_BALANCE=false so a developer's local .env can never fail every send with zero-balance users - skips unless LIBRECHAT_CODE_BASEURL is provided (kept out of CI)
* fix: stop refreshing MCP caches on every chat message * fix: reconcile MCP caches independently of chat turns * fix: scope MCP polling to visible controls * fix: refresh status in the unpinned MCP submenu
* fix: Patch gRPC xDS DoS dependency * fix: Tidy patched gRPC module graph
…ibreChat-AI#15770) * chore: bump agents sdk to v3.8.5 * chore: bump nodemailer to v10.0.1 * chore: bump sharp to v0.35.4 * chore: bump js-yaml to v4.3.2 * chore: bump hono to v4.13.7 and @hono/node-server to v2.1.1
* feat: Select Attached Code Workspaces * fix: Preserve Workspace Boundaries Across Agent Graphs * fix: Validate Lazy Agent Workspace Bindings Before Persistence * fix: Include Handoff Environments in Workspace Selection * fix: Close Workspace Admission and Remote Ingress Gaps * fix: Preserve Workspace Selection In Chat Runtime Envelopes * fix: Authorize Deployment Workspace Status And Match Readiness * fix: Preserve Ephemeral Chats And Pin Runtime Worker Identity * test: Complete Deployment Pairing Fixtures
* ✨ feat: Cancel ordinary background tools * 🛡️ fix: Keep cancellation receipts rollout-safe * 🛡️ fix: Harden Background Tool Cancellation * 🧪 test: Cover cancellation config wiring * 🎨 style: Sort cancellation imports * 🧪 test: Align Cancellation Claim Result * 🛑 fix: Complete Background Cancellation Lifecycle * 🎨 style: Align Cancellation Test Formatting
…5777) * fix: Preserve BYOM foreground cancellation identity * fix: Bind foreground cancellation to runtime message
* 🕰️ feat: Add BYOM Bash Execution Timeouts * 🔧 fix: Type Bash Timeout Bounds * 🔒 fix: Bound BYOM Bash timeouts by policy * 🧪 test: Propagate BYOM timeout policy fixture
* fix: Preserve BYOM workspace selection state * 🧭 fix: Centralize Workspace Error Serialization * 🎨 style: Format Workspace Error Helper
…ibreChat-AI#15791) - send each turn through sendMessageAndWaitForCompletion so the composer is unlocked before the next Enter - give the three tests explicit timeouts, matching the chat.spec.ts budgets from LibreChat-AI#14740
* fix: resolve queued turn placeholder anchors * fix: anchor queued turns to durable message parents * fix: preserve durable queued turn anchors
) * fix: recover CodeAPI uploads after throttling * fix: cover eager CodeAPI uploads * fix: scope CodeAPI upload recovery * test: clarify upload recovery deadlines * fix: isolate CodeAPI recovery state * fix: cancel CodeAPI recovery waits * test: provide CodeAPI registry in handler fixture * fix: propagate CodeAPI recovery controls * fix: bound CodeAPI recovery by run * fix: preserve skill upload cancellation * test: update deferred loader signal contract * fix: preserve recovery cancellation * fix: cancel recovery source reads * fix: classify Axios upload cancellation * fix: preserve lazy provisioning cancellation * fix: close resource recovery boundaries * fix: preserve provisioning failures compatibly
* fix: Validate Scheduled MCP Readiness 🕰️ * fix: Keep Schedule Permission Store Failures Retryable * perf: Parallelize Scheduled MCP Preflight * fix: Preserve Scheduled MCP Invariants * fix: Close scheduled MCP recovery gaps * fix: harden scheduled MCP recovery * fix: bound scheduled MCP validation * fix: harden scheduled MCP admission bounds * fix: align scheduled MCP graph admission * fix: bound scheduled MCP admission * fix: align scheduled MCP preflight with runtime * fix: persist scheduled MCP failure outcomes * fix: match scheduled MCP runtime semantics * fix: parallelize scheduled MCP admissions * fix: mirror scheduled subagent traversal * fix: enforce scheduled subagent config limits * fix: bound scheduled MCP initialization * fix: mirror lazy subagent metadata budgets * fix: complete scheduled MCP recovery * fix: attribute missing MCP tools * fix: harden scheduled MCP admission * fix: preserve scheduled admission invariants * fix: retain inaccessible MCP requirements * fix: make MCP admission recovery durable
* fix: Back Off MCP OAuth Discovery * fix: harden MCP discovery recovery state * fix: synchronize MCP authorization recovery * fix: fence MCP discovery authorization state * fix: retain recovery generation through cache outages * fix: close MCP authorization fence gaps * fix: complete MCP authorization lifecycle * fix: close MCP authorization recovery races * fix: centralize MCP recovery lifecycle * fix: fence ephemeral MCP catalog observers * fix: close MCP authorization recovery races * test: cover Redis token settlement race * fix: prefer authoritative token settlement * fix: harden MCP authorization retry recovery * fix: back off stalled OAuth refreshes * fix: bound durable authorization retries * test: isolate authorization retry adapter * fix: close MCP authorization recovery boundaries * fix: defer agent authorization observers * fix: close OAuth fence race windows * fix: keep retry deferrals monotonic * chore: sort startup hook imports
* fix: resolve saved subagent display identity * fix: persist explicit subagent execution identity
* 📭 fix: Treat Empty Mongo Auto-Index Env as Unset Empty or whitespace MONGO_AUTO_INDEX / MONGO_AUTO_CREATE values are now treated as unset so Mongoose keeps its defaults instead of receiving false. Co-authored-by: Zsanz3 <Zsanz3@users.noreply.github.com> * fix: Format optional Mongo index setting helper --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Zsanz3 <Zsanz3@users.noreply.github.com> Co-authored-by: Danny Avila <danny@librechat.ai>
* Propagate host cancellation through API tool execution * Preserve selected signal ownership across every API ingress
* Restore attached workspaces from the resolved owner conversation * Carry restored conversation through lazy tool initialization * fix: Resolve Workspace State From Effective Conversation * style: Format Conversation Regression Cases * test: Retain Real Workspace Resolver In Controller Fixtures * test: Exercise Workspace Envelope Conversation Identity
* feat: add Claude Opus 5.5 support * fix: preserve Opus 5.5 settings through provider adapters * fix: preserve model-hidden settings when pruning parameters --------- Co-authored-by: Lia <lia@librechat.ai>
…at-AI#16220) The collapsed live activity row printed its repeated-tool multiplier at the row's far right, beside the chevron, a full row width away from the line it counts. It now sits directly after that line, the way the unfolded group already reads Create File x2, while the span's failure and cancellation verdict keeps the row's right edge because it belongs to the whole span. Co-authored-by: Lia <lia@librechat.ai>
…hat-AI#16223) * 🔍 fix: Enable File Search When Attaching From the Files Panel * 🔍 fix: Skip the Ephemeral File Search Flag for Saved Agents
…-AI#16224) * feat: support Cognito M2M for Agent management * fix: reject compound management scopes * fix: require scopes for audience-less management tokens
…I#16225) * Count the tool only while the line is its generic label A streamed intent already names the work this call is doing, so a repeat count beside it reads as a claim that the sentence happened N times. The count now rides the generic Running/Ran label alone, and is dropped for an intent, a failure or cancellation verdict, and a background handle line. * fix: Omit Repeat Counts From Sandbox Startup Labels * test: Bound Client Recovery Worker Activation Waits --------- Co-authored-by: Lia <lia@librechat.ai>
* feat: add GPT-6 Sol and Luna support * fix: normalize Sol and Luna reasoning requests * fix: align Sol and Luna effective Responses routing * fix: honor server routing policy for model uploads * test: await system grant indexes before writes * fix: verify model upload policies against runtime initialization --------- Co-authored-by: Lia <lia@librechat.ai>
…6228) * 🛍️ feat: Add Programming App to OpenRouter Categories * style: Format OpenRouter category override test --------- Co-authored-by: Lia <lia@librechat.ai>
…#16229) Co-authored-by: Lia <lia@librechat.ai>
…at-AI#16078) * Add client side tools * 🚦 fix: Ask the Model to Call Caller-Executed Tools Alone * Add client tool continuation replay tests * Fix clientTools docstring * fix: return only tools that have been actually applied * 🔁 fix: Continue a Caller-Executed Tool Exchange Across Requests * fix: handle null values for tool descriptions and parameters in client tools * 🧩 fix: Keep the Arguments of Every Tool Call in a Streamed Message * Fix PR comments * fix: Preserve client tool handoff across SDK event ordering --------- Co-authored-by: Lia <lia@librechat.ai>
* 🚀 v0.8.8-rc4 * chore: bump LibreChat chart to 2.0.14
…the Fetched Catalog New `models.filter` option for custom endpoints: serve `default` ∩ fetched instead of replacing `default` with everything the API returns, so several endpoints over one gateway can each offer their own slice of its catalog, in declared order. A failed or empty fetch falls back to the declared list, as it always has without `filter`. A filter-managed endpoint left with an empty model list renders as an empty picker entry and an unusable Agent Builder provider, so the endpoints route withholds it. User-provided endpoints are kept — their empty list reflects the user's own key — and the route resolves models only when some endpoint filters, failing open when it cannot. An empty filter-managed endpoint is unavailable, not being asked for an illegal model: stored conversations and agents naming it would otherwise earn their owners violations for a catalog change they had no part in. Both the chat and agents validation paths reject without logging one. One request resolves the models config from several places (model validation, token config, agent initialization), and each resolution may re-fetch gateway catalogs, so the resolved config is memoized per request in a WeakMap, evicting on failure so a later caller retries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add `modelLabels`, an endpoint-level record mapping model ids to display labels. Purely presentational: the id stays what is declared, fetched, selected, stored on the conversation and sent upstream, and a model with no entry renders its id. One helper, getModelName, resolves the agent name, the assistant name, or the declared label; the model list, search results, the selector's closed trigger, the selection announcement, the @-mention menu, the favourites list, the model parameter dropdowns, the endpoint settings panels, the added-conversation header and the Agent Builder read it or the declared map directly through getModelLabel. A declared label is additive in search via modelSearchNames — labelling a model never makes its id unsearchable — which also consolidates three inline copies of the name-resolution rule and fixes the globe icon for unnamed public agents in search results. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds an optional per-MCP-server `deferLoading: boolean` config flag. When true, every tool from that server defaults to deferred loading: the model receives the `tool_search` tool plus a name-only listing instead of each tool's full JSON schema, saving context on large tool sets. Unlike the per-agent `tool_options[toolId].defer_loading` toggle, it also applies to ephemeral agents (model + attached MCP) that carry no `tool_options`. Extends the existing `deferred_tools` capability (LibreChat-AI#11295) to the server-config level and the ephemeral path. Complementary to the proposed MCP toolFilter (LibreChat-AI#13346 / LibreChat-AI#11088).
…ntMessages crash (#64) The streaming content aggregator builds message content by index and yields a sparse array; an interrupted/partial save persists a hole that serializes to null in MongoDB. On replay, @librechat/agents formatAgentMessages reads part.type with no null guard and crashes. Sanitize content holes at getMessages, the single DB read chokepoint for conversation history, so both already-corrupted and future rows are neutralized for every consumer (formatAgentMessages, token counting, edit path). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…and avoid bans for unserved models
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
…breChat-AI#16496) - Wrap and scale each pptx slide on its own at panel width, init pptx-preview with a width only, pin each slide to its block on wide panels, space the slides, guard finalize against running twice, and reserve the scrollbar gutter so the panel scrolls to the last slide without flicker. - Scope file card dedup to the message and register panel content only when newer by lastUpdateTime (global latest-mount claim kept as the equal-time tie-break), so every message that made a file shows its card and every card opens the newest version; diagram cards and search results follow the same rule. - Keep one copy per file per message (the newest write, tool-call-linked entries only), dedup the folded file group with the same identity, and key id-less files by path before name.
Creators can mark each built-in tool (web search, code, file search) and each MCP server on a saved agent as locked, switchable and on by default, or switchable and off by default (tool_options[key].user_toggle). Chat users see the switchable ones in the chat input, flip them per chat, and the server only ever removes switchable tools from the primary agent; a request can never add a tool or enable a locked one. Agents without switches, ephemeral chats and plain chats are unchanged. View-only agent reads now include tools and the user_toggle part of tool_options so shared users get their switches. MCP instructions follow the filtered tools, and a paused turn resumes with the same tool set. Related to LibreChat-AI#8096
…83) Scheduled Chats fire without a browser session, so `req.user` has no OpenID tokens. `resolveHeaders` then throws OpenIDReauthRequiredError for any endpoint header using {{LIBRECHAT_OPENID_ACCESS_TOKEN}} / {{LIBRECHAT_OPENID_ID_TOKEN}}, and every scheduled occurrence on such an endpoint fails before the model call. With SCHEDULES_OMIT_UNAVAILABLE_OPENID_HEADERS=true, the agents route marks the user of a scheduled fire, `createSafeUser` carries the marker, and `resolveHeaders` omits a header whose OpenID credential placeholder cannot be resolved instead of throwing, whether or not the caller strips unresolved placeholders. Valid tokens still substitute. Interactive requests and MCP resolution (`processMCPEnv`, which feeds the schedule MCP preflight) keep failing closed. Off by default. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e Ref's Profile deleteCodeEnvFile rethrew every error except 404. A deployment that only serves the stateful profile answers a default-profile delete with 409 execution_profile_mismatch on every retry, so the file landed in failedFileIds, its record and agent references stayed, and agents holding it aborted every code turn with "Failed to provision N file(s) to the code environment". The mismatch is now handled like an absent object: logged, and the delete proceeds. Other 409s, 5xx, auth and network errors still fail the delete.
pptx-preview turns EMF/WMF media into data:image/x-emf and data:image/x-wmf URIs, which no browser decodes, so template logos stored as Windows metafiles render as broken images in the artifact panel. Convert them to SVG on the server with emf-converter (pinned 4.8.7, Apache-2.0, no dependencies), embed the SVGs keyed by a hash of each entry's base64, and swap them into the rendered <img> elements when the bootstrap finalizes. Conversion is bounded per entry (512 KB, 10,000 records) and per deck (64 entries, 8 MB input, 1 s, 384 KB of SVG). If the map would push a deck past the preview cap, the deck is rendered without it, so no deck that previews today changes path. (cherry picked from commit 6b076b2) Upstream: LibreChat-AI#16672. Adapted for the storage-backed file shell on this branch: buildPptxCdnDocument/pptxToHtmlViaCdn keep their fileShell parameter, a shell over the cap retries without the map, and layout.spec.ts/html.spec.ts cover the shell path.
This branch has not been deployed
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
Rebuilds the fork stack on upstream
v0.8.8-rc4and supersedes #74 (sync/v0.8.8-rc2). Upstreammainwas 389 commits ahead ofsync/v0.8.8-rc2. This branch is 11 commits behind upstreammain: the post-rc4 fixes (LibreChat-AI#16231, LibreChat-AI#16252, LibreChat-AI#16261 agents SDK v3.9.3, LibreChat-AI#16266–LibreChat-AI#16270, LibreChat-AI#16253, LibreChat-AI#16005). That keeps it pinned to a tagged RC, like previous syncs did.It keeps the 2-layer commit stack from #74 (12 commits, same order, same authors).
sync/v0.8.8-rc2is left alone so #80 (which targets it) is not disturbed.Layer 1: upstream PR commits
0956e03e2aproorg/feat/custom-endpoint-model-filter, rebased on upstream on 2026-09-22) and squashed it back to one commit. The old cherry-pick conflicted with rc4 inagents/validation.tsandconfig-schemas.spec.ts.6d2f6ceccaproorg/feat/custom-endpoint-model-labels(2026-09-23)089771775deferLoadingaproorg/feat/mcp-server-defer-loading(2026-09-22)059ffd728Layer 2: fork-specific commits (unchanged in intent)
d3404df0enull content parts (#64) ·43e582733OIDC auto-refresh ·4379e8a57modelSpecs availability filter ·d6fa1c157empty model list / complement filter ·7851bd025declared custom endpoint over case-folded builtin ·17031ef93Locize i18n ·a14ea19bcMCP form-mode elicitation ·08dcdde48test mock alignmentConflict resolutions
packages/data-provider/src/types/assistants.ts: upstream movedPartMetadata/ContentPart/TMessageContentPartsintotypes/content.ts. TheAgents.ElicitationContent & ContentMetadataunion member now goes incontent.ts, and the old copy inassistants.tsis dropped.api/server/routes/mcp.js: kept the fork'scanAccessElicitationFlowand form validators. Dropped the re-addedclearGetTokensFlow, because upstream removed it and nothing calls it anymore.packages/api/src/mcp/MCPManager.ts: kept upstream's new constructor (catalog recovery tracker), theUpstreamTokenProviderResolverimport, and theonOAuthCredentialsChang(ed|ing)params. Added the elicitation slot tracking and theelicitationStreamId/elicitationStepIdparams alongside them.packages/api/src/flow/manager.ts,librechat.example.yaml: kept both sides.api/server/controllers/agents/client.js:stripUiOnlyContentPartsruns before upstream's (comment-only) summary-parts note.api/server/controllers/agents/responses.js: combined both wrappers intostripUnusableSummaryParts(stripUiOnlyContentParts(stripActivityLabelParts(allMessages))).SearchResults.tsx: the fork commit only reordered an import. Took upstream's version.ModelPanel.test.tsx: upstream now provides thePanelHeader/getModelLabelmocks itself. Took upstream's version.Fixes pulled forward from the upstream LibreChat-AI#15550 branch
stripUiOnlyContentPartsreturns the same array when nothing is stripped. Without this, rc4'sclient.test.js › derives and forwards compaction guidancefails itstoBe(payload)identity check. The form-elicitation commit also carried a stale copy ofruns.tsthat silently undid this change, so that hunk is removed from it.ElicitationForm.test.tsxmockslibrechat-data-providerwith...jest.requireActual. The rc4 provider icon registry readsProviderIdat import time, so a bare mock crashed the suite.Verification (run locally on this branch)
npm run build:data-provider && build:data-schemas && build:api && build:client-package: passclient:tsc --noEmit: 0 errorsnode --checkon all 640api/**/*.js: 0 failures. No conflict markers anywhere in the tree.apijest (mcp routes, agents controllers, Model/Endpoint controllers, validateModel, Config services, openIdJwtStrategy, AuthService): 1512 passed, 1 skippedpackages/data-providerjest: 2119 passedpackages/apijest (mcp, flow, agents, endpoints; CI ignore patterns): 7650 passed. The remaining failures are all caused by the sandbox, not by the sync:hardenedFetch.behavior.test.tsfails because loopback sockets are blocked. The fork doesn't touchsrc/mcp/oauth.endpoints/models.spec.tsandsummarization.e2e.test.tsfail because the host hadANTHROPIC_*/OPENAI_*set. With those unset (as in CI): 58 passed, 4 skipped.clientjest in every directory the stack touches: 287 suites, 4906 tests passed (after the ElicitationForm fix)Not run: the Redis/Mongo integration suites, Playwright e2e, and a deployed smoke test.
Note on the lockfile
Upstream's
package-lock.jsonat rc4 is unchanged by this stack. Installing needsNODE_ENV≠production(or--include=dev) to gettsdown.Supersedes #74.
🤖 Generated with Claude Code