Skip to content

工作区与会话管理 ​

本文引用的源码文件

本文引用的文件

更新摘要 ​

变更内容

  • 新增“浏览…”按钮,用于本地代理集成下的原生目录选择框功能
  • 实现跨平台系统原生目录选择器(macOS osascript、Windows PowerShell FolderBrowserDialog、Linux zenity/kdialog)
  • 添加安全验证机制:仅允许本机回环地址访问目录选择 API,远端请求返回 available:false
  • 完善国际化支持:新增 workspace.browseBtn、browseUnavailable、browseFailedWithError、picking 等翻译键
  • 增强工作区切换对话框的用户体验,支持从允许目录列表中选择或手动输入路径

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与优化
  8. 故障排查
  9. 结论

引言 ​

本文面向"工作区与会话管理"这一主题,围绕以下目标展开:

  • 解释工作区概念:项目隔离、配置共享、资源管理与 Agent 连接。
  • 说明会话管理器:会话创建、状态持久化、并发控制与 UI 交互。
  • 描述工作区面板的界面行为:树形浏览、文件操作、预览与反馈。
  • 描述会话管理界面:会话列表、状态监控、批量操作。
  • 给出代码级示例路径,展示如何创建工作区、管理多会话生命周期。
  • 说明数据同步机制:本地 IndexedDB、chrome.storage 兜底、归档与备份导入导出。
  • 说明权限与安全边界:Agent 配对、允许目录、删除回收站语义。
  • 总结性能策略:流式下载、虚拟滚动、增量保存、并发切换等。

本项目为双进程架构:Chrome 扩展端(Manifest V3,版本 2.3.1)+ 独立本地代理端 Agent(Node.js,版本 2.3.1)。扩展端通过 HTTP/WebSocket 调用 Agent 的文件系统、命令执行、长期记忆与 RAG 能力;Agent 源码修改后需重启进程接口才生效。

章节来源

项目结构 ​

与工作区和会话相关的主要代码位于 side panel 层和 storage 层:

  • src/side_panel/workspace-manager.js:工作区 API 封装,负责与 Agent 通信、路径缓存、文件读写与下载。
  • src/side_panel/workspace-panel.js:工作区面板 UI,包含目录导航、多选、上传/下载、预览、重命名、移动、删除等。
  • src/side_panel/session-manager.js:会话管理对外 API,转发到存储层并维护"完成待查看"标记。
  • src/side_panel/session-manager-ui.js:会话标签栏 UI,渲染会话列表、搜索、拖拽排序、批量关闭、分叉复制等。
  • src/storage/session-store.js:IndexedDB 会话存储适配器,提供会话 CRUD、归档、恢复、复制、定时任务宿主会话等。
  • src/side_panel/state.js:全局状态,包括活跃会话、消息历史、生成状态、Agent 信息等。
  • agent/src/directory-picker.js:系统原生目录选择器实现,支持跨平台目录选择。
  • agent/src/server.js:Agent 服务器,提供目录选择 API 和安全门控。
graph TB
subgraph "Side Panel"
WP["workspace-panel.js<br/>工作区面板 UI"]
WM["workspace-manager.js<br/>工作区 API"]
SMUI["session-manager-ui.js<br/>会话标签栏 UI"]
SM["session-manager.js<br/>会话管理 API"]
ST["state.js<br/>全局状态"]
end
subgraph "Storage"
SS["session-store.js<br/>IndexedDB 会话存储"]
end
subgraph "Agent 本地代理"
AG["Agent HTTP API<br/>/api/fs/* /api/config/* /api/status/*"]
DP["directory-picker.js<br/>原生目录选择器"]
SV["server.js<br/>API 路由与安全门控"]
end
WP --> WM
WM --> AG
SMUI --> SM
SM --> SS
SMUI --> ST
SM --> ST
SS --> ST
AG --> DP
AG --> SV

图表来源

章节来源

核心组件 ​

本节从职责边界角度梳理关键模块:

  • 工作区管理器(workspace-manager.js)

    • 负责获取 Agent 配置、工作目录根路径、家目录、状态详情。
    • 封装文件系统操作:列出目录、读取/写入内容、删除、重命名、创建目录、移动、统计信息。
    • 封装下载能力:单文件/批量下载、带进度流式下载、取消支持。
    • 新增:pickDirectory() 函数,调用 Agent 的 /api/config/pick-directory 接口进行原生目录选择。
    • 提供远程搜索、MIME 类型判断、预览类型分类、文件大小/时间格式化等工具函数。
    • 对 Agent 不可达进行降级日志处理,避免控制台噪音。
  • 工作区面板(workspace-panel.js)

    • 初始化浮窗/嵌入双模式面板,绑定事件、渲染面包屑、工具栏、文件列表、预览遮罩层。
    • 实现目录导航、排序、全选/多选、批量下载 ZIP、批量删除、重命名、新建文件夹、移动。
    • 集成文件预览:文本、Markdown、PDF、Excel、PPTX、图片、视频、音频等。
    • 支持上传、拖拽移动、键盘导航、上下文问答附件。
    • 已更新:增强了文件列表点击交互逻辑,改进了虚拟滚动支持和焦点管理机制。
    • 新增:工作区切换对话框中的"浏览…"按钮,仅在本地代理时显示,调用原生目录选择器。
  • 会话管理器(session-manager.js)

    • 暴露会话创建、加载、保存、切换、删除、重命名、排序、归档、恢复、导入、追加消息、复制会话等 API。
    • 维护"完成待查看"会话集合,持久化到 chrome.storage.local,并在 UI 上显示提示。
  • 会话管理 UI(session-manager-ui.js)

    • 渲染会话标签栏、下拉列表、分组标题(今天/昨天/近 7 天/更早)、搜索过滤。
    • 支持拖拽排序、右键菜单、中键关闭、批量关闭、按组关闭、会话分叉复制。
    • 与 session-manager.js 解耦,通过 DOM 事件通知上层。
  • 会话存储(session-store.js)

    • 基于 IndexedDB 的会话持久化,兼容旧 chrome.storage 迁移。
    • 提供会话列表加载、当前会话保存、切换、删除、归档、恢复、复制、定时任务宿主会话等。
    • 清理 ReAct checkpoint、书签、scrollPosition 等关联数据。
  • 全局状态(state.js)

    • 集中管理活跃会话 ID、消息历史、模型参数、工具开关、Agent 信息等。
    • 通过 getter/setter 代理默认导出对象,保证多种 import 方式共享同一份数据。
  • 原生目录选择器(directory-picker.js)

    • 新增:跨平台系统原生目录选择器实现。
    • 支持 macOS (osascript)、Windows (PowerShell FolderBrowserDialog)、Linux (zenity/kdialog)。
    • 提供 buildPickCommand() 和 pickDirectoryNative() 两个主要函数。
    • 包含超时保护、错误处理、路径规范化等功能。
  • Agent 服务器(server.js)

    • 新增:/api/config/pick-directory 路由,提供目录选择 API。
    • 实现安全门控:仅允许本机回环地址访问,远端请求返回 available:false。
    • 集成 directory-picker.js 实现原生目录选择功能。

章节来源

架构总览 ​

工作区与会话管理的整体流程如下:

sequenceDiagram
participant User as "用户"
participant WP as "工作区面板<br/>workspace-panel.js"
participant WM as "工作区管理器<br/>workspace-manager.js"
participant AG as "Agent 本地代理"
participant DP as "目录选择器<br/>directory-picker.js"
participant SV as "服务器<br/>server.js"
participant SMUI as "会话标签栏 UI<br/>session-manager-ui.js"
participant SM as "会话管理器<br/>session-manager.js"
participant SS as "会话存储<br/>session-store.js"
participant ST as "全局状态<br/>state.js"
User->>WP : 打开工作区面板
WP->>WM : getWorkspaceRoot()
WM->>AG : GET /api/status/detail
AG-->>WM : {workdir, homeDir}
WM-->>WP : workdir
User->>WP : 点击切换工作目录
WP->>WM : pickDirectory()
WM->>AG : POST /api/config/pick-directory
AG->>SV : 安全检查 (localhost only)
SV->>DP : pickDirectoryNative()
DP-->>SV : {success, path, available}
SV-->>WM : 目录选择结果
WM-->>WP : 填充路径输入框
User->>WP : 确认切换
WP->>WM : switchWorkspace(newPath)
WM->>AG : POST /api/config/workdir
AG-->>WM : 切换结果
WM-->>WP : 刷新工作区
User->>SMUI : 点击新建会话
SMUI->>SM : createSession()
SM->>SS : createSession()
SS->>SS : IndexedDB putSession + setActiveSessionId
SS-->>SM : newSession
SM-->>SMUI : newSession
SMUI->>ST : state.activeSessionId = newSession.id
SMUI->>SMUI : renderSessionTabs()

图表来源

详细组件分析 ​

工作区管理器(workspace-manager.js) ​

工作区管理器是扩展端与 Agent 之间的桥梁,承担以下职责:

  • 获取 Agent 配置:从 chrome.storage.local 读取 pairedAgents 与 activeAgentId,构造 URL 与 token。
  • 探测工作目录与家目录:调用 /api/status/detail,缓存 workdir 与 homeDir。
  • 切换工作目录:调用 /api/config/workdir,成功后重置本地缓存。
  • 文件系统操作:listDirectory、readFileContent、writeFileContent、deleteFs、renameFs、createDir、moveFs、getFileInfo。
  • 下载能力:downloadFileStream、downloadFilesStream、downloadFileStreamWithProgress、downloadFilesStreamWithProgress,支持 AbortSignal 取消。
  • 新增:pickDirectory() 函数,调用 /api/config/pick-directory 接口进行原生目录选择。
  • 远程搜索:searchFilesRemote,后端递归搜索,前端统一归一化路径。
  • 错误处理:isAgentUnreachableError 与 logProbeFailure 将网络失败降为 debug,避免控制台噪音。
flowchart TD
Start(["调用 agentRequest"]) --> GetConfig["读取 Agent 配置<br/>pairedAgents + activeAgentId"]
GetConfig --> HasConfig{"是否已配对?"}
HasConfig --> |否| ReturnNotPaired["返回未配对错误"]
HasConfig --> |是| Fetch["POST /api/... with Authorization Bearer"]
Fetch --> RespOk{"响应成功?"}
RespOk --> |否| ParseErr["解析 JSON 或返回错误"]
RespOk --> |是| ReturnData["返回业务数据"]
ParseErr --> ReturnData
ReturnNotPaired --> End(["结束"])
ReturnData --> End

图表来源

章节来源

工作区面板(workspace-panel.js) ​

工作区面板负责呈现目录树、文件列表、预览与操作反馈:

  • 初始化面板容器、按钮、面包屑、工具栏、文件头、内容区域、预览遮罩层。
  • 绑定事件:切换面板、切换工作目录、返回上级、刷新、上传、新建文件夹、问答附件、批量下载、批量删除、搜索、排序、全选、键盘导航、拖拽移动。
  • 文件预览:根据扩展名判断预览类型,支持 Markdown、PDF、Excel、PPTX、图片、视频、音频、HTML 源码与渲染预览。
  • 大文件处理:超过阈值时提示直接下载或在浏览器中打开。
  • 下载进度:使用 ReadableStream 读取 chunk,计算 loaded/total/percent,支持取消。
  • 上传与移动:支持拖拽移动至目标目录,移动前校验不能移动到子目录。
  • 删除确认:区分文件与目录,提示可恢复至回收站(7 天后自动清理)。

已更新:增强了文件列表点击交互逻辑,改进了虚拟滚动支持和焦点管理机制。现在 handleFileListClick 函数能够正确处理虚拟滚动和非虚拟滚动两种场景,使用条件逻辑计算正确的全局索引以确保焦点管理的准确性。

新增:工作区切换对话框中的"浏览…"按钮功能。当检测到本地代理(localhost/127.0.0.1/[::1])时,显示浏览按钮,点击后调用原生目录选择器,将选中的路径填入输入框。

sequenceDiagram
participant User as "用户"
participant WP as "workspace-panel.js"
participant WM as "workspace-manager.js"
participant AG as "Agent"
User->>WP : 双击文件
WP->>WM : supportsPreview/getPreviewType
alt 文本/代码/HTML
WP->>WM : readFileContent(filePath)
WM->>AG : POST /api/fs/read
AG-->>WM : content
WM-->>WP : text/html
WP->>WP : 渲染源码/渲染预览
else PDF/Excel/PPTX/图片/音视频
WP->>WM : downloadFileStreamWithProgress(filePath, onProgress)
WM->>AG : POST /api/fs/download-stream
AG-->>WM : Blob + headers
WM-->>WP : blob/name/mimeType
WP->>WP : 渲染媒体/表格/文档
end
User->>WP : 点击切换工作目录
WP->>WP : 检测本地代理
alt 本地代理
WP->>WM : pickDirectory()
WM->>AG : POST /api/config/pick-directory
AG-->>WM : {success, path, available}
WM-->>WP : 填充路径输入框
else 非本地代理
WP->>WP : 隐藏浏览按钮
end

图表来源

章节来源

原生目录选择器(directory-picker.js) ​

新增组件:系统原生目录选择器,提供跨平台的目录选择功能。

主要功能 ​

  • buildPickCommand(title, platform):根据操作系统构造相应的目录选择命令
    • macOS:使用 osascript 调用 choose folder
    • Windows:使用 PowerShell FolderBrowserDialog
    • Linux:优先使用 zenity,回退到 kdialog
  • pickDirectoryNative(title, options):执行目录选择,返回标准化结果
    • 支持超时保护(120秒默认超时)
    • 处理用户取消、无 GUI 环境、命令不可用等情况
    • 返回统一的结果格式:

安全特性 ​

  • 标题参数经过安全清理,防止脚本注入
  • 所有命令以参数数组形式传入,避免 shell 注入
  • Windows 使用 base64 编码的 UTF-16LE 脚本,避免命令行转义问题
flowchart TD
Start(["pickDirectoryNative()"]) --> CheckDisplay{"检查图形界面环境"}
CheckDisplay --> |Linux无DISPLAY| ReturnNoGUI["返回 available:false"]
CheckDisplay --> |有GUI| BuildCmd["buildPickCommand()"]
BuildCmd --> RunCmd["spawn 子进程执行命令"]
RunCmd --> Timeout{"超时保护(120s)"}
Timeout --> |超时| KillProcess["kill 子进程"]
KillProcess --> ReturnTimeout["返回 timeout 错误"]
Timeout --> |正常| CollectOutput["收集 stdout 输出"]
CollectOutput --> Normalize["normalizePickedPath()"]
Normalize --> Validate{"路径有效?"}
Validate --> |是| ReturnSuccess["返回 {success:true, path}"]
Validate --> |否| ReturnCancel["返回 {success:true, path:null}"]
ReturnNoGUI --> End(["结束"])
ReturnTimeout --> End
ReturnSuccess --> End
ReturnCancel --> End

图表来源

章节来源

Agent 服务器目录选择 API(server.js) ​

新增功能:/api/config/pick-directory 路由,提供安全的目录选择 API。

安全门控 ​

  • 仅允许本机回环地址访问:127.0.0.1、::1、::ffff:127.0.0.1、localhost
  • 远端请求返回 available:false,扩展端据此隐藏浏览按钮
  • 记录安全日志:logSecurity('pick_directory_remote_blocked', ...)

错误处理 ​

  • 捕获目录选择过程中的异常,返回结构化错误信息
  • 记录系统日志:logSystem('directory_picked', ...)
  • 超时保护:子进程悬挂时自动终止
flowchart TD
Request["POST /api/config/pick-directory"] --> CheckIP["检查来源 IP"]
CheckIP --> IsLocal{"是否本机地址?"}
IsLocal --> |否| Block["返回 available:false"]
IsLocal --> |是| Execute["执行 pickDirectoryNative()"]
Execute --> Success{"选择成功?"}
Success --> |是| LogSuccess["记录日志"]
LogSuccess --> ReturnSuccess["返回 {success:true, path}"]
Success --> |否| HandleError["处理错误"]
HandleError --> ReturnError["返回 {success:false, error}"]
Block --> End(["结束"])
ReturnSuccess --> End
ReturnError --> End

图表来源

章节来源

虚拟滚动与焦点管理增强 ​

新增功能:工作区面板现在具备增强的虚拟滚动支持和改进的焦点管理机制。

虚拟滚动实现 ​

  • 当文件项超过阈值(VIRTUAL_SCROLL_THRESHOLD)时自动启用虚拟滚动
  • 仅渲染可视区域 + 缓冲区的文件项,大幅提升大数据集性能
  • 动态测量实际行高,修正估算值以提高渲染精度
  • 智能滚动位置计算,避免不必要的 DOM 重建

焦点管理改进 ​

  • 在 handleFileListClick 函数中添加了条件逻辑来处理虚拟滚动和非虚拟滚动场景
  • 虚拟滚动模式下:通过 virtualScrollState.sorted.findIndex 查找全局索引
  • 非虚拟滚动模式下:直接使用 items.indexOf 获取相对索引
  • 确保 focusedIndex 始终为全局绝对下标,避免 updateFocusVisual 计算错误
flowchart TD
Click["文件列表点击"] --> CheckVirtual{"是否虚拟滚动模式?"}
CheckVirtual --> |是| FindGlobalIdx["virtualScrollState.sorted.findIndex<br/>查找全局索引"]
CheckVirtual --> |否| FindRelIdx["items.indexOf<br/>获取相对索引"]
FindGlobalIdx --> UpdateFocus["更新 focusedIndex<br/>调用 updateFocusVisual"]
FindRelIdx --> UpdateFocus
UpdateFocus --> ApplyVisual["应用视觉焦点样式"]
ApplyVisual --> ScrollIfNeeded{"需要滚动到可视区域?"}
ScrollIfNeeded --> |是| AutoScroll["自动滚动到目标位置"]
ScrollIfNeeded --> |否| Complete["完成"]
AutoScroll --> Complete

图表来源

章节来源

会话管理器(session-manager.js) ​

会话管理器作为对外 API,屏蔽底层存储细节:

  • 恢复 completedSessionIds:从 chrome.storage.local 读取,用于刷新后仍显示"完成待查看"。
  • 标记完成/清除完成:仅对非活跃会话标记,避免重复写入,触发 UI 更新事件。
  • 会话 CRUD:loadSessions、saveSessions、saveCurrentSession、createSession、switchToSession、deleteSession、renameSession、reorderSessions、archiveCurrentSession、restoreArchivedSession、importSessions、appendMessageToSession、duplicateSession。
  • 与 session-store.js 完全解耦,保持 API 兼容。
classDiagram
class SessionManager {
+restoreCompletedSessions()
+markSessionCompleted(sessionId)
+clearSessionCompleted(sessionId)
+generateSessionId()
+loadSessions()
+saveSessions(sessionsData)
+saveCurrentSession()
+createSession()
+switchToSession(sessionId)
+deleteSession(sessionId)
+renameSession(sessionId, newTitle)
+reorderSessions(orderedIds)
+archiveCurrentSession()
+restoreArchivedSession(archivedId)
+importSessions(sessionsData)
+appendMessageToSession(sessionId, message)
+duplicateSession(sourceSessionId, upToMessageId)
}
class SessionStore {
+init()
+loadSessions()
+saveSessions(sessionsData)
+saveCurrentSession()
+createSession()
+switchToSession(sessionId)
+deleteStoreSession(sessionId)
+renameSession(sessionId, newTitle)
+reorderSessions(orderedIds)
+archiveCurrentSession()
+restoreArchivedSession(archivedId)
+importSessions(sessionsData)
+appendMessageToSession(sessionId, message)
+duplicateSession(sourceSessionId, upToMessageId)
}
SessionManager --> SessionStore : "委托"

图表来源

章节来源

会话管理 UI(session-manager-ui.js) ​

会话标签栏 UI 负责会话列表的可视化与交互:

  • 渲染会话标签:标题、关闭按钮、生成中指示器、完成待查看指示器。
  • 会话切换:乐观高亮,防连点,异常时回滚高亮。
  • 更多按钮与下拉面板:分组标题(今天/昨天/近 7 天/更早),搜索过滤,键盘导航。
  • 批量操作:关闭全部、按组关闭、删除单个会话。
  • 拖拽排序:dragstart/dragover/dragleave/drop/dragend,持久化 order。
  • 会话分叉:复制源会话的消息历史与配置,自动生成新会话并激活。
sequenceDiagram
participant User as "用户"
participant SMUI as "session-manager-ui.js"
participant SM as "session-manager.js"
participant SS as "session-store.js"
participant ST as "state.js"
User->>SMUI : 点击新建会话
SMUI->>SM : saveCurrentSession()
SM->>SS : saveCurrentSession()
SMUI->>SM : createSession()
SM->>SS : createSession()
SS-->>SM : newSession
SM-->>SMUI : newSession
SMUI->>ST : state.activeSessionId = newSession.id
SMUI->>SMUI : renderSessionTabs()

图表来源

章节来源

会话存储(session-store.js) ​

会话存储是持久化核心,基于 IndexedDB:

  • 初始化与迁移:ensureMigration,清理孤儿 scrollPosition key。
  • 会话列表加载:getAllSessions + getActiveSessionId,按 order 排序。
  • 当前会话保存:合并 state 中的模型、工具、Agent、温度、topP、上下文压缩记录、消息历史。
  • 切换会话:并发保存当前会话与读取目标会话,恢复 state 与 Agent 配置。
  • 删除会话:清理 ReAct checkpoint、书签、scrollPosition,就近激活下一个会话。
  • 归档与恢复:最多保留 20 个归档,恢复时创建新活跃会话。
  • 复制会话:完整复制或消息级截断,重新生成 messageId,记录 forkMetadata。
  • 定时任务宿主会话:为 scheduledTaskId 创建专属宿主会话。
flowchart TD
Switch["switchToSession(sessionId)"] --> SaveCurrent["saveCurrentSession()"]
Switch --> LoadTarget["idb.getSession(sessionId)"]
SaveCurrent --> SetActive["idb.setActiveSessionId(sessionId)"]
LoadTarget --> SetState["state.activeSessionId/messageHistory/compaction/model/temperature/topP/tools/agentId"]
SetActive --> ApplyAgent["加载 Agent 配置并触发 agent-model-changed"]
ApplyAgent --> CleanupGen["清理过期 isGenerating 标记"]
CleanupGen --> Return["返回 targetSession"]

图表来源

章节来源

依赖关系分析 ​

工作区与会话管理的依赖关系如下:

graph LR
WP["workspace-panel.js"] --> WM["workspace-manager.js"]
WM --> CHROME["chrome.storage.local"]
WM --> AGENT["Agent HTTP API"]
AGENT --> DIRPICKER["directory-picker.js"]
AGENT --> SERVER["server.js"]
SMUI["session-manager-ui.js"] --> SM["session-manager.js"]
SM --> SS["session-store.js"]
SS --> IDB["IndexedDB"]
SMUI --> ST["state.js"]
SM --> ST
  • workspace-panel.js 依赖 workspace-manager.js 提供的文件系统与下载 API。
  • workspace-manager.js 依赖 chrome.storage.local 获取 Agent 配置,依赖 Agent HTTP API 执行文件操作。
  • 新增:workspace-manager.js 新增 pickDirectory() 方法,调用 Agent 的 /api/config/pick-directory 接口。
  • 新增:Agent server.js 依赖 directory-picker.js 实现原生目录选择功能。
  • session-manager-ui.js 依赖 session-manager.js 的会话 API,并通过 state.js 更新 UI 状态。
  • session-manager.js 依赖 session-store.js 的持久化 API。
  • session-store.js 依赖 IndexedDB 与 chrome.storage.local(兜底与迁移)。

图表来源

章节来源

性能与优化 ​

  • 流式下载:workspace-manager.js 使用 ReadableStream 读取 chunk,计算进度,支持 AbortController 取消,避免 base64 膨胀。
  • 虚拟滚动:当文件项超过阈值时自动启用虚拟滚动,仅渲染可见区域,大幅优化大目录性能。虚拟滚动状态管理包括 sorted 数组、itemHeight 测量、滚动位置跟踪等。
  • 增强的焦点管理:handleFileListClick 函数现在正确处理虚拟滚动和非虚拟滚动场景,确保键盘导航和焦点状态的准确性。
  • 原生目录选择优化:directory-picker.js 实现跨平台目录选择,支持超时保护(120秒)、命令回退机制(Linux zenity→kdialog)、路径规范化处理。
  • 目录缓存:文档提到 LRU 缓存最近 20 个目录(30s TTL),避免重复请求;同时 Agent 切换时自动重置缓存。
  • 并发切换:session-store.js 在 switchToSession 中并发保存当前会话与读取目标会话,减少切换延迟。
  • 按需加载:workspace-panel.js 对 pdfjs-dist、mammoth、pptx-to-html 等重型库采用动态加载,避免首屏阻塞。
  • 预览优化:workspace-panel.js 对 HTML 预览使用 iframe sandbox,避免双层滚动条;对大文件限制内置预览,引导下载。

章节来源

故障排查 ​

  • Agent 未配对:workspace-manager.js 在 getAgentConfig 失败时返回 null,UI 应提示"Agent 未配对",引导用户在设置中完成配对。
  • Agent 不可达:workspace-manager.js 将网络错误降为 debug 日志,避免控制台噪音;UI 应显示"Agent 未连接"提示。
  • 工作目录获取失败:getWorkspaceRoot 失败时返回 null,UI 应提示"无法获取工作目录,请确认 Agent 已连接"。
  • 下载失败:downloadFileStreamWithProgress 返回 error 字段,UI 应显示"下载失败"或具体错误信息。
  • 会话切换失败:session-manager-ui.js 在切换异常时回滚高亮,并重新渲染会话标签栏。
  • 会话存储异常:session-store.js 在 deleteStoreSession 中清理 ReAct checkpoint、书签、scrollPosition,避免脏数据残留。
  • 虚拟滚动焦点问题:如果虚拟滚动模式下焦点管理出现异常,检查 handleFileListClick 中的索引计算逻辑是否正确处理了 virtualScrollState 条件分支。
  • 目录选择失败:
    • 检查 Agent 是否为本地代理(localhost/127.0.0.1/[::1]),非本地代理会返回 available:false
    • 检查系统是否安装了必要的目录选择工具(macOS osascript、Windows PowerShell、Linux zenity/kdialog)
    • 检查是否有图形界面环境(Linux DISPLAY/WAYLAND_DISPLAY 环境变量)
    • 检查超时设置(默认120秒),长时间不选择会自动终止
  • 安全门控问题:远端请求被拒绝时,检查 server.js 中的 IP 白名单逻辑是否正确配置。

章节来源

结论 ​

工作区与会话管理在本项目中形成了清晰的职责分层:

  • 工作区管理器负责与 Agent 通信,封装文件系统与下载能力。最新增强:新增原生目录选择功能,支持跨平台系统目录选择器。
  • 工作区面板负责用户交互,提供目录浏览、文件操作、预览与反馈。最新增强:改进了虚拟滚动支持和焦点管理机制,新增了"浏览…"按钮和本地代理集成。
  • 会话管理器提供统一的会话 API,屏蔽存储细节。
  • 会话管理 UI 负责会话列表的可视化与批量操作。
  • 会话存储基于 IndexedDB,提供持久化、归档、恢复、复制等能力。
  • 全局状态集中管理活跃会话、消息历史、Agent 信息等。
  • 新增:原生目录选择器提供跨平台系统级目录选择功能,支持 macOS、Windows、Linux 三大平台。
  • 新增:Agent 服务器提供安全的目录选择 API,包含 IP 白名单安全门控。

通过流式下载、虚拟滚动、并发切换、按需加载等优化策略,系统在大数据集与多会话场景下保持了较好的性能与用户体验。最新的虚拟滚动和焦点管理增强进一步提升了文件列表的交互体验,特别是在处理大量文件时的性能和可用性方面有了显著改善。新增的原生目录选择功能为用户提供了更直观的目录选择方式,特别是在本地代理环境下,可以直接调用系统原生目录选择器,提升用户体验。权限方面,通过 Agent 配对、允许目录、删除回收站语义等机制,确保了安全边界。新增的安全门控机制确保只有本机代理可以访问目录选择功能,防止远程攻击。未来可进一步探索云端备份与冲突解决机制,以增强数据同步能力。