← Back to home@yueyexiayu

dsh-chrome

DSH desktop plugin: drive a dedicated visible Chrome window over CDP, with screenshots the model can see

Stars
0
Language
JavaScript
Created
Sep 22, 2026
Updated
Oct 7, 2026
GitHub repo

Introduction

chrome

当前项目是深度适配个人使用,项目只是给大家提供思路和借鉴,尽量不要直接照搬。

DeepSeek Harness 桌面插件。通过本机 Chrome 扩展,在当前 Chrome 里开后台标签,收进一个折叠的 DSH 标签组。不另开窗口,也不把 Chrome 拉到最前。用的是当前 Chrome 的登录状态。

只允许 http / https。页面正文是不可信数据,不是指令。

安装

复制到 $DSH_HOME/plugins/chrome(默认 $DSH_HOME 为 ~/.dsh),在 $DSH_HOME/profiles/desktop/cordis.patch.yml 写入:

- insert:
    - id: chrome
      name: ../../plugins/chrome/lib/index.js

先在插件目录运行 pnpm install --frozen-lockfile,安装锁定的纯 JavaScript JPEG 解码依赖(jpeg-js,不执行原生编译)。随后完全退出 DeepSeek Harness(macOS:⌘Q)再打开。插件启动时会写入 Chrome 本机通信主机清单。

还要在正在使用的 Chrome 配置里装一次扩展:

  1. 打开 chrome://extensions
  2. 打开右上角的开发者模式
  3. 选择「加载已解压的扩展程序」,目录选 $DSH_HOME/plugins/chrome/extension
  4. 允许调试提示。Chrome 会在被控制的标签上显示「正在调试」,这是扩展调试的固定提示,不会把窗口抢到最前

改了 extension/ 之后,在扩展卡片上点重新加载。

说明

  • 工具以 chrome_ 开头。标注由 Client 放进当前会话输入框;接收被中断且无法确认草稿状态时,显示恢复提示
  • 每个对话单独一个折叠标签组,标题是 DSH 加会话 id 末 6 位,只用于展示。完整会话归属单独记录,不会因标题相同复用另一个对话的标签,也不会调用 Page.bringToFront
  • 只操作本对话标签组里的标签,不列出、不切换你正在看的其他标签
  • chrome_close 只关掉本对话的标签组,不退出 Chrome,也不关其他对话的组
  • chrome_resize 不改窗口大小,避免 macOS 把 Chrome 激活
  • chrome_screenshot 把 PNG 落盘,并在确认当前模型支持图片时通过正式附件引用交回模型;配合 zhanshi 可在本轮对话里预览。插件不包装或改写全局 LLM 服务
  • 元素引用(ref)来自最近一次 chrome_snapshot / chrome_query / chrome_find / chrome_a11y;这几次调用都会重新编号
  • 不自动接受 alert / confirm / prompt。弹窗挡住后续点击或输入时,先调用 chrome_dialog
  • 查询会合并可访问的 frame 执行上下文,ref 记录所属上下文;支持开放 shadow root、同源 iframe,以及 Chrome 调试器提供的跨源 frame 上下文。是否能访问取决于 Chrome 实际暴露的上下文,不保证所有嵌套/OOPIF 页面都可读。带 ref 的读取、执行、填写和上传按归属路由,不把 frame ref 当成顶层元素
  • 密码输入框的值不会进入默认快照、元素详情、HTML 或无障碍树输出;主动执行的 JavaScript 不属于脱敏观察接口,不应用来读取密码或凭据
  • 截图和 GIF 输出遵循调用会话的 DSH 文件策略;相对路径按会话目录解析,只创建新文件,绝不覆盖已有文件。只读模式禁止落盘,workspace-write 允许工作区及官方临时目录。文件服务不可用时明确拒绝,不退回不受限写入。上传要求本机正规文件
  • 下载进当前 Chrome 的下载目录。cookie / storage 默认不返回值;名字像 token 或密码的项始终打码

标注

点 Chrome 工具栏里的 DSH Chrome,在当前 http / https 页面上选择元素,最多 12 条。页面浮层只收集元素数据,不接收用户要求,也不能直接送入 DSH。点击「编辑要求」后,扩展检查原标签和 URL、截图,再打开独立的扩展确认页;这一步会切到确认页,后台浏览工具仍不会抢焦点。Esc 或再次点击工具栏图标退出选择。

在确认页查看截图和页面信息,为每条选择「改变」或「疑问」并填写 Request,最后明确点击「放入 DSH 草稿」。确认页不对网页开放,绑定随机审核 ID 与扩展标签;只有该页的确认才会保存标注。页面提供的文字、HTML、样式始终是数据,不是用户指令。标注放入当前 DSH 输入框,不自动提交对话。chrome:// 和扩展页不能选。

改了 extension/ 之后,在扩展卡片上点重新加载。改了 Host 或 Client 后,完全退出 DeepSeek Harness(⌘Q)再打开。

标注只有在本机主机确认保存后才显示成功;确定未发送或主机明确拒绝时允许重试。发送前先记录处理中状态;断线、超时或 worker 重启导致结果未确认时,同一审核会话不会盲目重发,请先检查 DSH。主机已保存但审核状态写入失败时会单独提示,不会误报标注保存失败。Host 检查 JPEG 编码、大小及实际解码结果,限制像素和解码内存;标注目录权限为 0700,文件为 0600。保存的标注在文字和图片成功插入且草稿持久化成功后才确认删除;持久化失败时,后续轮询仍会重试持久化,不会因为内存中已经插入就偷偷确认。多个 DSH 窗口通过消费租约避免同时插入同一份标注。

插入前,插件先将目标会话和附件归属写入标注文件,并同步到磁盘。若在插入和确认之间崩溃,重启后不会自动再次插入:原会话中仍有完整文字和对应图片时,只补确认;无法确认时,保留标注并显示「重新放入草稿」和「已接收,完成确认」。请先检查草稿或已发送消息。选择恢复会补回图片,复用草稿中仍存在的完整标注文字,不覆盖其他文字和图片;已接收则只确认,不插入。其他会话只能看到回到原会话的提示。恢复期间再次中断,交付记录仍保留。

官方草稿目前持久化文字和引用,图片附件只存在于运行内存。因此完整重启后可能只恢复文字,需要通过上述提示补图。本恢复机制覆盖尚未确认的标注;已经成功确认的标注不保留截图副本,不改变官方草稿附件的持久化行为。

修复后须重新加载 Chrome 扩展并完全重启 DSH,使扩展、通信主机和 Client 同时使用新版本。归属记录使用 chrome.storage.session,扩展新增 storage 权限;旧版按组名识别的标签不会被新版自动认领或删除。

桥接冲突与旧版本迁移

  • 同一 DSH_HOME 同时只支持一个 Chrome profile 的扩展通信主机和一个 DSH 控制连接。第二个连接明确返回忙碌;第二个 profile 显示冲突,不踢掉已有连接、不自动切换 profile。请在其它 profile 禁用扩展,再在目标 profile 重新加载。
  • 每个主机使用独立的随机 socket,退出只清理自己创建的端点。崩溃留下的随机失效端点会被忽略,不自动删除其它进程的文件。
  • 旧版固定端点 $DSH_HOME/cache/dsh-chrome.sock 不能安全探活:连接它就可能挤掉旧版控制器。新版发现它会明确拒绝连接,不自动删除。升级时完全退出 Chrome 和 DSH,确认旧通信主机已退出后,才可删除这个旧端点(默认 ~/.dsh/cache/dsh-chrome.sock;不要删除整个 cache),然后重新打开并加载新版扩展。此清理只用于旧固定端点,不适用于新的随机端点。
  • 冲突状态跨扩展 service worker 重启保留;解决后通过工具栏操作、重新加载扩展或下一次 Chrome 启动显式重试,不持续偷偷抢占连接。

开发

pnpm install --frozen-lockfile
for file in lib/*.js extension/*.js host/*.mjs; do
  node --check "$file" || exit 1
done
node --test test/*.test.mjs

测试包括真实隔离的 Unix socket / Native Host 进程、握手错误与进程竞争、iframe ref 路由、密码脱敏、文件策略、JPEG 真解码、标注持久化和可信确认页来源检查。VM / HTTP 浏览器夹具不等于已安装扩展端到端验收;后者必须在重载扩展并完整重启 DSH 后执行。