聊天前端接口
聊天前端界面
相关源文件
以下文件为本 Wiki 页面的生成提供了上下文:
web/src/app/app/interfaces.tsweb/src/app/app/message/HumanMessage.tsxweb/src/app/app/message/MultiModelPanel.tsxweb/src/app/app/message/MultiModelResponseView.tsxweb/src/app/app/message/codeUtils.test.tsweb/src/app/app/message/codeUtils.tsweb/src/app/app/message/custom-code-styles.cssweb/src/app/app/message/interfaces.tsweb/src/app/app/message/messageComponents/AgentMessage.tsxweb/src/app/app/message/messageComponents/markdownUtils.tsxweb/src/app/app/message/messageComponents/renderers/MessageTextRenderer.tsxweb/src/app/app/services/lib.tsxweb/src/app/app/settings/layout.tsxweb/src/app/app/stores/useChatSessionStore.tsweb/src/app/craft/components/InputBar.tsxweb/src/app/craft/components/SideBar.tsxweb/src/app/css/colors.cssweb/src/app/css/content-editable.cssweb/src/app/ee/admin/layout.tsxweb/src/app/globals.cssweb/src/app/nrf/NRFPage.tsxweb/src/components/chat/DynamicBottomSpacer.tsxweb/src/components/chat/ScrollContainerContext.tsxweb/src/hooks/useChatController.tsweb/src/hooks/useContentEditable.tsweb/src/hooks/useSmoothStreaming.tsweb/src/hooks/useTypewriter.tsweb/src/layouts/admin/ClientLayout.tsxweb/src/layouts/admin/Layout.tsxweb/src/layouts/app-layouts.tsxweb/src/layouts/sidebar-layouts.tsxweb/src/lib/contentEditable.tsweb/src/lib/richInputTile.tsweb/src/refresh-pages/AppPage.tsxweb/src/sections/chat/ChatScrollContainer.tsxweb/src/sections/chat/ChatUI.tsxweb/src/sections/input/AppInputBar.tsxweb/src/sections/input/QueuedMessageBar.tsxweb/src/sections/sidebar/AdminSidebar.tsxweb/src/sections/sidebar/AgentButton.tsxweb/src/sections/sidebar/AppSidebar.tsxweb/src/sections/sidebar/ChatButton.tsxweb/src/sections/sidebar/ProjectFolderButton.tsxweb/src/sections/sidebar/StepSidebarWrapper.tsxweb/tailwind-themes/tailwind.config.jsweb/tests/e2e/chat/input_focus_retention.spec.tsweb/tests/e2e/chat/queued_messages.spec.ts
Onyx 聊天界面是一个高性能、实时的 React 应用程序,基于 Next.js App Router 构建。它管理着复杂的状态转换,包括流式大语言模型(LLM)响应、多模型对比、消息分支(基于树的历史记录)以及富媒体渲染(Markdown、LaTeX 和文件附件)。
核心聊天架构
前端聊天体验以 useChatController 钩子为核心,该钩子编排了从初始提交到最终持久化的整个对话生命周期。
数据流与流式传输
该界面使用服务器发送事件(SSE)从后端接收细粒度的数据包对象。这些数据包会被处理成工具执行和消息增量的可视化时间线。
标题:聊天状态与交互流程
关键组件:
- useChatController:管理用于停止生成的
AbortController,通过createChatSession处理会话创建,并更新全局消息树web/src/hooks/useChatController.ts:134-194。 - AppInputBar:一个复杂的输入组件,通过
useContentEditable处理文本编辑、文件上传以及通过MicrophoneButton进行语音录制web/src/sections/input/AppInputBar.tsx:103-208。 - ChatUI:消息列表的主要容器。它通过检查用户消息的
childrenNodeIds来区分标准消息和多模型响应web/src/sections/chat/ChatUI.tsx:153-172。 - ChatScrollContainer:一个专用容器,实现了自动滚动行为,并处理聊天头部元素的粘性定位
web/src/sections/chat/ChatScrollContainer.tsx:54-56。
来源: web/src/hooks/useChatController.ts:1-210,web/src/sections/chat/ChatUI.tsx:63-188,web/src/sections/input/AppInputBar.tsx:1-208,web/src/refresh-pages/AppPage.tsx:107-164
消息渲染管线
Onyx 采用了一套复杂的渲染管线,以在保持视觉稳定性的同时处理流式文本。
文本揭示与打字机效果
为了防止大块文本到达时 UI 出现"跳跃",useTypewriter 钩子以每帧 3 个字符的固定速率揭示内容 web/src/hooks/useTypewriter.ts:5-12。
| 特性 | 实现方式 | 文件引用 |
|---|---|---|
| Markdown | 使用 remarkGfm 和 rehypeHighlight 的 ReactMarkdown | web/src/app/app/message/messageComponents/renderers/MessageTextRenderer.tsx:78-82 |
| LaTeX | 使用 remarkMath 和 rehypeKatex 处理数学公式 | web/src/app/app/message/messageComponents/renderers/MessageTextRenderer.tsx:8-9 |
| 引用 | MemoizedAnchor 将 [1] 解析为 SourceTag 组件 | web/src/app/app/message/MemoizedTextComponents.tsx:27-114 |
| 语音同步 | 内容揭示由 useVoiceMode 中的音频位置驱动 | web/src/app/app/message/messageComponents/renderers/MessageTextRenderer.tsx:110-134 |
多模型对比视图
当选择了多个模型时,MultiModelResponseView 会并排渲染响应。它支持"选择模式",在该模式下,首选响应会被居中显示,其他面板则会变暗并限制高度 web/src/app/app/message/MultiModelResponseView.tsx:53-63。
标题:多模型视图编排
来源: web/src/app/app/message/MultiModelResponseView.tsx:64-167,web/src/app/app/message/messageComponents/renderers/MessageTextRenderer.tsx:1-134,web/src/hooks/useTypewriter.ts:1-134,web/src/app/app/services/lib.tsx:17-17
交互功能
消息分支与编辑
前端支持编辑之前的人类消息,这会在对话树中触发一个新的分支。
- HumanMessage:包含一个
MessageEditing子组件,该组件将文本显示切换为textarea。提交编辑会调用onEdit,从而持久化更改并重新生成响应web/src/app/app/message/HumanMessage.tsx:22-86。 - MessageSwitcher:集成在
HumanMessage中,允许用户在消息树的不同分支(同级分支)之间导航web/src/app/app/message/HumanMessage.tsx:144-172。
导航与项目管理
聊天界面与一个侧边栏系统集成,该系统管理会话的持久化和组织:
- AppSidebar:使用
@dnd-kit管理"最近"和"固定代理",支持拖放组织web/src/sections/sidebar/AppSidebar.tsx:82-193。 - ProjectFolderButton:允许将聊天会话分组到项目中。支持重命名和删除操作,并带有确认弹窗
web/src/sections/sidebar/ProjectFolderButton.tsx:32-135。 - ChatButton:侧边栏中的单个会话链接,支持在首次生成会话标题时显示自动命名动画
web/src/sections/sidebar/ChatButton.tsx:156-178。
来源: web/src/app/app/message/HumanMessage.tsx:88-230,web/src/sections/sidebar/AppSidebar.tsx:1-193,web/src/sections/sidebar/ChatButton.tsx:102-180,web/src/sections/sidebar/ProjectFolderButton.tsx:32-204
样式与布局
该应用程序使用基于 Tailwind 的设计系统,并在 globals.css 和 tailwind.config.js 中定义了自定义令牌。
排版与主题
- 字体系统:UI/正文使用 "Hanken Grotesk",代码块使用 "DM Mono"
web/src/app/globals.css:180-187。 - 设计令牌:自定义边框半径(例如
--border-radius-12)和背景模糊效果被定义为 CSS 变量web/src/app/globals.css:34-48。 - Tailwind 扩展:定义了聊天元素的具体宽度,例如
message-default(740px)和document-sidebar(800px)web/tailwind-themes/tailwind.config.js:78-88。
全局布局
AppLayouts.Header 提供会话级别的操作,包括分享、移动到项目以及删除 web/src/layouts/app-layouts.tsx:83-110。它通过提供一个侧边栏切换按钮来适配移动端屏幕 web/src/layouts/app-layouts.tsx:87-88。
来源: web/src/app/globals.css:1-187,web/tailwind-themes/tailwind.config.js:1-173,web/src/layouts/app-layouts.tsx:69-200