【免费下载链接】terminal
Terminal UI to get stuff done in the browser
Browser Use Terminal(终端里完成浏览器任务的 TUI 工具)的渲染层采用了一套清晰的分工:由 transcript.rs 维护的Ratatui Transcript 模型负责把会话事件压缩成“已提交 + 进行中”两部分,已定稿的文字交给原生终端 Scrollback保存,正在变化的内容交给 Ratatui 活动视口实时绘制。这套“完成内容归终端、运行内容归框架”的架构,直接解决了重复输出、闪烁、布局跳动等终端 UI 的经典顽疾。
老架构为什么会“翻车”:四个任务挤在一条控制链上
在迁移到 Transcript 模型之前,旧渲染器把四件互不相干的事混在同一个绘制路径里:
- 把事件投影成用户可见的对话记录;
- 用 Ratatui 绘制已提交的记录;
- 往原生终端 scrollback 里插入内容;
- 绘制输入框、浮层与活动状态。
耦合带来的后果很直观:重复的 transcript 块、空白间隙、画面闪烁、子代理(subagent)事件伪装成父级工具调用、无关 UI 状态一变就整屏跳版。官方架构文档把这些归因记录在 docs/terminal-renderer-architecture.md 的 “Why This Fixes The Old Bugs” 一节。
三方分工:谁负责什么
现在的渲染层只有三个文件,职责边界非常干净:
| 模块 | 职责 |
|---|---|
| transcript.rs | 唯一的事件→Transcript 归约器,产出已提交节点与活动节点 |
main.rs 中的TerminalDriver | 终端生命周期:创建内联视口、决定何时重建、向原生 scrollback 追加已提交行 |
| render.rs | 应用界面:setup/ready/result/running 等 surface、composer、页脚与浮层 |
transcript.rs:把事件流压缩成 TranscriptNode
transcript.rs只做一件事:归约(reduce)。
- 从应用内存缓存读取当前会话的事件流(不直接打 SQLite);
- 把事件折叠成
TranscriptNode(Prompt、Assistant、Timeline、ToolImage、Error 等类型); - 区分committed(已定稿)节点和active(正在进行)节点;
- 过滤掉模型 token 增量、子会话内部事件等“噪声”,防止子代理细节泄漏到父级对话里。
它还内置了缓存(TranscriptModelCache、FilteredEventCache):流式会话每帧事件数都在变,旧实现每帧深拷贝全量事件是输入延迟的主要来源,现在只在“纯追加”时增量扩展缓存,会话越长收益越大。
TerminalDriver:原生 Scrollback 的唯一写入口
TerminalDriver(main.rs)管理终端的生命周期:
- 用
Viewport::Inline创建内联 Ratatui 终端; - 只有真实的终端 resize 或显式会话回放时才重建视口;
- 通过 maybe_emit_native_transcript 把新定稿的 transcript 行追加进原生 scrollback——普通按键、斜杠面板、模型流式输出、composer 编辑都不会清空或重放终端。
render.rs:只画“还在变的”
在正常任务模式下,render.rs不再重建已提交的记录(那部分归原生 scrollback 管),它只向 transcript 模型要“仍在变化的活动视口尾部”,再负责 composer、页脚和浮层。
数据流:从事件存储到屏幕
整条链路可以概括为:
SQLite / 事件存储 → 应用内存状态缓存 → transcript_model(app, state) (唯一归约器) ├→ committed 节点 → maybe_emit_native_transcript() → 原生 scrollback └→ active 节点 → render.rs 活动视口 → composer / 状态栏由此形成一条硬边界:
completed text → 原生终端 scrollback(唯一 owner) running text → Ratatui 活动视口(唯一 owner) composer/status → 稳定的 Ratatui dock overlays → Ratatui 独立 surface一个关键细节:活动节点定稿后只写一次 scrollback,然后立即从活动视口移除,所以同一段文字不会出现两份。
正常任务模式:追加式(append-oriented)交互
日常使用时的屏幕布局是三层叠加,全部按“只增不改”运作:
┌────────────────────────────────┐ │ 终端 scrollback(原生) │ │ > 历史提问 / 最终答案 │ │ > 当前提问 / 工具摘要 │ ├────────────────────────────────┤ │ 活动视口(Ratatui) │ │ 模型正在输出的文字 / 子代理活动 │ ├────────────────────────────────┤ │ composer / 页脚 │ └────────────────────────────────┘架构文档列出了 8 条不变量(docs/terminal-renderer-architecture.md),最值得记住的几条:
transcript.rs是唯一的事件→transcript 归约器;- 已提交记录只有原生 scrollback 一个 owner,活动内容只有活动视口一个 owner;
- 定稿节点恰好写入一次scrollback,随后离开活动视口;
- SQLite 只负责持久化与冷启动水合,实时渲染永远走内存缓存;
- 输入框、斜杠命令、历史/模型面板不许清掉原生 scrollback。
如何验证一次渲染改动
渲染器的很多 bug 只在真实终端里暴露(闪烁、残留重绘、括号粘贴泄漏、resize 重放错误),所以仓库自带了验收闭环 scripts/verify-terminal-ui.sh,它组合了 Rust/Python 测试、确定性 Ratatui dump 和一次真实 tmux 冒烟测试:
scripts/verify-terminal-ui.sh测试策略与用例设计可以参考 docs/terminal-ui-testing.md。
延伸阅读:源码与文档索引
- 架构总览:docs/terminal-renderer-architecture.md
- Transcript 归约器:crates/browser-use-tui/src/transcript.rs
- 终端驱动与 scrollback 写入:crates/browser-use-tui/src/main.rs
- 应用 surface 绘制:crates/browser-use-tui/src/render.rs
- UI 验收脚本:scripts/verify-terminal-ui.sh
【免费下载链接】terminal
Terminal UI to get stuff done in the browser
相关推荐
F3D:快速轻量级 3D 模型查看器
F3D:快速轻量级 3D 模型查看器 如果你收到客户发来的 .glb、机械同事转来的 .step,又不想打开重型 3D 软件,可以直接试 F3D:它是一款开源的
桌面应用图形学3D渲染数据可视化ratatui 脏追踪渲染系统设计:从 DirtyRect 架构到 Cangjie 终端增量渲染实现
ratatui 脏追踪渲染系统设计:从 DirtyRect 架构到 Cangjie 终端增量渲染实现 本文基于 ratatui 仓库中的脏追踪渲染系统设计文档,
CLIUI组件跨平台集成终端是如何工作的?obsidian-terminal的xterm.js渲染与伪终端(PTY)架构完整解析
集成终端是如何工作的?obsidian terminal的xterm.js渲染与伪终端(PTY)架构完整解析 obsidian terminal 是一款 Obs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考