Skip to content

Latest commit

 

History

History
223 lines (168 loc) · 20.5 KB

File metadata and controls

223 lines (168 loc) · 20.5 KB

界面

文档入口:用户指南 · 关联:架构(事件驱动渲染) · 权限(审批卡片语义) 相关调研:OpenWebUI 的消息树、触发符和流式渲染,以及 Claude Code Desktop 和 Codex 的工具卡片布局。

当前已有侧边栏、全屏页、共享消息流与输入框,以及十一项设置导航。队列编辑、恢复卡、Attachments、站点指令、ModelPreset、Plugin、MCP Prompt/Resource 与交互卡已接入。待审批、待输入或恢复通知可以打开对应会话;Skill auto_suggest 胶囊和完整的性能诊断界面仍未接入。


1. 设计 Token

设计 Token 以 src/ui/styles/global.css 为准。本节只解释用途,不复制完整色值。

  • 品牌色:靛青(indigo)。light = indigo-600 --primary + 白前景;dark = indigo-400 + indigo-950 前景(亮填充保证 text-primary 在暗底可读)。--ring 恒等于 --primary
  • 语义色各司其职:warning = 琥珀(审批卡、恢复横幅的警示语义,light 用 amber-700 保文本对比度);info = 青色(工具/Agent 活动、reasoning、L2 升级 —— 刻意远离靛青,避免与品牌色混淆);success / destructive 常规绿红(light 取深档达 4.5:1)。
  • 中性色带轻微靛青偏色(hue ~245),让 chrome 与品牌色成一体。
  • 状态色是"文本色"标准:light 一律取深档(700 级),dark 取亮档 —— 改动时先算对比度再落值。
--font-ui: Inter, 'PingFang SC', system-ui;
--font-mono: 'JetBrains Mono', ui-monospace; /* 工具参数、代码、ref、成本数字 */

--radius-card: 10px;
--radius-input: 12px;
--radius-chip: 999px;
--space-unit: 4px; /* 间距全为 4 的倍数;消息纵距 16px,工具卡片纵距 8px(紧凑)*/
--text-body: 14px/1.6;
--text-tool: 13px;
--text-meta: 11px;
  • 主题:跟随系统 + 手动三态;两套色板同一变量名,组件零感知。
  • 动效克制:流式光标(accent 方块闪烁)、工具卡片状态色过渡 150ms、审批卡片入场 slide-in 200ms。禁用装饰性动画。

2. 组件层级树(两形态共享核心)

 <ThreadView>                        ← 侧边栏与全屏页共用
 ├─ <MessageStream>                 虚拟滚动(长会话)
 │   ├─ <UserMessage>               编辑重发入口 → 分叉
 │   ├─ <AssistantMessage>           同一 turn 的完整 Agent 工作单元
 │   │   ├─ <Collapsible>           运行中展开过程,完成后默认收起
 │   │   │   ├─ <ReasoningBlock>    按真实事件顺序展示思考
 │   │   │   └─ <ToolCallGroup>     与思考交替出现的连续工具调用组
 │   │   │       └─ <ToolCallCard>  一行摘要 + 可展开详情
 │   │   │           └─ <SnapshotViewer>/<ScreenshotViewer>/<DiffViewer>   details 通道渲染
 │   │   ├─ <MarkdownRenderer>      最终回答常驻在折叠过程之外
 │   │   ├─ <CitationsPill>         本轮访问来源
 │   │   └─ <BranchSwitcher>        ‹ 2/3 ›(siblings 派生,见数据模型文档 §3.2)
 │   ├─ <ApprovalCard>              审批 RPC 的 UI 端
 │   └─ <SystemNotice>              暂停/软提醒等浅色横条
 │   └─ <InteractionCard>           提问/接管/页面等待/定时/MCP Elicitation
 ├─ <PromptInput>
 │   ├─ <TriggerMenu>               @ / 斜杠 统一建议框架
 │   ├─ <AttachmentTray>  <ContextChips>   已附着的页面/选区/文件胶囊
 │   └─ <InputToolbar>              模型选择器 · 工具级别开关 · 发送/Stop

3. 页面线框

3.1 全屏对话页(双栏,对话内容 768px 上限居中)

┌─────────────┬───────────────────────────────────────────────────────────┐
│ ⌕ 搜索会话    │  耳机调研对比                              claude-sonnet-5 │
│ ✚ 新会话     │ ───────────────────────────────────────────────────────── │
│─────────────│  ◆ 帮我调研这三款耳机的评价并做对比表                        │
│ 📁 购物研究   │                                                           │
│   ● 耳机调研  │  处理中 ▾                                                 │
│   翻译PDF    │  ──────────────────────────────────────────────────────── │
│ 今天         │  我将先读取当前页面,再根据结果继续打开并提取其他页面。          │
│   周报生成    │  ▸ 运行了 3 个命令                                        │
│ 昨天         │  已获得三款商品的评价数据,正在整理对比。                      │
│   …         │                                                           │
│             │  ⚠ 允许在 taobao.com 点击 [加入购物车] ?                    │
│             │    [允许一次·Y] [本轮会话·S] [本站始终·A] [拒绝·N]           │
│─────────────│ ───────────────────────────────────────────────────────── │
│ ⚙ 设置       │  ⌨ @引用 /命令…                     [claude-s5▾][🌐▾][➤] │
└─────────────┴───────────────────────────────────────────────────────────┘

当前左栏:按更新时间分组、置顶、未读/运行/审批状态;搜索先查最近 200 个 Thread 标题,再对最多 50 个标题未命中的最近会话扫描消息正文,不是 Dexie FTS 索引。行菜单支持改名、置顶/取消置顶、删除;文件夹、移动、归档和单会话导出尚未接入。过长的会话标题保持单行,并在行内和侧边栏头部显示省略号。思考与工具调用按真实事件顺序保留在同一条 Agent 消息内,不再使用独立任务面板。

响应式布局:宽度达到 1024px 时显示可调整宽度的左侧会话栏;更窄时会话栏进入左侧 Sheet,由顶栏按钮打开,主对话独占可用宽度。顶栏使用对称三列网格,模型入口位于左侧,会话标题保持视觉居中;消息流和输入区继续共享 768px 内容上限。

3.2 侧边栏(360–500px)

侧边栏头部的展开按钮和 Cmd/Ctrl+E 会在全页对话中定位当前会话;全页标签创建成功后关闭当前窗口中的 Panelot 侧边栏,避免两种对话形态同时占用界面。全页端的 Cmd/Ctrl+E 会先重新打开同一窗口的 Panelot 侧边栏,成功后再关闭全页标签。

侧边栏按独立应用页面处理:根布局使用动态视口高度并锁定横向溢出,头部、消息流和底部输入区分别承担固定导航、可滚动内容和持续可用的主操作。窄宽度下消息、空态、审批卡和输入区收紧水平留白;模型与权限入口允许在中间工具带内滚动,发送/停止按钮始终保留在可见区域。输入框按实际换行后的内容高度自适应,宽度变化时重新测量;长草稿达到面板 42dvh / 16rem 或全页 45dvh / 20rem 上限后改为内部滚动,连续长字符串可在任意位置换行。

侧边栏会在 chrome.storage.local 记录最后选中的真实会话。浏览器或侧边栏重新打开时先校验该 Thread 仍存在、未归档且未处于删除状态,再恢复原会话;记录失效时回退到最近更新的有效会话,无有效会话时进入不落库的新会话草稿。若 UI 与后台协议版本不一致,界面停止重连和加载骨架,禁用输入并提示重载扩展,不把该状态误报为 Provider 端点错误。

┌────────────────────────────┐
│ 耳机调研 ▾         ⛶  ✚  ⋯ │   ← 会话下拉 / 展开全屏(定位当前会话) / 新会话
│────────────────────────────│
│ 📎 当前页: 淘宝-XX耳机  [+]  │   ← 上下文胶囊:默认不注入,点+附着
│────────────────────────────│
│      (MessageStream 同款)    │
│────────────────────────────│
│ ⌨ 问问当前页面…        [➤]  │
│ claude-sonnet-5 ▾  🌐▾  ⏹  │
└────────────────────────────┘

3.3 首次引导(Onboarding,全屏页首启)

首次引导分三步:选择连接模板并填写 API Key,运行内联 Verify;选择默认权限模式;最后显示一条可直接尝试的页面总结指令。引导可以跳过。没有可用模型连接时,空会话持续显示引导;已有消息的会话仍可查看历史,但底部只显示“添加模型”操作栏,不渲染消息输入框。

3.4 设置页

当前左侧导航为 Attachments / Sites / Presets / 通用 / 模型 / 浏览器权限 / Skills / Plugins / MCP 服务器 / 数据 / 关于。各页内容如下:

  • 模型:连接卡片列表(启停、编辑、删除)+ 必须指向已有可用模型的默认模型选择器;对话模型选择器中的“默认模型”表示使用这里配置的模型(Thread 绑定的 preset 仍优先)。编辑表单含 template、baseUrl、多 Key、自定义头、quirks、手动模型列表和本次 Verify 结构化结果,Verify 状态不持久化为卡片状态点;
  • 浏览器权限:“默认权限策略”三选一(全程询问 / 操作询问 / 自动操作)+ 规则表(工具/站点/裁决/来源/删除)+ 手动添加 + 用户敏感站点区块;当前规则来源不能跳回原会话;
  • MCP:服务器卡片显示 URL/auth/启停、连接状态、工具数与逐工具开关;OAuth 服务器有授权按钮,支持连接/断开、删除和粘贴 JSON 导入;脱敏日志抽屉仍未实现。
  • 数据:导入对话框先执行后台预检并显示活动任务、暂停任务、待审批和待交互计数;暂停/排队状态需要单独勾选确认,第二次点击才覆盖提交。提交后显示扩展重载提示,重载前 Chat 与 Side Panel 的新命令会显示维护拒绝状态。
  • 关于:显示 manifest 版本,并可手动检查最新的 GitHub Release。发现新版本时只提供当前浏览器对应 ZIP 的下载入口;开发者模式安装仍需覆盖原目录并在扩展管理页重新加载。

4. 交互状态

4.1 流式渲染

idle → streaming(item.delta 追加)
  首个可见 delta 前: item.start 立即显示“思考中”;不要求 Provider 暴露 reasoning 内容
  规则1: 未闭合代码块 —— 检测 ``` 奇偶,未闭合时以纯 pre 渲染,闭合后才交给 Shiki/Mermaid(防闪烁报错,OpenWebUI 教训)
  规则2: Mermaid/KaTeX 仅在块完整后渲染,失败降级为代码块
  规则3: 自动滚动 —— 用户上滚即解除跟随,出现 [↓ 回到底部] 胶囊
→ complete(终稿替换) | error(局部保留 + 重试按钮)

4.2 工具卡片

pending(参数已知, ⏳) → running(onUpdate 进度文本) → ok(✓ + 耗时) | uncertain(? + 待确认) | fail(✗ + 错误摘要)
折叠规则: 连续 ≥3 张卡片折叠为组头 "N 步浏览器操作 ✓m ?u ✗k";运行中的组自动展开尾部一张
展开态: 参数(mono 字体) / content 结果 / details 富渲染(快照高亮、截图縮略图点击放大)

同一用户 turn 内的 reasoning、工具调用、阶段性文本和最终回答统一收进一张 AssistantMessage 卡片,并按真实到达顺序形成活动时间线;思考与工具调用可以多次交替,只有真正连续的工具调用才合并为一组。卡片头部持续显示运行/完成状态,底部统一承载引用、用量、复制、重试与分支操作。

后台在 item 活动期间临时保留重放数据。侧边栏与全页对话在 turn 中途订阅同一 Thread 时,先接收持久快照,再接收当前 item 的 item.start 和已累计 delta,避免已生成的回答从空白处重新输出。turn.complete 后仍以持久快照为准;Service Worker 中止后的恢复不依赖这份内存态。

工具卡片标题使用当前界面的语言描述实际动作,例如“获取标签页列表”“打开 NoVNC 连接页面”或“点击‘登录按钮’”。活动中的工具调用通过 item.start.meta.paramsSummary 只发送一条脱敏短目标,因此无需等待持久快照就能显示具体动作。打开和导航工具可提供人类可读的 page 名称;未提供时回退到移除查询与片段后的域名和路径。tabs_list 等协议名称只用于执行、持久化和排错,不直接显示在折叠标题中;完整参数仍可在展开区域查看。

红色失败状态只用于确认未发生或已确认失败的操作。若写操作已经派发,但中断、超时或页面跳转使最终效果无法确认,卡片使用琥珀色“待确认”状态;成功结果中的 actionEvidence.outcome = uncertain 也采用同一状态。tab_open 在 Chrome 返回新标签页 ID 和已接受的目标地址后立即成功,不等待页面加载完成;加载状态只写入结果说明。其它导航操作核实目标 URL 后也不再等待完整加载。

4.3 审批卡片

出现后临时替换底部输入框并获得焦点。操作栏只保留目标、风险摘要和主要决策;完整参数按需展开。
键盘: Y=允许一次  S=本轮会话  A=本站始终  N=拒绝  (焦点自动落卡片, Esc=拒绝并停止)
多个排队: 队列显示 "1/3",逐张处理
超时(5min): 变灰 + "已超时按拒绝处理"
flags 渲染: `sensitive_payload` / `escalation_l2` 显示告警;`cross_scope` 仅为兼容旧事件保留,引擎当前不再发出

4.4 交互替换区

ask_user 等待回答时,底部选择器临时替换消息输入框;提交、跳过或取消后恢复原输入框。选择器一次展示一个问题,使用单列编号选项、推荐标记、问题进度与前后导航;选择最后一题后提交结构化答案,也可以在底部输入自由回答。

watch_page 等待页面条件时也替换消息输入框。条件满足或超时后,对应工具完成事件会移除等待状态并恢复输入框。其它交互类型继续显示在输入框上方。

4.5 运行/停止

发送键 ➤ ↔ 运行时变 ⏹(Esc 同效)。运行中输入:Enter=插话 steer(不可插话轮自动降级排队并 toast 说明),Shift+Alt+Enter=显式排队;队列胶囊显示待发条数、可点开删改。

5. 触发符与动态变量

<TriggerMenu> 统一调度(模糊搜索、↑↓ 选择):

触发 内容
@ 当前只列出打开的可脚本化标签页;选择后抽取该 tab 正文为 ContextBlock
/ enabled Skill + MCP /server:prompt;带参数的 Skill/Prompt 弹结构化表单
{{ 动态变量自动补全:{{PAGE_URL}} {{PAGE_TITLE}} {{SELECTION}} {{CLIPBOARD}} {{CURRENT_DATE}},提交时求值

输入框的 + 菜单可附着当前页、其它 tab 或用户文件;@ 可搜索 MCP Resource,/ 可调用 MCP Prompt。用户文件只在 Thread 已由首条消息显式创建后开放持久化;初始会话选择上传时必须提示先发送消息,不打开文件选择器,也不创建隐形空 Thread。附件随后持久化为 user-provenance 记录,再随同一 submissionId 发送/排队;上传工具只接受当前 Thread 的用户来源附件。截图由 L2 screenshot 工具生成并作为不可信 page attachment。

6. 快捷键全表

快捷键以 src/ui/shortcuts.ts 中的 SHORTCUT_REGISTRY 为准;扩展页内按 ? 可打开帮助。

作用 作用域
Alt+P 开/关侧边栏 全局(commands)
Cmd/Ctrl+K 命令面板(切会话/改模型/命令) 扩展页
Cmd/Ctrl+N 新会话 扩展页
Cmd/Ctrl+, 设置 扩展页
Cmd/Ctrl+E 侧边栏 ⇄ 全屏页切换 扩展页
Cmd/Ctrl+Shift+S 折叠/展开会话列表 扩展页
? 快捷键帮助 扩展页
Enter / Shift+Enter 发送(运行中=插话)/ 换行 输入框
Shift+Alt+Enter 排队(当前轮结束后执行) 输入框
Esc 停止当前 turn 输入框
召回上一条输入 输入框(空时)
@ / / / {{ 引用 / 命令 / 变量触发菜单 输入框
Cmd/Ctrl+↑↓ 分支切换 消息流
Cmd/Ctrl+Shift+C 复制最后一条回复 消息流
Shift+Esc 焦点回输入框 消息流
Y / S / A / N 审批:一次 / 本轮会话 / 本站始终 / 拒绝 审批卡片(保留键,不可改绑)
Esc 拒绝并停止 审批卡片(保留键)

7. 空态 / 错误态 / 加载态

  • 空会话:居中 logo + 最多 4 条建议;侧边栏用 URL 规则提供视频/PDF/GitHub/普通页面建议,当前没有合并 Skill auto_suggest;点击只预填输入框,不自动发送;
  • Provider 未配置:空会话显示首次引导;已有会话用“添加模型”操作栏替换输入框;
  • 错误态规范:ProviderError 按 Provider §7 归因显示易懂文案(“API Key 无效,请检查 [设置]”);可重试错误显示“重试”按钮,网络断开时在顶部显示细横幅;
  • 加载态:会话切换用骨架屏(3 条消息形状);架构 §3.4 握手期间,输入框显示“重新连接引擎…”。

8. i18n 与可达性

  • 对话与设置组件使用 src/ui/i18n.ts 中的 zh-CN/en key;设置搜索索引仍会保留中英文关键词。默认语言来自 global_settings.language,未配置时为 zh-CN,不自动读取浏览器语言;
  • 审批卡片、工具卡片有完整 aria 标注;全键盘可达是验收项(Tab 顺序:消息流 → 审批 → 输入框);
  • 颜色对比度 ≥ WCAG AA;状态不只靠颜色(✓/✗/⏳ 图标并存)。

9. 当前约束

  • Mermaid 暗色主题:渲染时按当前主题传 theme: 'dark' | 'default'mermaid.initialize(Markdown.tsx),不注入自定义变量。
  • 虚拟滚动选型:react-virtuoso,流式追加用 followOutput 锚定,替代手写 auto-scroll。
  • ToolCallCard 窄容器不做专门降级布局:卡片头部文本已 truncate,耗时/状态是行尾短标签,侧边栏最小宽度下无溢出,单一布局即可。