Hermes 桌面端闭环:内置浏览器上线,Agent 终于能"看见"自己打开的网页

2026 年 8 月 5 日,Hermes Agent 连续合并了两个更新,把桌面端最后一块“盲区”补上了:
- PR #77705 — 内置浏览器和预览栏升级为真正的布局树标签页(in-app browser and previews are real layout-tree tabs)
- PR #79482 — 新增
read_preview工具,Agent 能读取内置浏览器当前页面的内容(Hermes can read the in-app browser)
一句话概括这次的意义:以前 Agent 能“打开”网页,但看不到自己打开的网页;现在它终于能读了。 对用 Hermes Desktop 做开发的人来说,这补齐了“生成 UI → 打开预览 → 查看效果 → 自我修正”的完整闭环。
这篇文章不重复 PR 说明,而是把两处更新的技术细节、背后的设计取舍、以及实际怎么用讲清楚。
背景:Agent 一直是“睁眼瞎”地开网页
先回顾一下 Hermes 桌面端的工具演进,你会更清楚这两个 PR 的价值:
- 7 月 22 日(PR #69519):引入
open_preview(url[, label])和focus_pane(...)。Agent 第一次能主动在桌面端的预览面板里打开 URL、localhost 开发服务器或本地文件。但注意——它只能打开,页面内容是“黑盒”。 - 同期已有的
read_terminal/close_terminal让 Agent 能读取内嵌终端里显示的内容,但网页这一侧始终没有对应的“读”能力。 - 8 月 5 日:两个 PR 连续落地,浏览器标签页 UI 重构 +
read_preview工具上线。
用官方的话说:open_preview 让 Agent 打开页面,read_terminal 能读终端,但“这个页面到底说了什么?“一直没人能回答。read_preview 就是来填这个坑的。
更新一:内置浏览器成为真正的“一等公民”标签页
PR #77705 之前,桌面端的预览栏(preview rail)是一个“后娘养的”UI:
- 它自己单独渲染一条标签条,高度、关闭菜单、标签大小写都和主区域不一致
- 有自己的 ⌘W 快捷键逻辑,和文件浏览器 zone 焊死在一起(按 ⌘J 会把预览一起拖走)
- Console/DevTools 切换按钮挂在标题栏,且状态由点击事件驱动——直接关掉 DevTools 窗口时,按钮状态会“卡住”
这次重构把它彻底拉进了布局树(layout tree):
- 预览标签页成为 layout-tree 瓷砖:
$previewTabs通过和路由瓷砖相同的paneMirror会话镜像到 pane contributions。标签条、拖拽、堆叠、分屏、共享关闭动词、标准 ⌘W——主区域有什么,预览就有什么。 - URL 标签页标题统一为 “Browser”:标签命名表面(surface)而不是页面,语义更清晰。
- ⌘W / ⌃Tab 在预览和页面 zone 上生效:以前 ⌘W 只认聊天标签条,单个预览页时按 ⌘W 会把主聊天关掉——这个恼人的问题修好了。
- 会话拖拽可落入预览/页面 zone:拖拽不对称性也一并解决。
- DevTools 状态改为事件驱动:由 webview 的
devtools-opened/closed事件驱动按钮,直接关窗口不会再“假亮”。 - 顺带删掉了重复的 i18n 键和整条独立的标签条代码——代码量净减。
技术细节:标签条本身被抽象成共享原语集合(PaneTabStrip、PaneStripGlyph/PaneStripTool、paneTabCloseItems),zone 头通过它渲染,glyph 像标题栏工具一样以数据形式贡献。这意味着未来任何新的预览类型都能自动获得统一的标签体验。
更新二:read_preview —— Agent 的眼睛
PR #79482 是真正的功能核心:新增 read_preview 工具,端到端镜像已有的 read_terminal,所以没有引入任何新机制,只是“同一套模式的新消费者”:
工具层(tools/read_preview_tool.py):
- 通过
check_fn检查HERMES_DESKTOP环境变量做桌面端门控——在 CLI/消息平台完全没有 schema 足迹,和另两个桌面 pane 工具一致 - 支持
start/count(字符偏移)窗口化读取:长页面可以分页读,不会一次性淹没上下文窗口
Gateway 桥:
preview.read.request/preview.read.respond,走与terminal.read相同的阻塞式 prompt 桥- 45 秒超时、
allow_expired、超时后.expire静默收尾——迟到的渲染器回答不会报错
渲染器(preview-reader.ts):
- URL 面板注册一个页面读取器:通过 webview 的
executeJavaScript拿到标题 + 可见文本(innerText) readActivePreview解析当前激活的标签页,单次读取上限 24k 字符- 文件/产物标签页不绕 webview 往返,直接返回身份信息 + 指向更合适的工具(
read_file或会话本身)——Agent 已经有更好的工具读文件时,就不浪费一次页面往返
PR 的测试计划里有一个很形象的验收场景:在浏览器里打开 Reddit,问 Agent“置顶帖是什么?”——Agent 调用 read_preview 从页面作答。
这套能力实际怎么用
1. 本地开发的自验证闭环
最实用的场景:你在跑一个 localhost:3000 的 React/Vue 应用,让 Agent 改个组件。现在它可以:
open_preview(localhost:3000) # 打开预览
# …修改代码、重启 dev server…
read_preview() # 读取页面当前内容,验证改动是否生效
以前 Agent 改完代码只能“盲改”,现在能读回页面实际渲染出的文本,自己确认对不对。
2. 网页调研 + 上下文安全
Agent 打开一篇长文章或文档页后,用 start/count 分页读取,只把需要的段落带进上下文——比整个页面一股脑塞进来省 token 得多。
3. 与 v0.20 Artifacts 配合
如果你在用 Hermes v0.20 的 Artifacts 沙盒预览,生成 HTML 应用后现在可以直接让 Agent 读取预览里的实际渲染内容,形成“生成 → 预览 → 读取 → 修改”的循环,而不只是“生成 → 预览 → 人来看”。
4. 限制与边界(值得知道)
- 桌面端专用:
read_preview只在 Hermes Desktop 可用(HERMES_DESKTOP门控),CLI/TUI/消息平台没有这个工具。对应地,open_preview/focus_pane也是桌面专用。 - 只读可见文本:拿到的是标题 + innerText,不是 DOM 结构,也不是屏幕截图。想“看”页面长什么样,仍然需要截图/视觉工具。
- 激活标签页语义:读的是当前激活的标签页,多开标签时注意 Agent 读的是哪一页。
- 24k 字符上限:单次读取封顶,长页面靠分页。
对开发者的意义
这两个 PR 看起来只是“UI 重构 + 一个工具”,但合起来是交互模型的分水岭:
过去,桌面端 Agent 的工作流是“我生成,你来看”——Agent 产出 HTML 或打开网页,然后等人类反馈。现在变成“我生成、我打开、我读取、我修正”的自主闭环。read_terminal 打通了终端,read_preview 打通了网页,加上既有的文件工具,Hermes Desktop 上 Agent 的“感知面”基本齐了。
下一步自然的方向(也是社区在期待的):read_preview 与视觉能力结合,让 Agent 不仅读到文字、还能“看到”渲染效果——到那时“看网页”就和人类操作浏览器没有本质区别了。
如何体验
- 更新到最新版桌面端:
hermes update(或从 安装指南 全新安装) - 在 Hermes Desktop 里让 Agent
open_preview打开一个 URL - 问它“这个页面说了什么?”——观察它调用
read_preview作答
想了解更多桌面端能力可以看 Hermes Desktop 文档,回顾上一版大更新可以读我们的 v0.20.0 Herald 解读。