ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

LibreChat @librechat/client 动态主题系统完全指南:CSS 变量、ThemeDefinition 与 Tailwind 深度定制

LibreChat @librechat/client 动态主题系统完全指南:CSS 变量、ThemeDefinition 与 Tailwind 深度定制 LibreChat librechat/client 动态主题系统完全指南CSS 变量、ThemeDefinition 与 Tailwind 深度定制【免费下载链接】LibreChatEnhanced ChatGPT Clone: Features Agents, MCP, Skills, DeepSeek, Anthropic, AWS, OpenAI, Responses API, Azure, Groq, o1, GPT-5, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, Code Interpreter, langchain, DALL-E-3, OpenAPI Actions, Functions, Secure Multi-User Auth, Presets, open-source for self-hosting. Active项目地址: https://gitcode.com/GitHub_Trending/li/LibreChat本文面向需要在 LibreChat 生态尤其是librechat/clientReact 组件库中实现深色/浅色模式切换、运行时动态换肤、自定义主题甚至多主题选择器的前端开发者。文章以 packages/client/src/theme/README.md 为骨架结合 ThemeProvider.tsx、registry.ts、applyTheme.ts 等源码与测试讲清从RGB 通道三元组 CSS 变量的基础约定到版本化 ThemeDefinition 外观Appearance注册表这一代新主题模型的完整接入与迁移方案读完即可在你的 React 应用中复刻 LibreChat 的动态主题能力。概述它解决什么问题LibreChat 的主题系统基于 CSS 自定义属性CSS Variables与 Tailwind CSS 构建为 React 应用提供四类能力明暗模式切换——跟随用户偏好自动在 light/dark 之间切换运行时动态配色——无需重新编译 CSS即可在运行时修改全部颜色CSS 变量驱动——颜色只通过 CSS custom properties 变更性能开销小Tailwind 无缝集成——语义色以text-text-primary、bg-surface-primary这类工具类暴露天然支持bg-surface-primary/50等透明度修饰符TypeScript 强类型——主题定义有完整接口约束错误在编译期暴露。const compactTheme: ThemeDefinition { version: 1, name: compact, modes: { light: { appearance: { controlRadius: 0.25rem, roundControlRadius: 9999px, surfaceRadius: 0.5rem, largeSurfaceRadius: 0.75rem, controlHeight: 2rem, }, }, }, }; ThemeProvider themeDefinition{compactTheme}{children}/ThemeProvider;值得注意的是初始的外观注册表appearance registry刻意只覆盖控件形状、表面形状、控件高度、紧凑/常规间距、UI 排版、表面抬升elevation以及快/慢动效。而themeRGB、REACT_APP_THEME_*环境变量以及旧的 localStorage 键则继续通过遗留适配器得到支持重置主题时系统只会移除主题模块自己拥有的变量绝不干扰宿主应用的其它 CSS。工作原理三层架构从 README 与源码可以归纳出主题系统分三层工作CSS 变量层应用自身 CSS如style.css定义颜色通道与兜底值ThemeProvider 层React Context 负责主题状态管理并把解析后的主题写到html元素的 inline style 上Tailwind 层把 CSS 变量映射为theme.extend.colors中的语义色工具类。默认行为不传任何自定义主题CSS 变量完全来自应用自身的style.css级联浅色模式使用html选择器下的变量深色模式使用.dark选择器下的变量整个过程中没有任何 JavaScript 介入颜色值的计算。这也是applyThemeMode在 ThemeProvider.tsx 中的行为没有themeDefinition时只切换dark/lightclassroot.classList.toggle(dark, mode dark)并恢复restore由宿主 CSS 级联决定的样式。自定义主题行为优先使用版本化的themeDefinitionprop遗留的themeRGBprop 仍被支持fromLegacyTheme会把旧的 RGB 接口自动转换成语义等价的版本化定义见 registry.ts用裸R G B通道三元组覆盖 CSS 变量未在themeDefinition中声明的值会回退到组件库内置的 light/dark 默认色resolveTheme以{ ...baseColors, ...customColors, ... }的形式合并见 registry.ts被遗留themeRGB省略的颜色保持不设置从而让消费方 CSS 继续级联生效。快速上手5 步接入第 1 步安装组件库npm install librechat/client在 monorepo 的 packages 中它定义于 packages/client/package.json同时导出了librechat/client/tailwind-preset与librechat/client/style.css两个子路径。第 2 步用 ThemeProvider 包裹应用import { ThemeProvider } from librechat/client; function App() { return ( ThemeProvider initialThemesystem YourApp / /ThemeProvider ); }第 3 步准备基础 CSS每个主题变量必须保存裸的R G B通道三元组如255 255 255而不是一个完整的 CSS 颜色值。原因在于 Tailwind 的颜色映射会把它们包装成rgb(var(--x) / alpha-value)这样才能让bg-surface-primary/50这类透明度修饰符正常工作。/* style.css */ :root { --white: 255 255 255; --gray-800: 33 33 33; --gray-100: 236 236 236; /* ... 其它颜色定义 */ } html { --text-primary: var(--gray-800); --surface-primary: var(--white); /* ... 其它浅色主题变量 */ } .dark { --text-primary: var(--gray-100); --surface-primary: var(--gray-900); /* ... 其它深色主题变量 */ }⚠️ 直接在手写 CSS 里使用这些变量时必须自己包装三元组color: rgb(var(--text-primary));破坏性变更说明早期版本接受完整颜色值如--text-primary: #212121。现在十六进制#...、rgb(...)函数与具名颜色都会生成无效声明必须全部转换为通道三元组。源码在 registry.ts 中通过rgbPattern/^(\d{1,3})\s(\d{1,3})\s(\d{1,3})$/与Number(channel) 255做严格校验非法值会被validateThemeDefinition报错并在applyTheme阶段直接console.error跳过见 applyTheme.ts。第 4 步配置 Tailwindlibrechat/client发布了一份开箱即用的语义外观工具预设必须保留它哪怕你还要定义项目自己的工具类const libreChatTailwindPreset require(librechat/client/tailwind-preset); module.exports { presets: [libreChatTailwindPreset], content: [ ./src/**/*.{js,jsx,ts,tsx}, // 别忘了包含组件库文件 ./node_modules/librechat/client/dist/**/*.js, ], darkMode: [class], theme: { extend: { colors: { // 把每个通道三元组包装起来透明度修饰符才能继续工作 text-primary: rgb(var(--text-primary) / alpha-value), surface-primary: rgb(var(--surface-primary) / alpha-value), brand-purple: rgb(var(--brand-purple) / alpha-value), // ... 其它颜色 }, }, }, };预设提供的语义外观工具包括h-theme-control、rounded-theme-control、gap-theme-compact、duration-theme-fast等它们被 theme-aware 组件变体广泛使用。仓库自身在 packages/client/tailwind.config.js 中的实际做法值得参考通过createTailwindColors()一次性生成全部语义色——该函数定义于 createTailwindColors.js其头注释明确指出clientSPA 与librechat/client包共享同一份单点定义保证两处生成的工具类永不漂移。带固有透明度的 token如 border 各档使用配套的--x-alpha变量与透明度修饰符相乘rgb(var(--x) / calc(var(--x-alpha, 1) * alpha-value))。第 5 步在组件中使用语义色function MyComponent() { return ( div classNameborder border-border-light bg-surface-primary text-text-primary h1 classNametext-text-secondaryHello World/h1 button classNamebg-surface-submit text-text-on-status hover:bg-surface-submit-hover Submit /button /div ); }语义色全景可用的主题颜色以下分类来自 README 的Available Theme Colors清单并可在 types/index.ts 的IThemeVariables/IThemeRGB接口中找到对应的--xCSS 变量与rgb-x键是一一对应的。文本色Text Colorstext-text-primary主文本色默认浅色33 33 33深色236 236 236text-text-secondary次级文本text-text-secondary-alt次级文本的替代档text-text-tertiary三级文本text-text-warning警告文本text-text-destructive破坏性/错误文本text-text-on-status用于高对比状态表面的文字色表面色Surface Colorsbg-surface-primary主背景bg-surface-secondary次背景bg-surface-tertiary三级背景bg-surface-submit提交按钮背景bg-surface-destructive破坏性操作背景bg-surface-dialog对话框/弹窗背景bg-surface-overlay弹窗遮罩scrim随主题自适应bg-surface-chat聊天界面背景接口中还包含surface-active、surface-hover、surface-composer-hover、surface-primary-alt、surface-primary-contrast、surface-inverted、surface-fixed等更多表面档位其中surface-fixed/text-fixed在明暗模式中保持同一取值如 default.ts 所注释 same in light dark。边框色Border Colorsborder-border-light浅边框border-border-medium中边框border-border-heavy重边框border-border-xheavy超重边框border-border-destructive破坏性动作边框状态色Status Colors每个状态族都有 foreground、-subtle背景、-border边框以及用于高对比通知的-strong表面text-status-success/bg-status-success-subtle/border-status-success-bordertext-status-info/bg-status-info-subtle/border-status-info-bordertext-status-warning/bg-status-warning-subtle/border-status-warning-bordertext-status-error/bg-status-error-subtle/border-status-error-bordertext-status-neutral/bg-status-neutral-subtle/border-status-neutral-borderbg-status-success-strong/bg-status-info-strong/bg-status-warning-strong/bg-status-error-strong其它颜色bg-brand-purpleLibreChat 品牌紫bg-presentation演示/展示背景ring-ring-primary焦点环颜色版本化主题定义与外观注册表新主题应使用版本化的ThemeDefinition接口。它的定义是纯数据的data-only可分别提供明暗两种模式的覆盖未提供的值会先回退到 LibreChat 内置默认之后才应用 CSS 变量。接口定义见 types/index.tsexport interface ThemeDefinition { version: 1; name: string; modes: PartialRecordThemeMode, ThemeModeDefinition; brands?: PartialIThemeBrands; }其中ThemeModeDefinition允许每档模式声明colors?: IThemeRGB与appearance?: PartialIThemeAppearance。外观appearancetoken 全集对应 CSS 变量带--theme-前缀见 registry.ts及其默认值appearance 键CSS 变量默认值defaultAppearancecontrolRadius--theme-control-radius0.75remroundControlRadius--theme-round-control-radius9999pxsurfaceRadius--theme-surface-radius1remlargeSurfaceRadius--theme-large-surface-radius1.5remcontrolHeight--theme-control-height2.25remspaceCompact--theme-space-compact0.375remspaceNormal--theme-space-normal0.75remfontFamily--theme-font-familyInter, sans-serifelevationSurface--theme-elevation-surface0 10px 15px -3px rgb(0 0 0 / 0.1), ...motionFast--theme-motion-fast150msmotionNormal--theme-motion-normal200ms品牌brandstoken 全集provider-openai、provider-openai-gpt4、provider-openai-reasoning、provider-anthropic、provider-azure、provider-bedrock、provider-foreground见 registry.ts。品牌色允许十六进制或linear-gradient(...)值Azure 默认即渐变provider-foreground仅允许纯色。校验与解析validateThemeDefinitionregistry.ts会拒绝未知字段、未知 mode、非法 RGB 三元组、非法长度/时长值与未知品牌 tokenresolveTheme(theme, mode)再基于浅/深默认default.ts、dark.ts完成补全输出ResolvedThemeDefinition全量RequiredIThemeRGB 完整 appearance brands。仓库预置的libreChatThemename:librechat就是这个机制的最好样例。自定义主题方式 A遗留接口IThemeRGB仅颜色覆盖import { IThemeRGB } from librechat/client; export const customTheme: IThemeRGB { rgb-text-primary: 0 0 0, // 黑 rgb-text-secondary: 100 100 100, // 灰 rgb-surface-primary: 255 255 255, // 白 rgb-surface-submit: 0 128 0, // 绿 rgb-brand-purple: 138 43 226, // 蓝紫 // ... 定义其它颜色 };import { ThemeProvider } from librechat/client; import { customTheme } from ./themes/custom; function App() { return ( ThemeProvider themeRGB{customTheme} themeNamecustom YourApp / /ThemeProvider ); }themeRGB只覆盖键名中明确给出的颜色fromLegacyTheme内部会对themeColorTokens做白名单过滤并把同一份颜色同时应用在 light 与 dark 两个 mode 下。凡在存储/环境主题时代写的主题早于 shimmer 双档出现系统会自动把--shimmer-base跟随主题的text-primary详见 applyTheme.ts 的注释解释rgb-surface-composer-hover也有向rgb-surface-hover的回退逻辑。方式 B版本化ThemeDefinition推荐支持外观与品牌const oceanTheme: ThemeDefinition { version: 1, name: ocean, modes: { light: { colors: { rgb-brand-purple: 0 119 190, rgb-surface-primary: 240 248 255, }, appearance: { controlRadius: 0.5rem }, }, dark: { colors: { rgb-brand-purple: 147 197 253, rgb-surface-primary: 2 6 23, }, }, }, brands: { provider-openai: #19C37D }, };自定义主题的正确姿势只声明你想改变的 token其余全部交给默认补齐。这一点在 types 注释中写得很明确——Missing values resolve against LibreChat defaults。环境变量主题构建期注入不写 TS 也能通过构建环境变量定制颜色。第 1 步创建环境变量# .env.local REACT_APP_THEME_BRAND_PURPLE171 104 255 REACT_APP_THEME_TEXT_PRIMARY33 33 33 REACT_APP_THEME_TEXT_SECONDARY66 66 66 REACT_APP_THEME_SURFACE_PRIMARY255 255 255 REACT_APP_THEME_SURFACE_SUBMIT4 120 87 REACT_APP_THEME_LINK37 99 235 REACT_APP_THEME_ACCENT_PRIMARY18 110 107 REACT_APP_THEME_STATUS_ERROR185 28 28 REACT_APP_THEME_STATUS_ERROR_SUBTLE254 226 226 REACT_APP_THEME_STATUS_ERROR_BORDER252 165 165命名规则IThemeRGB中的每个键都可配置——去掉rgb-前缀、其余部分转成大写蛇形。rgb-status-error-border→REACT_APP_THEME_STATUS_ERROR_BORDER。注意前缀必须登记在打包器的envPrefixVite 默认仅暴露VITE_需在 vite.config.ts 等配置中显式放行或等效配置中值在构建期内联改动后必须重新构建客户端。第 2 步写一个主题加载器function getThemeFromEnv(env import.meta.env): IThemeRGB | undefined { const theme { rgb-text-primary: env.REACT_APP_THEME_TEXT_PRIMARY, rgb-brand-purple: env.REACT_APP_THEME_BRAND_PURPLE, // ... 其它颜色 }; const set Object.fromEntries(Object.entries(theme).filter(([, value]) value)); return Object.keys(set).length 0 ? set : undefined; // 无则回退默认主题 }第 3 步应用环境主题ThemeProvider initialThemesystem themeRGB{getThemeFromEnv()} App / /ThemeProvider明暗模式与持久化使用 useTheme Hookimport { useTheme } from librechat/client; function ThemeToggle() { const { theme, setTheme } useTheme(); return ( button onClick{() setTheme(theme dark ? light : dark)} Current theme: {theme} /button ); }主题取值light强制浅色dark强制深色system跟随系统偏好通过window.matchMedia((prefers-color-scheme: dark))并在system模式下监听其change事件实时切换见 ThemeProvider.tsx。状态持久化谁优先ThemeProvider 把主题状态持久化到 localStorage使用以下键源码常量见 ThemeProvider.tsxlocalStorage 键内容color-theme明暗外观模式light/dark/systemtheme-definition序列化后的完整ThemeDefinitiontheme-colors遗留IThemeRGB颜色legacy 来源时theme-name主题名称theme-source来源标记legacy或definition关键语义themeDefinition、themeRGB、themeName这三个 props 是受控的——只要父级传了就会覆盖存储值并在 props 变化时保持同步ThemeProvider.tsx 的 effect 会对比 props 变化并调用对应的 setter因此只有当父组件确实要接管这些值时才应传主题 props否则请使用 Context 的 setter让用户存储的偏好保持权威当父组件控制的是部署级/嵌入级主题、不允许替换用户已存的主题时设置persistThemeDefinition{false}ThemeProvider.tsx 的writeThemeStorage会直接短路明暗模式是独立持久化的键color-theme。想让用户存储的 light/dark/system 偏好保持权威就别传initialTheme或传undefined。resetTheme 与作用域清理resetTheme()把外观切回system、清空定义与theme-colors并恢复宿主 CSS。清理时只移除主题模块拥有的变量——即themeOwnedProperties全部--颜色变量 --theme-*外观变量 --provider-*品牌变量见 applyTheme.ts绝不误删其它来源的变量。卸载组件时也会通过快照captureThemeDOM/restoreThemeDOM同时记住dark/lightclass 与data-theme属性把 DOM 恢复原状ThemeProvider.tsx。Context 完整 APItype ThemeContextType { theme: light | dark | system; setTheme: (theme: string) void; themeRGB?: IThemeRGB; setThemeRGB: (colors?: IThemeRGB) void; themeDefinition?: ThemeDefinition; setThemeDefinition: (definition?: ThemeDefinition) void; themeName?: string; setThemeName: (name?: string) void; resetTheme: () void; };从旧主题系统迁移1. 更新导入路径之前import { ThemeContext, ThemeProvider } from ~/hooks/ThemeContext;之后import { ThemeContext, ThemeProvider } from librechat/client;2. 更新 ThemeProvider 用法新 Provider 向后兼容但能力更强ThemeProvider initialThemesystem // 与之前一致 themeRGB{customTheme} // 新增可选的定制颜色 App / /ThemeProvider3. 既有组件无需改动使用ThemeContext消费状态的组件原样可用const { theme, setTheme } useContext(ThemeContext);另外早前由 jotai 提供、面向持久化的themeModeAtom/themeColorsAtom/themeNameAtom见 themeAtoms.ts在文件中已明确标注deprecated——内部实现已改为 ReactuseState localStorage原子仅保留向后兼容且与 ThemeProvider 使用同一批 localStorage 键color-theme、theme-colors、theme-name。实现细节源码结构一览仓库中packages/client/src/theme/的真实结构与 README 描述一致并多出 spec 与 semanticTokenspackages/client/src/theme/ ├── atoms/ │ └── themeAtoms.ts # 已弃用的 jotai 持久化原子向后兼容 ├── context/ │ ├── ThemeProvider.tsx # 主题 Provider 主实现useState localStorage │ └── ThemeProvider.spec.tsx # Provider 测试 ├── themes/ │ ├── default.ts # 内置浅色主题完整 RGB token │ ├── dark.ts # 内置深色主题 │ └── index.ts # 导出 defaultTheme / darkTheme ├── types/ │ └── index.ts # IThemeRGB / ThemeDefinition / ResolvedThemeDefinition 等接口 ├── utils/ │ ├── applyTheme.ts # 应用/清理 CSS 变量applyResolvedTheme / themeOwnedProperties │ ├── createTailwindColors.js # 语义色 Tailwind 映射单点来源 │ └── createTailwindColors.spec.js ├── registry.ts # 校验、解析、遗留转换validateThemeDefinition / resolveTheme / fromLegacyTheme ├── semanticTokens.spec.ts ├── index.ts # 库入口导出 └── README.md # 本文档三种格式的对应关系CSS 变量--text-primary: 33 33 33主题定义rgb-text-primary: 33 33 33Tailwind 用法text-text-primaryRGB 格式要求所有颜色值必须是空格分隔的 RGB✅ 正确255 255 255❌ 错误#ffffff或rgb(255, 255, 255)这个格式让 Tailwind 可以叠加透明度修饰符如bg-surface-primary/50。校验逻辑同时存在于registry.ts的validateThemeDefinition拒绝整个定义与applyTheme.ts逐变量 console.error 后跳过。应用流程底层视角ThemeProvider 在 effect 中调用applyThemeMode决定 mode → 维护dark/lightclass → 无定义则恢复级联 → 有定义则用快照暂存 DOM →applyResolvedTheme(resolveTheme(definition, mode), root)把每条--变量setProperty到html的 inline style并设置root.dataset.theme theme.name。任何异常都会触发restoreAppliedTheme回滚并打印Unable to apply theme definitionThemeProvider.tsx。组合实战示例动态切换明暗主题import { ThemeProvider, defaultTheme, darkTheme } from librechat/client; import { useState } from react; function App() { const [isDark, setIsDark] useState(false); return ( ThemeProvider initialTheme{isDark ? dark : light} themeRGB{isDark ? darkTheme : defaultTheme} themeName{isDark ? dark : default} button onClick{() setIsDark(!isDark)}Toggle Theme/button YourApp / /ThemeProvider ); }多主题选择器const themes { default: undefined, // 使用 CSS 默认值 ocean: { rgb-brand-purple: 0 119 190, rgb-surface-primary: 240 248 255, // ... 海洋主题色 }, forest: { rgb-brand-purple: 34 139 34, rgb-surface-primary: 245 255 250, // ... 森林主题色 }, }; function App() { const [selectedTheme, setSelectedTheme] useState(default); return ( ThemeProvider themeRGB{themes[selectedTheme]} themeName{selectedTheme} select onChange{(e) setSelectedTheme(e.target.value)} {Object.keys(themes).map((name) ( option key{name} value{name} {name} /option ))} /select YourApp / /ThemeProvider ); }在主应用中与 localStorage 持久化协同import { ThemeProvider } from librechat/client; import { getThemeFromEnv } from ./utils; function App() { const envTheme getThemeFromEnv(); return ( ThemeProvider // 只有当需要覆盖存储值时再传 props // 若总是传 props它们会一直覆盖 localStorage initialTheme{envTheme ? system : undefined} themeRGB{envTheme || undefined} {/* 应用内容 */} /ThemeProvider ); }注意themeDefinition、themeRGB、themeNameprops 会覆盖存储值并且在它们变化时保持同步。仅当父组件需要掌控这些值时才传主题 props否则应通过 context setter 操作、让存储偏好保持权威。父组件托管部署/嵌入主题且不希望覆盖用户存储定义时设persistThemeDefinition{false}外观模式仍独立持久化于color-theme想尊重存储的明暗偏好就不要给initialTheme传值。故障排查常见问题1. 颜色不生效现象自定义主题色没有显示。解决传入合法的themeDefinition或为纯颜色覆盖继续使用遗留themeRGBprop。检查DevTools 中 CSS 变量应显示为裸R G B三元组而不是十六进制或rgb(...)。2. 循环引用错误现象--brand-purple: var(--brand-purple)形成死循环。解决直接给通道值--brand-purple: 171 104 255。3. 深色模式不切换现象切到 dark 没反应。解决确认 Tailwind 配置里darkMode: [class]已设置.darkclass 模式而非media。检查深色模式下html元素应带有classdark源码通过root.classList.toggle(dark, ...)维护。4. TypeScript 报错现象定义主题时出现类型错误。解决导入并使用IThemeRGB类型import { IThemeRGB } from librechat/client;5. 校验抛错/控制台告警现象setThemeDefinition抛TypeError、或控制台出现Invalid RGB value。解决前者来自validateThemeDefinition的错误列表未知 token、非法值、版本不匹配、version ! 1等都会被拒绝对照上文的 token 白名单逐一检查后者是applyTheme的逐值容错。注意ThemeDefinition.version当前必须是1。调试建议检查 CSS 变量用浏览器 DevTools 查看html的 inline style / Computed 面板中对应--x变量的值验证主题应用确认根元素存在 inline style 且data-theme属性已被设置控制台错误留意Unable to apply theme definition、Invalid RGB value与校验抛错最小化隔离先给一个只有 12 个 token 的最小主题判断问题出在主题本身还是宿主 CSS 级联。为新增颜色 token 贡献代码当需要扩展一套新的主题色时按 README 给出的链路同步修改保证五个环节一致在types/index.ts中新增类型定义IThemeRGB/IThemeVariables/IThemeColors三张映射表必须同步声明——registry.ts顶部对series-N的编译期守卫注释说明三张手工维护的 token 映射表任一漏加构建期就会失败而不是在运行时暴露坏主题把颜色加入themes/default.ts与themes/dark.ts更新applyTheme的变量映射逻辑加入 Tailwind 配置createTailwindColors在本 README 中补充文档与可用的 Tailwind 类名说明。组件库出口packages/client/src/theme/index.ts统一导出全部类型、ThemeProvider/ThemeContext/useTheme/isDark、applyTheme/applyResolvedTheme/clearAppliedTheme/themeOwnedProperties、registry 一族的THEME_VERSION/defaultAppearance/defaultBrands/fromLegacyTheme/libreChatTheme/resolveTheme/themeAppearanceProperties/themeBrandTokens/themeColorTokens/validateThemeDefinition、弃用的 jotai atoms 以及预置defaultTheme/darkTheme。主题模块的每一处细节都可以在 theme 目录 及配套的*.spec测试如 registry.spec.ts、applyTheme.spec.ts、ThemeProvider.spec.tsx中找到对应实现与验证。【免费下载链接】LibreChatEnhanced ChatGPT Clone: Features Agents, MCP, Skills, DeepSeek, Anthropic, AWS, OpenAI, Responses API, Azure, Groq, o1, GPT-5, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, Code Interpreter, langchain, DALL-E-3, OpenAPI Actions, Functions, Secure Multi-User Auth, Presets, open-source for self-hosting. Active项目地址: https://gitcode.com/GitHub_Trending/li/LibreChat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表