Repository navigation
Conversation
…hat-AI#16794) * feat: Show the Conversation Pull Request in the Chat Header A header chip shows the pull request a code conversation opened: the agent picture with a CI status dot, the pull request icon and a truncated title. It opens a card with the number, added and removed lines, a link to GitHub, and state and checks badges. The chip renders nothing while loading, when there is no pull request, or when the first lookup fails. * feat: Place the Pull Request Chip Beside the Model Controls and Move It to the Overflow Menu on Small Screens On desktop the chip sits with the left header controls and its card opens to the right as an Ariakit hovercard that slides in from the left, on hover or keyboard focus. Small screens offer the same card from the header overflow menu through a dialog, following the dialog-item contract. * fix: Address Review Findings on Pull Request Polling, Badges and Tooltip Layering Advertise pullRequestsEnabled in the startup config and skip the lookup without it, keep polling a finished pull request while its checks run, render the card badges with the shared Chip, and portal the GitHub tooltip into the card's own layer. * fix: Address Second Round Review Findings on the Pull Request Dialog and Chip Scope the mobile dialog to the conversation it opened for and expose dialog semantics on its menu entry, only use the chat agent's avatar for the routed conversation, and make the hover tests move the pointer the way a browser does so they pass under NODE_ENV=development as CI runs them.
…LibreChat-AI#16817) * fix: Make DataTable Row Estimates Breakpoint- and Leaf-Column-Aware * test: Cover the Compact Row Estimate Against the Rendered Cell * test: Tag the Row Estimate Scenarios Literally
…t-AI#16820) * fix: Dim a Disabled InputNumber Through Its Nested Input * test: Cover the Disabled InputNumber Wrapper in the Browser * test: Tag the InputNumber Scenarios Literally
…Chat-AI#16822) * refactor: Clear Chat Design Suppressions That Render Nothing * test: Tag the Steer Render Spec as a Scenario
…eChat-AI#16826) * refactor: Mark Message Text Containers With a Data Attribute * test: Tag the Private Text Spec as a Scenario * test: Cover Message Text Containers in a Mobile-Safe Scenario
…LibreChat-AI#16825) * refactor: Clear the Raw-Color and Unknown-Class Design Suppressions * fix: Keep the Prose Classes style.css Still Reads * fix: Keep the split-parent Marker the Screenshot Spec Waits On * chore: Prune the Recorded Suppressions the Rebase Cleared
…ibreChat-AI#16828) * refactor: Give Sign-In Controls Button, Input and Alert Variants * fix: Load the Field Stylesheet From SecretInput * fix: Default the Floating Fields to the Placeholder Sentinel * test: Cover the Sign-In Control Roles in the Default Theme * test: Wait for the Floating Label Transition Before Reading It * test: Read the Floating Label Scale Property * fix: Keep Button Heights on Theme Roles and Honor Reduced Motion in Floating Fields
* feat: Show Lia on the Welcome Screen Adds the opt-in Show Lia setting (off by default) and the interface.mascot deployment flag (allowed by default). Lia mounts only on the landing page, loads lazily after first paint, stands on the composer's top edge clear of the greeting, reacts to typing, files and theme changes, and speaks through localized bubbles. She is decorative and hidden from assistive technology. * fix: Keep Lia's Long-Message Reaction Re-Armed and Pointer Reads Per Frame Deleting a message back under 280 characters now re-arms the long-message reaction, pointer handling reads layout at most once per animation frame, and the ChatView specs stub Lia like their other children. * test: Open Settings from the Phone Drawer in the Lia Scenarios The opt-in scenario no longer resets the stored preference on reload, and both Settings scenarios open the account menu from the mobile drawer on phones. * fix: Measure Lia's Caret Like the Composer and Label Her When Idle The caret mirror copies direction, alignment, indentation, wrapping and box sizing, so right-to-left and wrapped text measure like the composer. Hovering Lia between activities now says she is hanging out instead of showing nothing. * fix: Wave Off Assistants Sends and Keep Lia's Canvas and Bubble Off Welcome Content * fix: Keep Lia's Speech Bubble Inside Her Stage * fix: Wrap Long Translations in Lia's Speech Bubble * fix: Keep Lia's Long-Message Reaction Until It Plays and Pin the Scenario Greeting * fix: Make Only Lia's Body Clickable So She Fits Beside Long Greetings * fix: Let Lia Stand Beside the Composer When the Greeting Fills Its Top * feat: Let Users Drag Lia Around and Keep Her Near the Composer * test: Cover Picking Lia Up and Setting Her Down on the Composer * refactor: Keep Lia's Preference Inside Her Feature * fix: Let Keyboard Users Pet Lia and Move Her With the Arrow Keys * test: Shift Only the Wall Clock for Lia's Morning Greeting * test: Measure Lia's Keyboard Walk Both Ways So the Greeting's Width Cannot Pin Her * fix: Bring Lia Back When a New Chat Opens During Her Farewell * fix: Start Lia's Reactions on Her Own Clock After a Pause Without Room * fix: Load Lia Through Stale-Asset Recovery and Skip the Farewell Before She Appears * feat: Mark the Lia Settings Toggle as Beta
…Chat-AI#16815) * feat: Show the Conversation Pull Request in the Sidebar List Add a batch lookup route and a sidebar row mark: the state icon with the CI dot, opening the same card beside the row on hover. The row keeps the conversation's own title. * fix: Address Review Findings on the Sidebar Pull Request Batch and Row Mark Cap the whole batch with a configurable deadline, make the row mark a keyboard-reachable button that opens the card on focus, refresh rows when the window regains focus through the shared batch, and show a retryable failure state instead of treating a failed first lookup as no pull request. * fix: Send Sidebar Pull Request Batches One at a Time Queue every batch request behind the one before it, so an oversized list or an overlapping flush cannot multiply the server's configured lookup concurrency, and bound how long one request may hold the queue so a request that never answers cannot stop the rest. * fix: Keep the Batch Request Timeout Above the Server Deadline Default the client's request timeout to just past the longest batchTimeoutSeconds a deployment may configure, so a queued request never starts while the previous request's server-side lookups are still running. * fix: Keep Batch Lookups Inside the Concurrency Limit and Per-Entry Failures Per Entry Share one lookup limiter across every batch request so lookups that outlive a request's deadline keep their slot, answer a missing token only for the conversations that needed it, and point the row at its pull request description only while that text is in the page. * fix: Bound Batch Reads, Scope Concurrency Per Credential, and Gate the Sidebar on the Batch Version Start the batch deadline when the request arrives and bound the config and lane reads, count lookup slots per credential, advertise a batch route version and ask only a server that has it, take no row space for an absent mark, show a failed refresh over a cached empty answer, keep a malformed response from stalling the request queue, and repair the lane recording tests that still used a mock removed on dev. * fix: Move Capability Resolution Into the Package and Harden the Batch Route and Queue Resolve the pull request startup capabilities in packages/api so the route stays wiring only, bound the config and lane reads by the configured deadline, merge identical lanes before taking limiter slots, fall back to the single route when a replica has no batch route, and dispose the batch queue when the signed-in user changes. * fix: Abort the Batch Fallback With Its Request So the Queue Never Overlaps It Give the batch fetcher the request's abort signal and pass it to every single-route call, abort a request that times out or is disposed, and stop the fallback workers from starting more calls once it has. * fix: Forward the Abort Signal to the Batch POST Pass the request's abort signal through the batch fetcher, the data-provider call and Axios, so a batch request that times out or is disposed is cancelled instead of continuing beside the next one, and settle a request promptly when it is aborted. * fix: Close the Pull Request Lookup Follow-Ups and Cancel Abandoned Sidebar Rows
…-Chrome Themes (LibreChat-AI#16833) * fix: Keep Chrome Surfaces and Destructive Confirms Legible in a Quiet-Chrome Theme * fix: Soften Remaining Inline Destructive Triggers and Canonicalize Zero Chrome Alpha * fix: Keep Pressed Feedback on the Quiet-Chrome Floating Control and Cover the Quiet Surfaces * test: Scope the Quiet Surface Scenarios to the Header * fix: Keep the Two-Factor Disable Trigger on the Soft Destructive Variant
…hat-AI#16827) * feat: Add 10, 11, 13 and 15px Steps to the Theme Type Scale * test: Prove the Off-Scale Type Steps in the Mock Harness * style: Sort cn Imports * refactor: Name the 13 and 15px Steps 1xs and 1sm * test: Probe the Type Step Roles Instead of Unused Utilities
…at-AI#16823) * refactor: Route Stylesheet Colours Through Theme Variables and Gate CSS Literals * fix: Run the Colour Check Through Its Own Script * fix: Read Numeric Fallbacks Inside Colour Function var() in the Colour Literal Check
) * fix: Polish the Pull Request Chip and Card Header Shrink the GitHub link icon and keep its hover on the icon only, drop the agent avatar from the chip so only the pull request icon remains, and open the hover card below the chip. * fix: Scale the GitHub Icon With a viewBox and Rebase the Card Placement onto the Shared Panel
…ssions (LibreChat-AI#16829) * refactor: Clear Raw-Color, Unknown-Class and Arbitrary-Value Suppressions in Auth, Nav and Endpoints * refactor: Use the Registry Type Steps in the Nav Shortcut Chrome * refactor: Prune Recorded Suppressions the Registry Type Steps Clear
…iants (LibreChat-AI#16863) * refactor: Clear Chat Input Design Suppressions Through Existing Variants * test: Cover the Chat Composer Send Path After the Suppression Cleanup * refactor: Keep the FileUpload Action on Its Ghost Pressed Fill
…16861) * a11y: Ring Tabs, Table, Dropdown and Menu Items in the Focus Control Role * test: Tag the Focus Primitives Scenarios Literally * test: Match the Dark Focus Rule That Yields to Outline Utilities * refactor: Keep Menu Items and Table Rows on Their Existing Focus Treatment * refactor: Leave Tabs and Dropdown on the Global Focus Outline * test: Assert Both Outline Utility Exclusions in the Dark Focus Rule
…at-AI#16819) * feat: Derive the Theme Cache Version and Close the Color Token Drift * feat: Add a Button Padding Role for the Default Size * test: Run the Boot Script Through the Version Injection * fix: Retain Signed-Out Provenance and Tighten Token Declarations
…Chat Package (LibreChat-AI#17170) * refactor: Move the Queue Drain, Reveal and Recovery Hooks into the Chat Package * test: Run the Unmounted Steer Retry on React Query Itself
…Stream Errors (LibreChat-AI#17256) * fix: Restrict Stop to the Generation's Owner and Contain S3 Ingest Stream Errors The legacy abort route passed any caller-supplied conversation id straight to GenerationJobManager.abortJob, so a signed-in user who knew another user's conversation id could stop that generation and receive its partial output. abortOwnedGeneration now reads the job first and stops it only for its owner and tenant, fenced to the epoch it read; anything else reads as not found. saveURLToS3 piped Readable.fromWeb into the byte-limit transform with .pipe, which does not forward source errors. A body that failed mid-download emitted an unhandled error and left the upload awaiting forever. Use stream.pipeline, as the CloudFront strategy already does. * test: Cover Stop Ownership on the Legacy Abort Route * test: Scope the Parts Attachment Check to the Composer Tray The file name also labels a hidden recent-file row once earlier tests in the shard have left one mounted, so the unscoped locator resolved to two buttons.
…ibreChat-AI#17262) A tool call that is the only one in its group, inside a phase of several, renders its panel bare: open, with no row of its own. The full-content request only fired when the reader expanded the card, so a bare panel stayed on the server preview, showing truncated output and keeping its copy buttons disabled. Bash, generic and the other useToolCallState cards now request the stored part whenever they render bare.
…t-AI#17203) * feat: Paint Inline Deployment Themes From the First Frame * test: Point the Theme Pin Mutations at the Provider Bundle
…ibreChat-AI#17258) * fix: Keep API Keys and Internal Errors Out of Logs and Responses The log redaction patterns did not cover the appid query parameter, so a failed Wolfram request logged its AppID with the axios request URL. appid now joins the redacted token and query names. OpenWeather returned a fetch error's message to the model verbatim, and node-fetch puts the full request URL, appid included, in that message. The tool now passes it through redactMessage, as ToolService does. The public startup config route and the unauthenticated password reset route sent raw error text on unexpected failures. Both now answer with a fixed message and keep the detail in the server log. * refactor: Format Tool Error Text in packages/api * fix: Redact appid Metadata Keys in Structured Logs
…hat-AI#17259) * perf: Index Hot Lookups and Project the Remote Models List checkBan reads the KeyvMongo logs collection by key on every request when bans are enabled, BYOK requests read Key by user and name, and agent tool loading reads Action by agent_id or assistant_id. None of those fields had an index, so each read scanned its collection. The Key and Action schemas gain indexes, and the KeyvMongo store builds a key index on first use unless the deployment disables auto indexing. The remote /v1/models routes loaded whole agent documents, including the unbounded versions history, to read six fields. getAgentModelSummaries loads only those fields. * test: Authenticate the Models List Scenarios With an Agent API Key
…lures (LibreChat-AI#17261) * fix: Hash Off the Event Loop and Surface API Key Lookup Failures Registration, email verification, password reset and verification resends hashed and compared with bcryptjs's synchronous calls. bcryptjs is pure JavaScript, so each call blocked the event loop for every request in the process. They now use the promise APIs, and the password reset dependencies are async. validateAgentApiKey caught its own query failures and returned null, so a database outage answered remote callers with 401 Invalid API key. It now lets the failure reach requireApiKeyAuth, which answers with a 500. * fix: Run bcrypt on a Worker Pool in packages/api bcryptjs's promise API still computes on the main thread, only in chunks of up to 100 ms, so concurrent registrations and resets kept stalling unrelated requests (four cost-10 hashes delayed a 5 ms timer by about 190 ms). hashSecret and compareSecret now run bcryptjs on a small worker_threads pool in packages/api, and AuthService.js calls them. * feat: Configure the Password Hashing Worker Count * fix: Verify Login and Step-Up Passwords on the Hash Pool
…ut (LibreChat-AI#17270) * fix: Contain Download and Speech Stream Failures and Cap Speech Input The code output download piped the Code API stream with .pipe, which adds no error listener, so a body that failed mid-stream (a bad gzip body, a reset) became an uncaught exception and the process exited. pipeToResponse uses stream.pipeline, ending the response and destroying the upstream when the client leaves. Text-to-speech piped provider streams the same way and waited only for 'end', so a provider error was uncaught and a client disconnect left the chunk loop waiting. pipeSegment resolves on end and rejects on an error or a disconnect, which ends the loop. A speech request had no length cap, so one request could fan out into thousands of serial paid provider calls. speech.tts.maxInputChars bounds it (default 20,000 characters). * docs: Document the Speech Input Cap in the Example Config * fix: Reject a Speech Segment When the Client Already Left * fix: Tear Down Both Ends of a Failed Speech Segment and Cap Streamed Speech A failed provider segment now destroys the response as well as the source, so a half-written answer cannot hang the client, and a response-side error rejects the segment instead of going unhandled. Automatic playback reads a message only up to speech.tts.maxInputChars, so long messages cannot fan out past the cap either. The download scenario now checks the behavior .pipe lacked: leaving a code download closes the upstream connection right away. * fix: Keep a Late Response Write Error From Going Unhandled * test: Key Slow Code Downloads by File and Send a Browser User Agent * fix: Read Speech Up to the Cap Instead of Refusing It Manual speech now synthesizes the text up to speech.tts.maxInputChars, the same as automatic playback, through capSpeechInput, so the CJS service only passes the capped text along and the request keeps its existing error contract. A streamed message that reaches the cap exactly now finishes, and a segment that fails before any audio went out leaves the response open for the caller's HTTP error. * fix: Count Only Text Against the Speech Cap
…st Paint (LibreChat-AI#17264) * fix: Follow the Interface Direction in Radix, the Composer and First Paint Wrap the app in a Radix DirectionProvider driven by i18n so Tabs, Select and menus stop rendering LTR subtrees in right-to-left locales, and swipe toasts toward the inline end. Chat direction becomes auto, ltr or rtl (auto by default; stored LTR/RTL values are kept). The composer applies a forced direction as a dir attribute instead of reversing rows, which double-flipped under an RTL document, and the text fields default to dir=auto. The unused Jotai chat direction atom that pinned every TextareaAutosize to ltr is removed. index.html sets dir before first paint, and the language setting no longer races i18n over document.lang. * fix: Keep the Empty Composer Placeholder on the Interface's Reading Edge
…g Speech Truncation (LibreChat-AI#17278)
…n RTL (LibreChat-AI#17266) * fix: Anchor Sidebar, Drawer and Panels to the Inline Edges in RTL * test: Cover the Mirrored Shell in RTL with Scenario Specs * test: Wait for the Sidebar Width Transition Before Dragging * test: Cover a Live Switch to RTL With the Artifacts Panel Open
…reChat-AI#17269) * fix: Use Logical Spacing and Positioning in the App Shell * test: Cover Logical Shell Sides in Arabic and English
…hat-AI#17267) * fix: Mirror Chat Surfaces For RTL Layouts * fix: Keep Short Subagent Ticker Lines at Their Reading Start Adds RTL chat scenarios covering code, markdown blocks, sibling arrows and virtualized lists. * fix: Resolve Quote and List Direction From Their Content dir=auto skips descendants that carry their own dir, so a quote or loose list holding dir=auto paragraphs always resolved left-to-right. Lists now take one direction so markers and indent stay on the same side. * fix: Keep Tables, Callouts and Trace Axes on One Direction Tables take one direction from their content so cell borders share a frame; strong-direction detection skips Arabic-Indic digits, separators and marks; handoff and answer callouts use a logical start border; trace tick and range labels stay on the LTR axis. * fix: Treat Every Script's Letters as Strong Direction Direction detection now keys on Unicode letters, so Devanagari, Thai and other LTR scripts resolve LTR. E2E specs that selected rows by pl-6 now select ps-6. * test: Cover the Shared Strong Direction Helper on Its Own * fix: Read Bidi Marks and Native Script Digits as Strong Direction * fix: Approximate Bidi Classes by Block So Symbols and Numerals Resolve * fix: Resolve Strong Direction From Unicode Bidi Class Tables * docs: Note How the Bidi Tables Are Generated and Where They Differ * fix: Generate the Bidi Tables From Unicode 17 Including L-Class Marks
…AI#17265) * fix: Mirror Shared Primitives For RTL Layouts * fix: Import the Direction Helper Relatively in InfoHoverCard * test: Cover Mirrored Switch and Dialog Close in RTL * fix: Keep the Focused Sign-In Label Inside Its Field in RTL * fix: Mirror by Element Direction and Re-Resolve Side Placement on Open * test: Pin RTL Scenarios to the Element Direction and Expect a Trailing Number Input * fix: Keep Time Column Arrow Keys Vertical in RTL * fix: Keep :dir() Selectors Through CSS Minification * chore: Declare lightningcss for the Client Build Config * fix: Keep SelectDropDown Left and Right Icon Sides Physical * fix: Fall Back to the dir Attribute Where :dir() Is Unsupported * fix: Leave Nested LTR Islands Unmirrored in the dir Attribute Fallback * fix: Resolve the Slider Direction From Its Nearest dir * fix: Resolve the Nearest dir at Any Depth in the :dir() Fallback * fix: Re-Resolve the Slider Direction When a dir Attribute Changes * fix: Keep the Provider Direction for a Slider Without a dir Ancestor * fix: Read an Automatic dir From the Computed Direction for the Slider * fix: Prefer the Computed Direction When Resolving an Element's Direction * fix: Re-Resolve the Slider Under a dir=auto Boundary When Its Content Changes * fix: Keep the Mirrored Combobox Placement Across Rerenders * refactor: Let the Slider Read Its Direction From the Radix Provider * fix: Space a Trailing Combobox Option Icon From Its Label
LibreChat-AI#17279) * test: Cover Interface and Chat Direction Scenarios * test: Pin the Default Textarea Direction to Auto * refactor: Keep the Chat Direction Preference in Jotai * test: Drive Direction Scenarios Through Phone Settings and a Held Bundle
…ibreChat-AI#17131) * refactor: Move the Resumable Generation Start Into the Chat Core * fix: Call a Host Transport's Start on the Transport Itself Forwarding transport.start as a bare function rebound this to the resumable host, breaking any host transport whose start is an instance method.
…AI#17133) * refactor: Split useResumableSSE Into Thin Host Bindings * refactor: Name the Resumable Binding Modules With Single Words
* refactor: Split useResumeOnLoad by Responsibility * refactor: Name the Resume Hooks' Modules With Single Words
…7136) * refactor: Split useEventHandlers by Responsibility * refactor: Name the Event Handler Modules With Single Words
… Jotai (LibreChat-AI#17138) * refactor: Move Run Display, Live Attachment and PTC Trace Atoms to Jotai * fix: Evict Reset PTC Trace Atoms From the Family Cache
Member
Author
|
Screenshots uploaded here because upstream attachments require upstream write access. The change is submitted for review at LibreChat-AI#17300; this evidence mirror is closed. |
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
When a parent agent has already streamed text or reasoning and then starts a specialist that needs MCP OAuth, the sign-in event reuses index zero and can collide with existing content. The event can also target the submission's old placeholder after the model response has replaced it. Users see a waiting specialist without the sign-in button needed to continue.
This keeps synthetic OAuth prompts outside model content indices, keyed by flow call ID, and routes preliminary OAuth steps to the live response. Signing in resumes the existing execution; reload restores one prompt; completion, failure, and cancellation remove only the matching prompt. Parent reasoning, tool calls, and sibling output remain intact.
How it works
The normal content prefix retains its absolute model indices, including sparse holes. OAuth UI rows form a separate suffix. Replayed flow IDs update that suffix in place, and late completion of an older flow cannot remove its replacement. The stream reducer resolves a preliminary OAuth step to the current model response before recording its identity, so its later deltas use the same response.
Type of change
Testing
Tested environments/configuration: Chromium, deterministic local model, real Streamable HTTP MCP SDK with a synthetic OAuth provider, disposable in-memory MongoDB, isolated Express server. No deployed service or real credentials.
Automated tests:
devwith a parent text preamble because the sign-in button is missing. It passes with this change, including reload and successful OAuth continuation of the same parent execution.Screenshots / recordings
Same Chromium viewport and specialist request. The unchanged base never exposes the sign-in button and eventually stops; the fixed branch exposes it alongside the parent call while waiting for consent.
Risk / compatibility
No OAuth token storage, scope, permission, timeout, or server configuration changes. This reuses the existing localized sign-in UI and existing stream events. Normal model parts keep their absolute indices. The fake OAuth fixture remains pending by default and approves only when the test explicitly adds its approval flag.
The separate SDK diagnostic extension is LibreChat-AI/agents#632; this UI fix does not depend on it.