主题
多面板支持
本文引用的源码文件
本文引用的文件
- src/side_panel/index.js
- src/side_panel/chat-manager.js
- src/side_panel/chat-panels.js
- src/side_panel/session-manager.js
- src/side_panel/workspace-manager.js
- src/side_panel/workspace-panel.js
- src/side_panel/search-panel.js
- src/side_panel/state.js
- src/side_panel/panel-context.js
- src/background/index.js
- src/background/react-loop.js
- src/storage/db.js
- src/storage/session-store.js
- side_panel.html
目录
引言
本文件面向“多面板支持系统”,聚焦 Chrome 扩展侧边栏(Side Panel)中的会话级多面板能力。该系统以“会话”为隔离单位,在同一个 Side Panel 中管理多个聊天会话、工作区上下文、执行日志、搜索面板等子面板,并通过 Background Service Worker 与本地 Agent 进程协作完成消息流式输出、工具调用确认、文件读写和 RAG 检索。
文档重点覆盖以下目标:
- 标签页管理机制:创建、切换、关闭、重命名、归档、恢复、复制分叉、批量操作。
- 独立会话隔离:内存空间分离、事件监听器隔离、状态同步机制。
- 面板布局管理:拖拽排序、尺寸调整、响应式适配。
- 批量操作功能:批量关闭、批量导出、批量搜索。
- 工作区管理:项目关联、文件上下文共享、协作能力。
- 面板间通信:消息传递、状态同步、事件广播。
- 性能优化:懒加载、资源释放、内存管理。
- 配置持久化:布局保存、偏好设置、主题应用。
项目结构
多面板相关代码主要位于 src/side_panel,并与 src/background、src/storage、side_panel.html 协同工作:
index.js:Side Panel 入口,负责初始化主题、i18n、全局配置监听、工具栏、输入区、会话 UI 绑定、面板可见性、版本信息等。chat-manager.js:聊天管理模块,封装发送消息、流式渲染、执行日志、导出导入、图片预览、书签、任务恢复等。session-manager.js:多会话管理 API,底层委托src/storage/session-store.js,并维护“已完成待查看”标记。workspace-manager.js:工作区数据管理,封装 Agent 文件接口、工作目录切换、远程搜索、流式下载等。workspace-panel.js:工作区面板 UI,包含嵌入模式宽度拖拽、文件列表、预览、下载等。search-panel.js:搜索面板,支持全局/当前会话搜索、增量结果、取消竞态。state.js:Side Panel 运行时状态对象。panel-context.js:面板上下文,记录会话与宿主 Tab 的映射关系。background/index.js:Background 入口,含全局快捷键、Side Panel 打开/关闭逻辑、窗口/Tab 镜像。background/react-loop.js:ReAct 执行循环,处理工具确认、交互面板路由、超时与兜底。storage/db.js、storage/session-store.js:IndexedDB 会话存储与迁移层。side_panel.html:Side Panel HTML 模板,包含输入区、记忆下拉、工具栏、搜索框等 DOM 骨架。
graph TB SP["Side Panel<br/>src/side_panel/index.js"] --> CM["聊天管理<br/>src/side_panel/chat-manager.js"] SP --> SM["会话管理<br/>src/side_panel/session-manager.js"] SP --> WM["工作区管理<br/>src/side_panel/workspace-manager.js"] SP --> WP["工作区面板<br/>src/side_panel/workspace-panel.js"] SP --> SE["搜索面板<br/>src/side_panel/search-panel.js"] SP --> ST["运行状态<br/>src/side_panel/state.js"] SP --> PC["面板上下文<br/>src/side_panel/panel-context.js"] CM --> DB["会话存储<br/>src/storage/session-store.js"] CM --> DBC["数据库层<br/>src/storage/db.js"] SP --> BG["Background 入口<br/>src/background/index.js"] BG --> RL["执行循环<br/>src/background/react-loop.js"] SP --> HTML["侧边栏模板<br/>side_panel.html"]
图表来源
- src/side_panel/index.js#L1-L34
- src/side_panel/chat-manager.js#L1-L52
- src/side_panel/session-manager.js#L1-L10
- src/side_panel/workspace-manager.js#L1-L24
- src/side_panel/workspace-panel.js#L1140-L1171
- src/side_panel/search-panel.js#L314-L354
- src/background/index.js#L581-L609
- src/background/react-loop.js#L371-L459
- side_panel.html#L531-L564
章节来源
核心组件
本节从“多面板支持”的角度,梳理关键职责边界:
- 会话生命周期:创建、切换、删除、重命名、归档、恢复、复制分叉。
- 聊天消息与流式渲染:用户输入、模型回复、工具调用、执行日志、质量评估。
- 工作区与文件:Agent 工作目录、文件浏览、预览、下载、搜索。
- 搜索面板:全局搜索与当前会话搜索,增量结果与取消竞态。
- 面板布局与交互:拖拽把手、宽度调整、响应式统计摘要。
- 背景服务与执行循环:工具确认、交互面板路由、超时保护。
- 存储层:IndexedDB 会话持久化、Chrome Storage 配置与缓存。
章节来源
- src/side_panel/session-manager.js#L69-L177
- src/side_panel/chat-manager.js#L1-L89
- src/side_panel/workspace-manager.js#L191-L335
- src/side_panel/search-panel.js#L314-L354
- src/side_panel/workspace-panel.js#L1140-L1171
- src/background/react-loop.js#L371-L459
架构总览
多面板系统的控制流可概括为:
- 用户在 Side Panel 输入或触发操作。
chat-manager.js组装上下文、选择历史、压缩策略,调用后台 API。- Background Service Worker 通过 ReAct 循环调度工具执行,必要时弹出确认对话框。
- 流式结果回写至当前会话的消息节点,同时更新执行日志、Token 使用、上下文占用指示器。
- 会话状态写入 IndexedDB;“已完成待查看”标记写入 Chrome Storage。
- 工作区面板通过 workspace-manager 访问 Agent 文件系统,支持流式下载与批量打包。
sequenceDiagram participant User as "用户" participant SP as "Side Panel<br/>index.js / chat-manager.js" participant BG as "Background<br/>react-loop.js" participant AG as "Agent 进程" participant Store as "IndexedDB<br/>session-store.js" User->>SP : 输入问题 / 触发工具 SP->>BG : 发送请求含 sessionId、上下文 BG->>AG : 调用工具 / 执行命令 AG-->>BG : 工具结果 / 流式片段 BG-->>SP : 流式消息 / 执行日志 / 状态变更 SP->>Store : 保存会话消息 / 更新活跃会话 SP->>Store : 标记会话完成待查看
图表来源
- src/side_panel/chat-manager.js#L1-L89
- src/background/react-loop.js#L371-L459
- src/side_panel/session-manager.js#L43-L65
- src/storage/session-store.js#L1-L200
详细组件分析
标签页管理与会话生命周期
会话是 Side Panel 中的“面板标签”。每个会话拥有唯一 ID、标题、消息历史、执行日志、配置快照等。核心能力包括:
- 生成会话 ID:基于时间与随机字符串。
- 创建会话:调用存储层创建新会话。
- 切换会话:更新活跃会话 ID,刷新 UI。
- 删除会话:删除存储数据,清理“完成待查看”标记。
- 重命名会话:更新标题。
- 重新排序:用于拖拽排序后的顺序持久化。
- 归档与会话恢复:将会话归档,后续可恢复为活跃会话。
- 复制分叉:完整继承源会话消息与配置,或在指定消息处截断形成分支。
flowchart TD Start(["用户操作"]) --> Create["创建会话"] Create --> Switch["切换到新会话"] Switch --> Edit["重命名 / 排序"] Edit --> Fork["复制分叉"] Fork --> Archive["归档会话"] Archive --> Restore["恢复归档会话"] Switch --> Delete["删除会话"] Delete --> Cleanup["清理完成待查看标记"]
图表来源
章节来源
独立会话隔离
多面板的核心在于“会话级隔离”:
- 内存空间分离:流式元素、累积内容、执行状态按
sessionId隔离,避免多会话并行时串台。 - 事件监听器隔离:工具确认、交互面板、完成反馈等通过
sessionId匹配,确保不同会话的确认互不干扰。 - 状态同步机制:活跃会话切换时,UI 与存储保持一致;“已完成待查看”标记通过
document自定义事件通知 UI 更新。
classDiagram
class SessionState {
+string sessionId
+HTMLElement streamingElement
+string streamedContent
+boolean isStreaming
+number thinkingStartTime
+number processStartTime
+string reasoningContent
}
class StreamingAccessor {
+createStreamingElementAccessor(sessionId)
+deleteStreamingState(sessionId)
+getStreamedContent(sessionId)
+setStreamedContent(sessionId, content)
}
class InteractionRouter {
+registerKeepalivePort(port)
+requestToolConfirmation(toolName, params, attempt, csPort)
+notifyInteractionRequired(kind, sessionId, detail)
}
SessionState <.. StreamingAccessor : "按 sessionId 隔离"
InteractionRouter --> SessionState : "会话级路由"
图表来源
章节来源
面板布局管理
布局管理涉及:
- 拖拽排序:会话列表支持拖拽后调用
reorderSessions持久化顺序。 - 尺寸调整:工作区面板嵌入模式提供左侧把手拖拽,实时更新 CSS 变量并持久化。
- 响应式适配:执行日志统计摘要根据视口宽度自适应折叠,使用 rAF 节流合并高频 resize。
flowchart TD DragStart["鼠标按下把手"] --> DragMove["mousemove 计算新宽度"] DragMove --> UpdateCSS["更新 --ws-embed-width"] UpdateCSS --> Persist["松手后持久化"] Resize["窗口 resize"] --> Adapt["rAF 节流适配统计摘要"]
图表来源
章节来源
批量操作功能
虽然仓库未提供统一的“批量关闭所有会话”按钮,但现有批量能力体现在:
- 批量导出:支持 Word、PDF、Markdown、图片等格式导出,可通过导出对话框批量处理当前会话或历史会话。
- 批量搜索:搜索面板支持全局搜索与当前会话搜索,增量结果、取消竞态,适合批量查找关键词。
- 批量下载:工作区管理器提供单文件/目录流式下载与批量打包下载。
flowchart TD BatchExport["批量导出"] --> Format["选择导出格式"] Format --> ExportAPI["调用导出接口"] BatchSearch["批量搜索"] --> Query["输入关键词"] Query --> RemoteSearch["后端递归搜索"] RemoteSearch --> Results["增量结果展示"] BatchDownload["批量下载"] --> Paths["选择多个路径"] Paths --> StreamZip["后端打包流式下载"]
图表来源
- src/side_panel/chat-manager.js#L24-L52
- src/side_panel/search-panel.js#L314-L354
- src/side_panel/workspace-manager.js#L389-L410
- src/side_panel/workspace-manager.js#L503-L576
章节来源
- src/side_panel/chat-manager.js#L24-L52
- src/side_panel/search-panel.js#L314-L354
- src/side_panel/workspace-manager.js#L389-L410
- src/side_panel/workspace-manager.js#L503-L576
工作区管理
工作区管理围绕 Agent 工作目录展开:
- 获取 Agent 配置与工作目录根路径。
- 切换工作目录:调用
/api/config/workdir,自动 mkdir 并将新 workdir 加入 allowedPaths。 - 文件操作:列出目录、读取/写入、删除、重命名、移动、统计信息。
- 远程搜索:后端递归搜索,单次请求避免前端多次串行请求。
- 流式下载:单文件/目录流式下载,支持进度回调与取消信号。
flowchart TD GetConfig["获取 Agent 配置"] --> GetWorkdir["获取工作目录"] GetWorkdir --> ListDir["列出目录内容"] ListDir --> ReadFile["读取文件内容"] ReadFile --> Preview["预览文本/图片/视频"] GetWorkdir --> SearchFiles["远程搜索文件"] GetWorkdir --> Download["流式下载"] Download --> Progress["进度回调"] Download --> Cancel["取消信号"]
图表来源
- src/side_panel/workspace-manager.js#L191-L335
- src/side_panel/workspace-manager.js#L389-L410
- src/side_panel/workspace-manager.js#L424-L498
章节来源
- src/side_panel/workspace-manager.js#L191-L335
- src/side_panel/workspace-manager.js#L389-L410
- src/side_panel/workspace-manager.js#L424-L498
面板间通信机制
面板间通信主要通过以下方式实现:
- 消息传递:Side Panel 与 Background 通过
chrome.runtime.sendMessage通信,携带sessionId、toolCallId、panel上下文等信息。 - 状态同步:通过
document.dispatchEvent(new CustomEvent('generating-state-changed'))通知 UI 更新“生成中”状态。 - 事件广播:工具确认、交互面板、完成反馈等通过 Background 路由到对应会话,避免跨会话串台。
sequenceDiagram
participant SP as "Side Panel"
participant BG as "Background"
participant UI as "UI 组件"
SP->>BG : sendMessage({ type, sessionId, panel })
BG-->>SP : onMessage(handler)
SP->>UI : dispatchEvent('generating-state-changed')
UI-->>SP : 更新状态 / 刷新 UI
图表来源
章节来源
面板性能优化
性能优化主要体现在:
- 懒加载:导出相关模块按需加载,避免首屏引入 MB 级依赖。
- 资源释放:流式状态按会话清理,DOM 缓存使用 LRU 限制大小。
- 内存管理:会话 DOM 缓存上限为 8,后台任务写入新消息后失效缓存,避免命中旧内容。
- 响应式适配:执行日志统计摘要使用 rAF 节流合并高频 resize。
flowchart TD LazyLoad["按需加载导出模块"] --> ReduceBundle["减少首屏体积"] StreamCleanup["清理流式状态"] --> FreeMemory["释放内存"] DOMCache["会话 DOM 缓存 LRU"] --> LimitSize["限制缓存大小"] RAFAdapt["rAF 节流适配"] --> SmoothResize["平滑 resize"]
图表来源
- src/side_panel/chat-manager.js#L37-L52
- src/side_panel/chat-streaming.js#L611-L625
- src/side_panel/index.js#L1703-L1728
- src/side_panel/log-summary-adaptive.js#L28-L54
章节来源
- src/side_panel/chat-manager.js#L37-L52
- src/side_panel/chat-streaming.js#L611-L625
- src/side_panel/index.js#L1703-L1728
- src/side_panel/log-summary-adaptive.js#L28-L54
面板配置的持久化
配置持久化包括:
- 布局保存:工作区嵌入宽度拖拽后持久化。
- 偏好设置:记忆限制、自动压缩、摘要存入记忆等开关立即持久化。
- 主题应用:主题 Token 体系支持亮/暗/跟随系统三态,样式通过 CSS 变量统一。
flowchart TD UserInput["用户操作"] --> SaveStorage["保存到 chrome.storage.local"] SaveStorage --> SyncUI["同步 UI 状态"] ThemeChange["主题切换"] --> ApplyTokens["应用 CSS 变量 Token"] EmbedResize["嵌入宽度拖拽"] --> PersistWidth["持久化宽度"]
图表来源
- src/side_panel/index.js#L278-L298
- src/side_panel/workspace-panel.js#L1140-L1171
- src/shared/theme.js#L1-L100
章节来源
依赖关系分析
多面板系统的依赖关系如下:
index.js依赖chat-manager.js、session-manager.js、workspace-manager.js、search-panel.js、state.js、panel-context.js。chat-manager.js依赖session-manager.js、export-import.js、image-preview.js、artifacts-manager.js、chat-resume.js、chat-streaming.js。session-manager.js依赖storage/session-store.js。workspace-manager.js依赖logger.js、i18n.js。background/index.js依赖tabs/windows事件,维护窗口/Tab 镜像。background/react-loop.js依赖chrome.runtime.onMessage,处理工具确认与交互面板路由。
graph TB Index["index.js"] --> ChatMgr["chat-manager.js"] Index --> SessionMgr["session-manager.js"] Index --> WorkspaceMgr["workspace-manager.js"] Index --> SearchPanel["search-panel.js"] ChatMgr --> SessionStore["session-store.js"] ChatMgr --> ExportImport["export-import.js"] ChatMgr --> ImagePreview["image-preview.js"] ChatMgr --> Artifacts["artifacts-manager.js"] ChatMgr --> ChatResume["chat-resume.js"] ChatMgr --> ChatStreaming["chat-streaming.js"] BackgroundIndex["background/index.js"] --> TabsWindows["tabs/windows 事件"] ReactLoop["background/react-loop.js"] --> RuntimeMsg["chrome.runtime.onMessage"]
图表来源
- src/side_panel/index.js#L1-L34
- src/side_panel/chat-manager.js#L1-L52
- src/side_panel/session-manager.js#L1-L10
- src/side_panel/workspace-manager.js#L1-L24
- src/background/index.js#L581-L609
- src/background/react-loop.js#L371-L459
章节来源
- src/side_panel/index.js#L1-L34
- src/side_panel/chat-manager.js#L1-L52
- src/side_panel/session-manager.js#L1-L10
- src/side_panel/workspace-manager.js#L1-L24
- src/background/index.js#L581-L609
- src/background/react-loop.js#L371-L459
性能与内存优化
- 懒加载:导出模块按需加载,避免首屏引入大依赖。
- 流式状态清理:按会话清理流式元素与累积内容,防止内存泄漏。
- DOM 缓存 LRU:会话 DOM 缓存上限为 8,后台任务写入新消息后失效缓存。
- rAF 节流:执行日志统计摘要使用 requestAnimationFrame 节流合并高频 resize。
- 网络请求优化:远程搜索单次请求,避免前端多次串行请求;流式下载支持取消信号释放连接。
章节来源
- src/side_panel/chat-manager.js#L37-L52
- src/side_panel/chat-streaming.js#L611-L625
- src/side_panel/index.js#L1703-L1728
- src/side_panel/log-summary-adaptive.js#L28-L54
- src/side_panel/workspace-manager.js#L389-L410
- src/side_panel/workspace-manager.js#L424-L498
故障排查指南
常见问题与排查建议:
- 工具确认无响应:检查 Background 是否收到
SHOW_CONFIRM_DIALOG,确认面板是否可见,超时是否触发 fail-closed。 - 会话状态不同步:检查
document.dispatchEvent('generating-state-changed')是否触发,UI 是否正确监听。 - 工作区不可达:检查 Agent 是否配对,网络请求是否失败,错误日志是否为“Failed to fetch”或“Load failed”。
- 流式输出串台:检查
sessionId是否正确隔离,流式元素访问器是否按会话创建。 - 导出模块加载失败:检查按需加载是否成功,依赖是否被正确引入。
章节来源
- src/background/react-loop.js#L371-L459
- src/side_panel/session-manager.js#L43-L65
- src/side_panel/workspace-manager.js#L171-L189
- src/side_panel/chat-streaming.js#L588-L625
结论
多面板支持系统以“会话”为核心,实现了标签页管理、独立会话隔离、面板布局管理、批量操作、工作区管理、面板间通信、性能优化与配置持久化。通过 Background Service Worker 与 Agent 进程的协作,系统在 Chrome 扩展环境中提供了稳定、可扩展的多面板体验。未来可进一步扩展批量关闭、批量导出、批量搜索等功能的用户界面,以提升操作效率。
附录:操作示例与最佳实践
创建新面板
- 调用
createSession()创建新会话。 - 调用
switchToSession(sessionId)切换到新会话。 - 调用
renderSessionTabs()更新标签 UI。
章节来源
切换面板
- 调用
switchToSession(sessionId)切换活跃会话。 - 调用
saveCurrentSession()保存当前会话状态。 - 调用
loadSessions()加载会话列表。
章节来源
执行批量操作
- 批量导出:调用
performExport(format)导出当前会话或历史会话。 - 批量搜索:调用
searchFilesRemote(dirPath, query, maxResults)远程搜索文件。 - 批量下载:调用
downloadFilesStream(paths)批量打包下载。
章节来源