|
Some checks are pending
Backend Unit Tests / Build packages (push) Waiting to run
Backend Unit Tests / Codegraph select (push) Waiting to run
Backend Unit Tests / TypeScript type checks (push) Blocked by required conditions
Backend Unit Tests / Circular dependency checks (push) Waiting to run
Backend Unit Tests / Tests: api (shard 1/3) (push) Blocked by required conditions
Backend Unit Tests / Tests: api (shard 2/3) (push) Blocked by required conditions
Backend Unit Tests / Tests: api (shard 3/3) (push) Blocked by required conditions
Backend Unit Tests / Tests: data-provider (push) Blocked by required conditions
Backend Unit Tests / Tests: data-schemas (push) Blocked by required conditions
Backend Unit Tests / Tests: @librechat/api (shard 1/4) (push) Blocked by required conditions
Backend Unit Tests / Tests: @librechat/api (shard 2/4) (push) Blocked by required conditions
Backend Unit Tests / Tests: @librechat/api (shard 3/4) (push) Blocked by required conditions
Backend Unit Tests / Tests: @librechat/api (shard 4/4) (push) Blocked by required conditions
Codegraph E2E Votes / vote (full suite) (push) Waiting to run
Docker Dev Branch Images Build / publish (push) Waiting to run
Frontend Unit Tests / Codegraph select (push) Waiting to run
Frontend Unit Tests / Build packages (push) Waiting to run
Frontend Unit Tests / TypeScript type checks (client) (push) Blocked by required conditions
Frontend Unit Tests / Tests: @librechat/client (push) Blocked by required conditions
Frontend Unit Tests / Tests: Ubuntu (shard 1/2) (push) Blocked by required conditions
Frontend Unit Tests / Tests: Ubuntu (shard 2/2) (push) Blocked by required conditions
Frontend Unit Tests / Vite build verification (push) Blocked by required conditions
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
* refactor: read status fill labels from the theme token Feature call sites paint the label on bg-surface-destructive, bg-surface-submit and the bg-status-*-strong fills with the raw text-white utility, while the shared Button, IconButton and Toast primitives already use text-text-on-status. The token exists so the label colour can differ per theme mode, and hard-coding white pins it. Point every call site at text-text-on-status, and compose DeleteIconButton onto the Button destructive variant rather than re-declaring the fill classes. Five call sites paired a status fill with the wrong token entirely (text-text-secondary, text-text-inverted) or used the non-strong hue as a solid fill; those move to the -strong fill with the on-status label. Tooltip.css and the app stylesheet copy of the same rule read colour from --text-primary instead of literal black and white, and the dead outline: var(--bg-surface-hover) in Dropdown.css becomes a real 2px token outline, since that variable is not declared anywhere and the focus ring never rendered. --text-on-status is 255 255 255 in both shipped themes, so this is a no-op for the light and dark palettes. * feat: add high contrast light and dark appearance modes Adds two appearance modes to the theme setting for users who need more than the standard palettes, plus contrast resolution for the system mode. The palettes are complete IThemeRGB maps rather than partial overrides, because a token left to fall back to defaultTheme or darkTheme would reintroduce a mid-grey the mode exists to eliminate. They resolve as a built-in ThemeDefinition that outranks a deployment's custom theme, since a contrast choice is an accessibility need rather than a branding preference. Text clears WCAG AAA on every surface it can render on, including the hover and active fills. Borders, rings and series marks clear the 3:1 non-text floor. Solid fills clear AAA against both their label and the page, which is what the per-mode text-on-status token buys: each mode paints its fills on the far side of its own canvas, dark fills under a white label on white and bright fills under a black label on black, so the two ratios coincide instead of pulling apart. The system mode now follows prefers-contrast the same way it already follows prefers-color-scheme, so a user who has switched on Increase contrast or Contrast themes gets the accessible palette without first finding this setting. isDark reports high-contrast-dark as dark; isHighContrast answers what the user picked, which is what the theme toggle preserves when it flips the scheme; resolvesToHighContrast answers whether the palette applies. The icon toggle keeps a contrast choice when it flips the scheme, and announces which of the four states it landed in. * feat: cover the non-tokenized chrome in high contrast The token layer reaches every IThemeRGB surface, but a good deal of the stylesheet predates it and holds literals the palette cannot move. Under html.high-contrast: The typography variable block is 32 hard-coded hex values, and message content carries prose dark:prose-invert, so the invert half is what dark mode reads. Both halves now resolve from tokens: prose links were 3.77:1 on a black canvas and 5.40:1 on a white one, and every rule and border in the set sat below the 3:1 non-text floor in one mode or the other. The highlight.js palette is raw hex and tops out at AA, worst cases 4.84:1 for dark attributes and 5.32:1 for the alpha-blended dark comment; these reuse the palette's own hues at AAA on each canvas. Focus perimeters go to 3px and read the ink token rather than literal black and white. Selection was left to UA system colours and is now an explicit inversion. Ring opacity is pinned at full strength for the controls that halve their own. Popover and tooltip elevation trades a black shadow, which separates against nothing on a black surface, for a token border. Prose links carry an underline so they are not distinguished by colour alone. The switch track, the scrollbar thumb and track, the markdown structure borders and the body background that .dark pins to #212121 all move onto tokens. * feat: draw panel and dialog edges in high contrast Adds a high-contrast: Tailwind variant to the shared preset, so styling can be scoped to the contrast modes the way dark: is scoped to the dark class. Deliberately not named contrast-more, which Tailwind already ships as the raw prefers-contrast media query: this follows the resolved app mode, so it covers an explicit choice as well as the OS preference. Two surfaces rely on a colour step that high contrast removes. The sidebar's right edge is a resize separator that is transparent until hovered, which is fine where surface-primary-alt carries the boundary but leaves no edge at all when both sides are the same pure white or black. Dialogs are borderless and lean on a black shadow, which separates against nothing on a black canvas. Both now draw a real edge in the contrast modes only. The dialog change sits in the Radix content primitives and the two shared templates so the feature dialogs inherit it, plus the settings panel, which is Headless UI and bypasses them. OGDialogTemplate carries border-none, so the variant restores the border style as well as the width. * fix: address PR review bot findings chatgpt-codex-connector: Move the syntax palette into semantic theme tokens. The highlight.js colours were raw hex in style.css, so a palette change had to be made twice and neither copy was covered by the registry's completeness check or any contrast test. They are eight rgb-syntax-* tokens now, declared across all four theme maps and consumed as CSS variables, which lets the whole high-contrast block for highlight.js go away. Two guardrails come with them: the contrast modes assert AAA for every syntax role on the code surface, and the stylesheet is pinned to the runtime themes with no hard-coded hex allowed in an .hljs rule. Two values could not be carried over literally: the dark comment and meta colours were alpha-blended whites, so they are stored as the flattened equivalents over the #212121 code surface. Everything else, including the dark code text, renders byte-identical to before. Declare Tailwind as a preset dependency. The preset ships as a raw file through the ./tailwind-preset export while tailwindcss is only a devDependency, so require('tailwindcss/plugin') could fail to resolve for a consumer under pnpm or Yarn PnP. Dropped the require instead of adding a peer dependency, since Tailwind accepts a plain function in plugins and the wrapper only adds option handling this variant does not use. Route remaining solid controls through semantic status roles. The assistant builder kept bg-red-600/bg-red-700 and bg-green-500 with text-white, which the built-in palette cannot reach, leaving them below the mode's contract at roughly 2.28:1 for the green controls. All five now use the destructive and submit surfaces with the on-status label, and the two that also suppressed their focus ring get a semantic one. * fix: address second round of PR review bot findings chatgpt-codex-connector: Migrate the builder submit to semantic status colors. AssistantPanel's submit button kept btn-primary, which hardcodes #10a37f and white in style.css, alongside a raw green hover and focus border. It uses the submit surface with the on-status label now, and drops btn-primary rather than fighting its specificity. Left .btn-primary itself alone: restyling every primary button in the app is not this PR's business. Give provider avatars contrast-safe brand colors. The white glyph sat at 2.30:1 on OpenAI green, 2.45:1 on Anthropic tan and 3.41:1 on GPT-4 purple. brands was a single theme-wide set, and a brand fill has to carry a glyph and stand out from the canvas, both of which flip between modes, so one set cannot serve both at enhanced contrast. ThemeModeDefinition takes an optional brands block now, resolved after the theme-wide set, and high contrast declares dark tints under a white glyph for light and bright tints under a black glyph for dark. Worst pair is 8.76:1 for both the glyph and the silhouette, with provider hues still recognisable. Brand validation is shared between the two levels rather than duplicated. Raise active-surface contrast against the canvas. The active fills sat at 1.48:1 and 1.98:1 on white, 1.93:1 and 2.91:1 on black, and since every ink token collapses to one colour here, dozens of call sites were left conveying the selected state with a sub-3:1 fill alone. The fills now clear 1.4.11 at 3.14:1 to 4.29:1. That costs the AAA label on those two fills, and the trade is unavoidable: above the luminance where a fill clears the 3:1 state floor, its own label cannot reach 7:1, and below it the state disappears. No integer grey satisfies both. 1.4.11 is Level AA and 1.4.6 is Level AAA, so the state wins and the labels land at 4.89:1 to 6.69:1. The spec now separates canvas and hover surfaces, which keep AAA, from the active fills, which assert the state floor and an AA label. * fix: address third round of PR review bot findings chatgpt-codex-connector: Drop the overriding btn-primary class from Select. My previous round assumed Tailwind utilities would win here by source order; they do not. In the built stylesheet .btn-primary sits at byte 136886 and .bg-surface-submit at 69233, equal specificity, so the hardcoded green won and that button had never followed the palette. Removed btn-primary, the same way as the submit button beside it. Preserve contrast mode when theming Mermaid output. isDark collapses a contrast mode onto the same boolean, so the cache key was unchanged across light to high-contrast light and an already-rendered diagram survived the switch untouched. Both diagram paths take the resolved contrast now: the cache key gains a suffix, and the config carries themeVariables built from the contrast palette, since Mermaid's own neutral and dark themes hold a palette no theme token can reach. Diagrams render on the canvas with ink nodes, ink edges and ink labels, which is 21:1 for every mark and label. Artifact diagrams go through the same helper: getMermaidFiles takes the flag, switches the generated document to Mermaid's base theme, which is the only built-in that honours themeVariables, and paints the page with the contrast canvas instead of the fixed #212121 or #FFFFFF. The helper returns undefined outside the contrast modes, so standard themes keep their current rendering exactly. * fix: publish resolved contrast through theme context chatgpt-codex-connector: notify consumers when system contrast changes. Under `system` the contrast comes from a media query, so `theme` stays `system` when the OS preference flips and React has nothing to rerender on. The listener I added last round only touched the root element, which is enough for CSS but not for anything computing from the resolved value: the Mermaid cache key and the artifact files would have kept the old palette while the rest of the app switched. ThemeContext exposes `highContrast` now, held as state and set wherever the mode is applied, which covers both an explicit choice and a media change. `useMermaid` and `useArtifactProps` read it from context instead of deriving it locally. `resolvesToHighContrast` stays exported as the predicate the provider itself resolves with. The existing media-change test now also asserts the context value moves, not just the class on the root, since the DOM assertion alone passed before this fix. * fix: publish the resolved scheme through theme context too chatgpt-codex-connector: publish resolved scheme changes through context. Same staleness as the contrast case, one field over. With the mode at `system` and contrast already on, an OS colour-scheme change reapplied the DOM palette but `setHighContrast(true)` was a no-op and `theme` stayed `system`, so no consumer rerendered and the diagram hooks kept the previous `isDark` result. This half predates the PR: those hooks derived the scheme from `theme` before it too, so a scheme flip under `system` has never reached them. ThemeContext exposes `resolvedMode` alongside `highContrast`, both set wherever the mode is applied. The two diagram hooks read the scheme from context instead of calling isDark themselves. The other isDark call sites are left alone: none of them cache, so they recompute whenever something else rerenders them, and sweeping every consumer onto the context value is a wider change than this PR should carry. * fix: address sixth round of PR review bot findings chatgpt-codex-connector: Restore a visible focus cue for dropdown options. `.select-item` blanks its own outline with `outline: none !important`, so the contrast focus rule never landed and the navigated option was marked only by a surface-hover fill at 1.48:1 on white and 1.93:1 on black. Hover stays deliberately soft in these palettes, since it is transient and can afford an AAA label, so the cue has to be a perimeter: a 3px inset outline on the active and focused option, matching the !important it has to beat. Verified with real keyboard navigation that the outline resolves to the ink colour in both modes. Apply contrast tokens to artifact controls. getMermaidFiles took the contrast flag last round but still built its controls from the standard palettes, whose fixed greys leave the zoom label below AAA and whose 10%-alpha border and divider sit below the 3:1 non-text floor against a pure canvas. The controls now come from the same tokens as the diagram: canvas fill, ink border and label, the active surface for hover, and no shadow, since a black shadow separates against nothing there. * fix: ignore undefined brand overrides when resolving a theme chatgpt-codex-connector: ignore undefined mode brand overrides. Partial<IThemeBrands> lets a key be present with undefined, and the brand validator accepts it, so spreading a mode block over the inherited set could overwrite a brand with nothing. Colors survive this because mapColors skips undefined, but every brand token is written to the DOM unconditionally, so the avatar would have lost its fill instead of falling back the way a partial theme promises. Both spreads now drop undefined entries, which covers the theme-wide set as well as the mode block, and keeps ResolvedThemeDefinition.brands honest about being fully populated. * fix: address eighth round of PR review bot findings chatgpt-codex-connector: Guard media queries during server rendering. The state initializers I added read prefers-color-scheme and prefers-contrast synchronously during render, so a server-rendered provider threw before producing markup. That was a regression: nothing in the provider read a media query during render before. Both reads go through a helper that returns false without a window, the way the storage helpers already tolerate its absence, so the server renders the light palette with no contrast override and hydration applies the real values. The subscription effect is guarded too, which also covers a host that has no matchMedia at all. Keep Mermaid pie slices distinct in contrast mode. My own regression: the contrast variables set primaryColor, secondaryColor and tertiaryColor to the canvas, and mermaid derives pie1 through pie3 from those, so every slice collapsed into the background and into its neighbours. The pie slots come from the palette's series ramp now, which is the categorical scale already built to clear the mark floor on that canvas and stay separable under simulated deuteranopia. Twelve slots wrap over seven, as mermaid's own palettes do. Remove the raw white override from bookmark submit. The save button passed text-white into the shared submit variant, which tailwind-merge resolved in favour of the local class, leaving white on the bright submit fill at 1.40:1. Dropped the override so the variant's token applies. Preserve the high-contrast canvas in screenshot exports. The export chose between two fixed colours, so a contrast export was filled with #171717 instead of the mode's canvas. It reads the resolved canvas token now, with the old pair as the fallback. Theme markdown artifact previews in contrast modes. useArtifactProps forwarded the appearance only to the mermaid branch. getMarkdownFiles takes it now and appends a contrast block derived from the palette; being unconditional it also outranks the sheet's own prefers-color-scheme query, so an explicit contrast choice is honoured whatever the OS reports. * fix: migrate agent version controls to semantic status roles chatgpt-codex-connector: migrate agent-version controls to semantic status roles. The active-version marker and the Restore action used raw green fills with text-white, about 2.28:1 and 3.30:1, and the built-in palette cannot reach either. The marker takes the strong success fill with the on-status label, and Restore takes the submit surface, matching the assistant builder migration. Also finished the rest of that component's active-version treatment rather than leaving it half migrated: the card border and tint, the title, and the Current chip now use the success subtle, border and strong roles. The same indicator was expressing one state through both raw and semantic colour otherwise. ToolCard's native badge and selected tick were the same shape, raw emerald under white, so they move to the strong success fill too. Left alone: the HTTP method badges in ActionsTable/Columns.tsx, the tool-kind colours in items/icons.ts, and CategoryFilter's active border. Those are categorical identity rather than status, so mapping them onto status roles would be wrong; they need the treatment provider brands got, which is its own change. * fix: address tenth round of PR review bot findings chatgpt-codex-connector: Use opposing ink for pie-section labels. My own regression from the slice fix: the series ramp deliberately sits on the far side of the canvas so slices are visible, which makes the canvas ink the wrong colour for a label drawn inside one. Section labels take the on-status ink now, the same colour the palette uses for a label on any solid fill, while the title and legend keep the canvas ink because they are drawn on the canvas. Preserve the blue initializing status in standard themes. Also mine, from the first round: I moved this dot to bg-status-info-strong, and the strong info slot is a neutral grey in both standard palettes, so a blue indicator turned grey. Back on bg-status-info, with the pulse taking the on-status ink so it inverts with the fill rather than being a fixed white. Route action method badges through contrast tokens. I declined this last round as categorical identity rather than status; the reviewer's framing is better. The series ramp is precisely the home for categorical identity, it is contrast-checked per mode, and its slots are separable under simulated deuteranopia, so the verbs map onto it while staying close to their conventional colours. `delete` keeps a red by taking the error role, since destructive genuinely is a status. * fix: seed published theme values without reading a media query chatgpt-codex-connector: defer media-query resolution until after hydration. Guarding window stopped the crash but left the server and the first client render disagreeing: the server produced light and false while the client resolved the OS preferences during that same first render, so any child reading the published values hydrated against different context. Both are seeded from the mode string alone now. An explicit mode needs no query, so it publishes immediately and stays consistent with isDark; only system starts at the light palette with no contrast override, on both sides, and applyThemeMode publishes the resolved values from its effect after hydration. The pre-existing localStorage read in getInitialTheme has the same shape of problem for `theme` itself, but changing where the stored mode is read is a wider change than this and belongs on its own. * fix: address eleventh round of PR review bot findings chatgpt-codex-connector: - keep the active version timeline rail opaque so it clears the 3:1 mark floor in both high contrast modes instead of compositing to ~2:1 - balance the dark success fill (#088759) so the selected-tool marker, the timeline rail and the prompt-version chip keep a visible silhouette on the #212121 panel while the white label stays at WCAG AA - include the resolved scheme and contrast in the mermaid cache key even when a custom theme is supplied, so a contrast switch re-renders * fix: address twelfth round of PR review bot findings chatgpt-codex-connector: - select mermaid's base theme ahead of a caller-supplied theme in the contrast modes, after the config spread, so the contrast variables actually reach the diagram - ship the tooltip and popover contrast edges in the package stylesheets they belong to, so a consumer importing @librechat/client gets them * chore: sort imports in the theme registry, provider and specs * fix: override the markdown preview table header in contrast modes The appended contrast block answered the ink, the canvas and the cell borders but not the thead tint, so an explicit contrast choice on the opposite OS scheme left white text on #f6f8fa or black text on #161b22. The header now takes the palette canvas and reads through its bold cells and border, and a new guardrail asserts every colour the base sheet sets inside prefers-color-scheme is answered by the override. * fix: address thirteenth round of PR review bot findings chatgpt-codex-connector: - keep an OS-requested contrast when the scheme toggle runs under the system mode, by reading the resolved contrast rather than the stored appearance name - move the unchecked switch track into the theme token registry so the shared Switch keeps its track for consumers of @librechat/client, and drop the SPA-only high-contrast overrides it no longer needs * fix: address fourteenth round of PR review bot findings chatgpt-codex-connector: - migrate agent and assistant validation states off raw red utilities and onto the destructive text and border roles, so the messages, the field outlines and the required markers follow the contrast palettes - theme the file-source badges with series slots and the status label ink instead of fixed blue and yellow fills behind an alpha * fix: paint the loading canvas from the resolved appearance The bootstrap in index.html read the stored mode's scheme but not the OS contrast, so system plus prefers-contrast: more flashed the standard-dark #0d0d0d behind the pure-black palette for the whole application load. An unset mode also painted white on a dark OS, though getInitialTheme resolves it as system. Both branches now resolve the same way the theme provider does, and a new spec runs the shipped script to prove it. * fix: theme the markdown renderer failure message The notice painted when the marked CDN does not load carried an inline color:#e53e3e, the one colour the appended contrast block could not reach, leaving it at 4.13:1 on the high-contrast light canvas. It is a .markdown-error rule now, which the base sheet declares with the current red and the contrast block overrides with the palette's destructive ink. * fix: address PR review bot findings chatgpt-codex-connector: - Route shortcut, steer, warning, and help-link states through semantic theme roles. - Add contrast-safe Mermaid Gantt variables for task, status, section, grid, and label states. - Theme Mermaid artifact render failures with destructive text colors. - Apply native color-scheme behavior through ThemeProvider and restore host values. * fix: address follow-up PR review findings chatgpt-codex-connector: - Route conflicting shortcuts through the semantic warning border. - Give checked composer capabilities opaque semantic series borders. - Move search results and their fade onto the presentation token. - Restore a visible semantic focus ring on the virtualized results list. * fix: address third-round review findings * fix: address fourth-round review findings * fix: align accessibility theme after dev rebase * fix: address PR review bot findings chatgpt-codex-connector: - Route the steer and queue identities through semantic `status-warning` / `status-info` roles in `Chat/Steering/identity.ts`, so the receipt label, its pulse dot and every Zap/Clock mark move with the theme instead of staying pinned to amber-500/600 and cyan-500. Fixes the high-contrast light failures (3.19:1 label text, 1.97:1 and 2.43:1 marks) and the default light label, which was also below the 4.5:1 text floor. - Pair each Monaco theme with the canvas it paints in `ArtifactCodeEditor`, so the transparent `@monaco-editor/react` loading view no longer flashes the light `surface-code` fill before the `vs-dark` editor mounts outside high contrast. * fix: declare the new dev theme tokens in the high contrast palettes dev added rgb-text-muted and the two chart widget tokens after this branch last rebased. The high contrast palettes did not name them, so the widget canvas and muted text fell back to the standard themes' greys, which the palette coverage spec caught. Both modes now take the plain canvas, pure ink and a pure-ink edge, and the contrast tables cover the new tokens. * style: sort imports in the specs this branch touched The added imports put ArtifactCodeEditor, ShortcutRecorder and OptionToggle out of the repo's import order, which the static-checks import-sort gate rejected. * fix: address fifth-round review findings chatgpt-codex-connector: - Preserve the pressed treatment on a disabled OptionToggle, so a tool made programmatic-only keeps showing the Intent state aria-pressed still reports. - Expose high contrast from the auth appearance control: the scheme toggle preserves contrast but never introduces it, so a logged-out user had no way to reach the palette. Adds a contrast toggle beside it, and the scheme toggle now shows the scheme rather than duplicating the contrast glyph. - Resolve system contrast from prefers-contrast: custom and forced-colors: active as well as more, since a Windows Contrast Theme never reports more. Mirrored in the index.html loading bootstrap and the theme README. - Route the remaining raw palette utilities through theme roles: agent success checks (Action, AdvancedPanel, ToolSection) to status-success, the favorited tool star to series-4, the orchestration Beta pill to brand-purple, the temporary-composer accent to series-6, and the pending quote marks to status-info. - Override the legacy btn-neutral chrome in the contrast block, whose hard-coded edge and hover fill sat at 1.1:1 and 2.09:1 on the new canvases. Rebased onto dev. * fix: mark the selected tab and theme placeholder ink in contrast modes Two states rendered invisibly under the high contrast palettes, both verified in a browser before and after: - Radix tab triggers mark selection with `surface-tertiary`, which is the plain canvas here, so the selected Settings section computed to the same rgb(0 0 0) fill as every unselected sibling. Give it the same inset perimeter `.select-item` already uses for its navigated option. - Tailwind preflight paints `::placeholder` with the raw gray-400 #999696, and a field that omits a `placeholder:` utility inherits it: the Custom Instructions textarea measured 4.06:1 on the black canvas and 3.08:1 on the white one, both under the 1.4.3 floor for what is ordinary text. Route it through `text-secondary`, which is pure ink in both palettes. * fix: mark selection with a perimeter and lighten the contrast selected fills The selected fill was carrying WCAG 1.4.11 on its own, which forced it dark enough (#8c8c8c light, #5c5c5c dark) that its own label capped at 6.25:1 and 6.69:1 — under the AAA these modes exist for, and visibly heavy on the light canvas. The `.select-item` rule already showed the better answer: mark the state with a `text-primary` perimeter at 21:1 and let the fill stay light. Generalise that rule to the two families it missed — every other Ariakit menu, whose navigated row carried only a `surface-hover` fill at 1.48:1 on white, and any row painted with the selected-surface role — then lighten the fills behind it: #e3e3e3 / #d4d4d4 light and #2b2b2b / #3d3d3d dark, all four AAA under their label. `-alt` meets `surface-hover`, as it does in the standard palettes. Inline `span` is excluded so a highlighted citation passage is not boxed per wrapped fragment. The palette contract moves with it: `activeFills` is now held to an AAA label rather than to 3:1 against the canvas, which the perimeter discharges. * fix: address sixth-round review findings chatgpt-codex-connector: - Ship the selected-state contrast with the package. The lightened `surface-active` fills only work because a perimeter marks the selection, and that perimeter lived in the SPA stylesheet, which `tsdown` never publishes — so `TimePicker`, `SelectDropDown`, `MultiSelect`, `InputWithDropDown`, `Badge` and `DataTable` gave an external consumer a 1.28:1 fill and nothing else. The perimeters and the placeholder ink now live in `packages/client/src/theme/highContrast.css`, imported by `ThemeProvider`; `style.css` keeps only what is genuinely SPA-only. The Ariakit selector also widened from four menu roles to `[data-active-item]`, and picked up `[data-state='selected']` for package data-table rows. - Give Monaco selections a contrast-safe highlight: a focused selection now inverts the canvas (`text-primary` on `surface-primary`), matching `::selection`, because Monaco draws no perimeter. Weaker emphases share `surface-hover-alt` behind the ink find-match border. - Populate Mermaid's separate `git0`-`git7` branch palette from the series ramp. Eight slots against a seven-slot ramp, so the last takes the ink rather than repeating branch one; labels take the canvas, since the ramp sits on its far side. - Debounce the two appearance controls separately. They are independent settings, so light -> high-contrast dark is one flip of each, and the shared 500ms window swallowed the second click. - Route sharing principal badges (USER/GROUP/ROLE) through series-1/7/6. - Apply the selected contrast mode to Office artifacts. The backend document picks its palette from `prefers-color-scheme` alone, so an explicit mode inverted whenever the OS disagreed. `withOfficeContrast` re-declares its `:root` tokens and pins `color-scheme` from inside the head. * fix: address seventh-round review findings chatgpt-codex-connector: - Restore the citation highlight. The perimeter rule skips `span` so a wrapped passage is not boxed per fragment, which left the inline highlight on the lightened fill alone. It inverts now instead — the same treatment the mode gives `::selection`, 21:1 and with no geometry to wrap. - Underline non-prose links. The 1.4.1 rule only reached `.markdown` and `.prose`, so the auth resend actions and in-dialog help links were colour-only against ink that is under 3:1 from them. It now also covers the shared `text-link` role, including the ones rendered as a `button`, and moved to the package stylesheet since that role is shared. MCP server descriptions style their anchors through an `[&_a]` variant rather than a class of their own, so they get the underline at the call site — running text, so it applies in every theme, not just the contrast ones. - Route the selected tool card through `status-success` instead of `emerald-500/60` over a 6% fill, which composited to about 1.7:1 and left a selected card with a weaker edge than an unselected one. * fix: keep helper hints opaque in the contrast modes chatgpt-codex-connector: the `opacity-40` default-value hints composite pure ink to about #999 on the white canvas (2.85:1) and #666 on the black one (3.66:1), so small active labels missed even AA under a palette that contracts for AAA. They take `high-contrast:opacity-100` now — the variant this branch already added and `MessageNav` already uses — rather than a new token: every text role is the same pure ink in these palettes, so there is no muted colour to fall back to and the hierarchy is carried by size and the parentheses. The mobile artifact drag handle gets the same treatment: it is a control, so 1.4.11 applies, and a 40% ink bar does not clear 3:1. The two remaining `opacity-40` sites are left alone deliberately — `AssistantTool` dims a disabled row, which WCAG exempts, and the `MarketplaceCatalog` empty-state glyph is `aria-hidden` decoration. * style: sort imports in the two parameter controls this branch touched * fix: soften the temporary-chat accent outside the contrast modes Moving the accent to `series-6` swapped a 60%-alpha `violet-800` edge for a full-strength one, and series-6 is a saturated #7e23cd on the light palette and #ab68fe on the dark one — the composer read as a warning rather than a quiet mode hint. Half alpha in the standard palettes, opaque only under `high-contrast:`, which is the one place the edge has to clear the 3:1 non-text floor. |
||
|---|---|---|
| .claude/skills | ||
| .devcontainer | ||
| .github | ||
| .husky | ||
| .vscode | ||
| api | ||
| client | ||
| config | ||
| docs | ||
| e2e | ||
| helm | ||
| otel/langfuse-fanout | ||
| packages | ||
| redis-config | ||
| scripts | ||
| search | ||
| skill | ||
| src/tests | ||
| utils | ||
| .codex | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .nvmrc | ||
| .prettierrc | ||
| AGENTS.md | ||
| bun.lock | ||
| CLAUDE.md | ||
| CONTEXT.md | ||
| deploy-compose.langfuse-fanout.yml | ||
| deploy-compose.yml | ||
| docker-compose.langfuse-fanout.yml | ||
| docker-compose.override.yml.example | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.multi | ||
| eslint.config.mjs | ||
| librechat.example.yaml | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| rag.yml | ||
| README.md | ||
| README.zh.md | ||
| tool-intent-spec.md | ||
| turbo.json | ||
LibreChat
English · 中文
🚀 What's New in v0.8.8-rc2
- Agent run control: Interrupt an Agent before visible answer text, steer runs with files and quoted excerpts, durably queue follow-ups, and recover saved partial work with Keep going or Answer now.
- Agent activity: Optional generated labels group reasoning and tool work, fold completed groups into live phase cards, keep generated files visible, summarize multi-step phases, and show the current reasoning direction.
- Human-in-the-loop Agents: Stream up to four related questions, pause for input or tool approval, and resume durably.
- Unified Agent Builder: Configure Skills, MCP, Code Interpreter, orchestration, Programmatic Tool Calling, model-spec controls, and per-tool background and intent settings in one Tools marketplace; Skills can be enabled for standalone runtime authoring without exposing the existing catalog.
- Durable Agent automation: Authenticated Agent Events support bound child actors, expected-action receipts, per-actor mailboxes, event batching, durable human pauses, and automatic detached Actions across built-in stream stores.
- Deeper Subagent history: Browse branch-aware child turns with bounded reasoning and stable live event views, load earlier activity, inspect event details, continue completed child chats, and automatically wake saved parent Agents when detached work settles.
- Background tools: Eligible Code Interpreter, MCP, Plugin, and Action tools can run while an Agent keeps working, with automatic delivery for supported completions and polling controls when needed.
- Code Interpreter workflows: Sandbox images return as viewable artifacts; highly experimental stateful sessions add scoped managed, attached, or personal environments, per-message file downloads, and guarded file-write and command permissions.
- Agent extensibility: Experimental Agent Plugins bundle deployment Skills, MCP servers, and opt-in command hooks; saved Agent teams run as isolated Subagent graphs.
- Scheduled Chats (experimental): Run saved Agents with presets or custom cron, selectable time zones, multi-day weekly cadence, and optional Chat Project destinations.
- Memory and context: Agents can use optionally isolated memory, preserve adaptive context fading across turns, and show categorized current-window usage, tokens, and optional cost.
- Editable long pastes: Long pasted text becomes an editable attachment that can be moved back into the composer; attachment-only turns and reliable Upload as Text downloads are also supported.
- Projects, settings, and navigation: Search conversation titles and message contents, manage project chats, use searchable settings and shortcuts, pin chats, choose clock/week conventions, and navigate faster on mobile.
- Sharing and artifacts: Stable shared links support personal copies; fullscreen previews, Mermaid export, PowerPoint templates, shell scripts, and original Office downloads expand file workflows.
- Web search: Keenable adds keyless search and page fetch, while SearXNG and Tavily gain richer controls and all web-tool egress uses stronger SSRF protection.
- Security and authentication: Default HTTP security headers, opt-in nonce CSP, authenticated local images, per-user Code Interpreter JWTs, stable SAML identity binding, live-session OpenID token refresh, and retired JWT-secret rejection harden deployments.
- Models and reasoning: Added GPT-5.6 with Responses reasoning controls, Claude Fable 5.1, Opus 5, and Sonnet 5, plus Gemini 3.8/3.7/3.6 Flash and Gemini 3.5 Flash-Lite.
- Langfuse observability: Configure encrypted in-app connections, tenant fanout, authenticated gateways, export-decision telemetry, and authorized session links in chats and shared views.
- Administration: Source-aware content filters can audit or block model-bound data, while tenant Insights, delegated configuration, encrypted secrets, and expiring violation scores improve operations.
- Streaming and reliability: Adaptive smoothing, Redis delta batching and failover recovery, automatic generation protocol v2, live MCP catalog refresh, Agent circuit breakers, and DocumentDB support improve long runs and scaled deployments.
Read the full v0.8.8-rc2 changelog.
✨ Features
-
🖥️ UI & Experience inspired by ChatGPT with enhanced design and features
-
🤖 AI Model Selection:
- Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, Google, Vertex AI, OpenAI Responses API (incl. Azure)
- Custom Endpoints: Use any OpenAI-compatible API with LibreChat, no proxy required
- Compatible with Local & Remote AI Providers:
- Ollama, groq, Cohere, Mistral AI, Apple MLX, koboldcpp, together.ai,
- OpenRouter, Helicone, Perplexity, ShuttleAI, Deepseek, Qwen, and more
-
- Secure, Sandboxed Execution in Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust, and Fortran
- Seamless File Handling: Upload, process, and download files directly
- No Privacy Concerns: Fully isolated and secure execution
- Open-Source & Self-Hostable: powered by ClickHouse/code-interpreter
-
🔦 Agents & Tools Integration:
- LibreChat Agents:
- No-Code Custom Assistants: Build specialized, AI-driven helpers
- Agent Marketplace: Discover and deploy community-built agents
- Collaborative Sharing: Share agents with specific users and groups
- Flexible & Extensible: Use MCP Servers, tools, file search, code execution, and more
- Skills: Create reusable
SKILL.mdinstruction bundles for manual, automatic, or always-on agent workflows - Agent Plugins: Experimentally bundle deployment Skills and MCP servers into startup-loaded packages
- Subagents: Delegate focused work to isolated child agent runs with their own context windows
- Compatible with Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, Google, Vertex AI, Responses API, and more
- Model Context Protocol (MCP) Support for Tools
- LibreChat Agents:
-
🔍 Web Search:
- Search the internet and retrieve relevant information to enhance your AI context
- Combines search providers, content scrapers, and result rerankers for optimal results
- Customizable Jina Reranking: Configure custom Jina API URLs for reranking services
- Learn More →
-
🪄 Generative UI with Code Artifacts:
- Code Artifacts create React, HTML, and Mermaid content directly in chat
- Open previews fullscreen and export Mermaid diagrams as SVG or PNG
-
🎨 Image Generation & Editing
- Text-to-image and image-to-image with GPT-Image-1
- Text-to-image with DALL-E (3/2), Stable Diffusion, Flux, or any MCP server
- Produce stunning visuals from prompts or refine existing images with a single instruction
-
💾 Presets & Context Management:
- Create, Save, & Share Custom Presets
- Switch between AI Endpoints and Presets mid-chat
- Edit, Resubmit, and Continue Messages with Conversation branching
- Create and share prompts with specific users and groups
- Fork Messages & Conversations for Advanced Context control
-
💬 Multimodal & File Interactions:
- Upload and analyze images with Claude 3, GPT-4.5, GPT-4o, o1, Llama-Vision, and Gemini 📸
- Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, & Google 🗃️
-
🌎 Multilingual UI:
- English, 中文 (简体), 中文 (繁體), العربية, Deutsch, Español, Français, Italiano
- Polski, Português (PT), Português (BR), Русский, 日本語, Svenska, 한국어, Tiếng Việt
- Türkçe, Nederlands, עברית, Català, Čeština, Dansk, Eesti, فارسی
- Suomi, Magyar, Հայերեն, Bahasa Indonesia, ქართული, Latviešu, ไทย, ئۇيغۇرچە
-
🧠 Reasoning UI:
- Dynamic Reasoning UI for Chain-of-Thought/Reasoning AI models like DeepSeek-R1
-
🎨 Customizable Interface:
- Customizable Dropdown & Interface that adapts to both power users and newcomers
-
- Never lose a response: AI responses automatically reconnect and resume if your connection drops
- Multi-Tab & Multi-Device Sync: Open the same chat in multiple tabs or pick up on another device
- Production-Ready: Works from single-server setups to horizontally scaled deployments with Redis
-
🗣️ Speech & Audio:
- Chat hands-free with Speech-to-Text and Text-to-Speech
- Automatically send and play Audio
- Supports OpenAI, Azure OpenAI, and Elevenlabs
-
📥 Import & Export Conversations:
- Import Conversations from LibreChat, ChatGPT, Chatbot UI
- Export conversations as screenshots, markdown, text, json
-
🔍 Search & Discovery:
- Search all messages/conversations
-
👥 Multi-User & Secure Access:
- Multi-User, Secure Authentication with OAuth2, LDAP, & Email Login Support
- Built-in Moderation, and Token spend tools
-
🎛️ Admin Panel:
- Browser-based UI to manage users, groups, roles, and configuration overrides
- Edit settings and per-role/group permissions live, without redeploying
- Bundled with the Docker Compose stacks for one-command setup
-
⚙️ Configuration & Deployment:
- Configure Proxy, Reverse Proxy, Docker, & many Deployment options
- Use S3 with CloudFront for stable media links, edge delivery, signed cookies, and secured downloads
- Use completely local or deploy on the cloud
-
📖 Open-Source & Community:
- Completely Open-Source & Built in Public
- Community-driven development, support, and feedback
For a thorough review of our features, see our docs here 📚
🪶 All-In-One AI Conversations with LibreChat
LibreChat is a self-hosted AI chat platform that unifies all major AI providers in a single, privacy-focused interface.
Beyond chat, LibreChat provides AI Agents, Model Context Protocol (MCP) support, Artifacts, Code Interpreter, custom actions, conversation search, and enterprise-ready multi-user authentication.
Open source, actively developed, and built for anyone who values control over their AI infrastructure.
🌐 Resources
GitHub Repo:
- RAG API: github.com/danny-avila/rag_api
- Website: github.com/LibreChat-AI/librechat.ai
Other:
- Website: librechat.ai
- Documentation: librechat.ai/docs
- Blog: librechat.ai/blog
📝 Changelog
Keep up with the latest updates by visiting the releases page and notes:
⚠️ Please consult the changelog for breaking changes before updating.
⭐ Star History
✨ Contributions
Contributions, suggestions, bug reports and fixes are welcome!
For new features, components, or extensions, please open an issue and discuss before sending a PR.
If you'd like to help translate LibreChat into your language, we'd love your contribution! Improving our translations not only makes LibreChat more accessible to users around the world but also enhances the overall user experience. Please check out our Translation Guide.
💖 This project exists in its current state thanks to all the people who contribute
🎉 Special Thanks
We thank Locize for their translation management tools that support multiple languages in LibreChat.