Skip to content

[功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线(已兼容0.2.1-rc.3) - #121

Open
graydovee wants to merge 10 commits into
omdsh-dev:mainfrom
graydovee:omdsh-dev/dsh-browser
Open

graydovee wants to merge 10 commits into
omdsh-dev:mainfrom
graydovee:omdsh-dev/dsh-browser

Conversation

@graydovee

@graydovee graydovee commented Oct 17, 2026 •

Copy link
Copy Markdown

本 PR 汇总 fork 仓库新增的功能。changelog 见 fork 仓库的 CHANGELOG.zh-CN.md;每个功能的详细说明(动机、工具与方法、审批与配置、测试与边界)见下方对应评论。

  • 2026-10-25 [Fix] 适配 dsh 0.2.1-rc.3:插件在新版运行时上无需改动即可加载与使用,dsh 0.2.1-rc.2 宿主仍受支持。
  • 2026-10-21 [Feature] 浏览器操作新增通用输入能力:指针手势与坐标、组合键与按住、光标插入与逐键输入、富文本剪贴板粘贴、文件上传与单 iframe 精读;输入默认后台执行,不激活标签页、不移动系统鼠标。
  • 2026-10-19 [Feature] 页面交接提示新增「跳转回到助手页面」,可把浏览器切回助手正在操作的页面;原有两个选项按主体改名为「助手留在原页面」「助手跟随当前页面」,更容易区分。
  • 2026-10-19 [Fix] 修掉一处会让自动检查间歇失败的用例,功能行为无变化。
  • 2026-10-18 [Feature] 即使 DSH Desktop 每次启动都把本地端口换成新的随机端口,侧栏现在也能重新找到本机 dsh;找不到时显示「未找到服务」而不再反复重试,并新增「自动检测」按钮列出本机所有实例供选择。
  • 2026-10-17 [Fix] 适配 dsh 0.2.1:插件在新版运行时下恢复可加载、可正常使用,插件页显示自己的标题、简介与图标。
  • 2026-10-16 [Feature] 侧栏输入区现在可以直接选择会话的权限模式(仅可查看 / 工作区内修改 / 完全权限,选择完全权限前会二次确认)、选择模型及其推理强度,并支持输入「/」执行命令或调用 skill。原先只能查看、回复期间还会失效的模型控件现在随时可切换;写错的斜杠命令会被拦下并保留草稿,不再被当成普通消息发给模型。
  • 2026-10-10 [Feature] 新增 browser_screenshot 视口截图工具(每次调用单独审批,需要 <all_urls> 主机权限),并支持在侧栏粘贴或拖拽图片随消息一起发送。
  • 2026-10-09 [Feature] 新增可选的开发者工具组:通过 Chrome 调试协议查看和修改页面元素与 CSS、在页面上下文执行 JavaScript、抓取网络请求;默认关闭、每次调用单独审批,仅 Chrome 提供。

开发者工具组默认关闭,只有 host 显式打开才注册;所有高权限动作保持逐次审批。

后续每次功能更新都推到同一条分支,并在本 PR 内回复对应功能的详细说明与 changelog 条目。

Adds three user-facing capabilities on top of the existing text-only browser
bridge, all opt-in and all gated by the extension's per-call approval:

- Developer tools (Chrome DevTools Protocol): an opt-in group that exposes
  Elements/Console/Network inspection (computed styles, box model, matched rules,
  live CSS/attribute edits, page-context JS evaluation, recorded console output,
  captured requests and bodies with credential headers redacted by default) plus
  a character budget (devToolsMaxChars) for the results.
- Viewport screenshots: browser_screenshot captures the controlled tab and returns
  an image, with host permissions widened to <all_urls> and an approval required on
  every call.
- Panel composer controls: permission modes, model strength, and the / command menu
  in the side panel, backed by new host methods (permission.catalog,
  session.permissions, session.setPermission, commands.list, commands.execute,
  skills.list) that are never offered to the model as tools; image paste and
  drag-drop attachments in the composer.

Extension and bridge tests cover each area (devtools controller/elements/network/
serialization/authorization, screenshot, panel api/commands/composer/permissions/
image transfer, remote-host-api, session deferral), and the smoke script exercises
the new host methods.
graydovee added a commit to graydovee/dsh-browser that referenced this pull request Oct 17, 2026
上游自 2026-10-01 起无提交、最后 release 为 v0.1.3,本 fork 暂时承担维护并
把更新源指向自己;对上游的改动统一走 omdsh-dev/dsh-browser 这条 PR 承载分支,
当前对应 issue omdsh-dev#120 与 PR omdsh-dev#121。
@graydovee graydovee changed the title feat: 浏览器桥接新增开发者工具、视口截图与输入区控件 [功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线 Oct 17, 2026
@graydovee

graydovee commented Oct 17, 2026 •

Copy link
Copy Markdown
Author

概述 / Summary

新增可选的开发者工具组:查看与修改元素样式、在页面中执行 JS、抓取网络请求。默认关闭,需要额外授权。

  • 实现:81eb4cd(20 文件);测试与文档:9d4d2e4(21 文件)——二者在 fork 历史中保留,本 PR 分支里已合成单一提交

动机 / Motivation

参考 #114 现有工具读不到计算样式与布局信息,样式类问题只能得到"页面上有这些元素",无法回答"为什么是这个尺寸""被哪条规则覆盖",这类问题以前直接走进死胡同。

改动内容 / Changes

Host 侧(bridge-browser):

  • hello 增加 devTools 能力协商:只有扩展声明该能力后才注册这一组工具,重连时能力消失则收回
  • 新增 9 个工具:browser_devtools_elements(查看元素)、browser_devtools_set_element_style / browser_devtools_set_element_attribute(改样式与属性)、browser_console_eval / browser_console_logs(执行 JS、读控制台)、browser_devtools_network / browser_devtools_list_requests / browser_devtools_get_request / browser_devtools_request_body(网络抓取);输出保持 { text }

扩展侧(dsh-browser):

  • chrome.debugger 会话管理:attach、开启 domain、超时,以及与浏览器自带 DevTools 冲突时的明确报错
  • 元素:按选择器或快照索引定位;返回计算样式、盒模型、命中规则;可改内联样式或命中规则中的样式
  • 控制台:Runtime.evaluate 执行 JS 并返回结果;记录控制台输出与异常
  • 网络:由 CDP 网络事件记录请求,含头、状态、时序与响应体
  • 授权:专用审批弹窗;新增"允许开发者工具"设置;关闭该设置立即 detach 调试器
  • Chrome manifest 增加 debugger 权限;Firefox manifest 不增加

两条实现说明:

  1. 网络抓取不能只听 Network.requestWillBeSent:部分页面 Chrome 只发 requestWillBeSentExtraInfo 而主事件永不到达,抓取结果会为空。现在两个事件都会建条目,缺少主事件的条目会标注"请求方法可能不完整"。
  2. 元素报告里,当某条规则同时带有简写与其展开属性时只保留简写;修改某个展开属性(如 margin-top)会替换整个 margin 族,否则简写会覆盖这次修改。

测试 / Testing

  • pnpm run check:runtime
  • pnpm run typecheck
  • pnpm run test(本 PR 分支:62 个文件 / 545 用例)
  • pnpm run build
  • pnpm run test:smoke

新增用例覆盖:debugger 会话生命周期、网络抓取的事件处理(含 ExtraInfo 情形)、元素定位与样式修改、授权策略("完全控制浏览器"与来源白名单都不覆盖该组)、manifest 的平台差异。

Chrome 实测:查看元素计算样式与命中规则;加一条 outline 后回读确认样式属性已写入;控制台执行 JS 并读回 JSON 与一个带栈的未捕获异常;抓取一次 fetch 的状态、头、时序与格式化后的 JSON 响应体。

影响范围 / Impact

  • 仅 Chrome 提供;Firefox 上不注册
  • 默认关闭:没有设置或逐次审批时行为零变化
  • 调试器 attach 期间,浏览器自带的 DevTools 无法在同一标签页打开
  • 无新增依赖;wire 协议不变

@graydovee

Copy link
Copy Markdown
Author

概述 / Summary

新增 browser_screenshot:截取受控标签页的可见视口,并把图片作为 image content block 返回,能看图的模型直接读它;纯文本模型得到运行时的占位投影,不受影响。截图会拍下用户屏幕上真实存在的内容——包括密码与私人消息——所以每次调用都要在侧栏弹出审批。侧栏同时增加粘贴与拖拽的图片入口。

改动内容 / Changes

截图工具:

  • 对受控标签页调用 chrome.tabs.captureVisibleTab,支持 png / jpeg 与质量参数
  • 像素进入附件存储、以 image content block 回来;持久化的工具结果只保留元数据——base64 从不进入会话文件。png 超过字节上限时以 jpeg 重试一次
  • 只截所属窗口里处于活动状态的受控标签页;受控标签页未激活、或页面不是 http/https,都会以带原因的报错拒绝

审批:

  • 每次截图都在侧栏弹窗:"截取当前页面截图(可能包含敏感内容)";拒绝即中止截图
  • 该弹窗与"页面内容共享"设置互相独立,后者仍然只管文本读取类工具;唯一的跳过路径是设置里的"完全控制浏览器"
  • 主机权限是 <all_urls>:captureVisibleTab 只接受 <all_urls> 或用户手势激活的 activeTab,不接受域名级 http/https 权限

侧栏:

  • 输入区支持 ⌘V 粘贴图片、把图片拖到输入框,校验规则与文件上传一致(数量、字节、尺寸、媒体类型)

测试 / Testing

  • pnpm run check:runtime / typecheck / build / test:smoke
  • pnpm run test(本 PR 分支:62 个文件 / 545 用例)
  • Chrome 实测:截图成功且模型能准确描述图片;审批弹窗出现,拒绝则无法截图;⌘V 粘贴能正确发送图片

影响范围 / Impact

  • 只有视口,不包含整页拼接
  • 主机权限为 <all_urls>(captureVisibleTab 的准入要求;域名级权限不被接受)
  • wire 协议不变;无新增依赖

@graydovee

Copy link
Copy Markdown
Author

概述 / Summary

侧栏输入区现在可以直接选择会话的权限模式、选择模型及其推理强度,并支持输入 / 执行命令或调用 skill。以前面板只能发消息:权限、模型都选不了,/ 命令也发不出去,尽管 Host 侧这些能力本来就有;而且模型控件在回复期间会失效。

动机 / Motivation

面板是用户唯一持续可见的操作面,但它的表达力长期只有"发一条消息"。要换模型、收紧权限、跑一条 host 命令,用户只能离开面板。把这些控件补齐,面板才真正覆盖日常操作。

改动内容 / Changes

输入区控件:

  • 权限模式:仅可查看 / 工作区内修改 / 完全权限,选择完全权限前二次确认
  • 模型与推理强度:面板内切换;回复流式期间仍然可用(此前该控件在流式期间失效)
  • / 命令与 skill:输入 / 打开可搜索菜单,执行 host 命令或调用 skill;写错的斜杠命令会被拦下并保留草稿,不会被当成普通消息发给模型

Host 侧新增六个面板专用方法,只服务于侧栏 UI,不作为工具暴露给模型:

面板方法 Host 侧工作
permission.catalog permissionPresets/catalog
session.permissions 目录 + 会话的 permissions 投影
session.setPermission 校验预置后执行 /permission <preset>
commands.list / commands.execute 按会话所属 agent 执行命令;未识别的行返回 bad-request
skills.list 按会话组合取可用 skill

测试 / Testing

  • pnpm run typecheck / build / test:smoke
  • pnpm run test(本 PR 分支:62 个文件 / 545 用例)
  • 面板实测:切换权限模式(含完全权限的二次确认);流式回复期间切换模型;/ 菜单搜索与执行;输入错误命令时草稿保留

新增用例:panel-permissions.spec.ts、panel-commands.spec.ts、panel-composer-controls.spec.ts、remote-host-api.spec.ts、session-deferral.spec.ts。

影响范围 / Impact

  • 会话尚未落地(deferred)时,这些方法返回 provisional,面板据此显示"发首条消息后可用"
  • 只新增面板侧的 host 方法,未改变既有工具面;wire 协议向后兼容
  • 无新增依赖

@graydovee

Copy link
Copy Markdown
Author

注意到 #116 也实现了截图能力。对比了两边的实现,主要差异如下:

图片交付:#116 将像素写入本地文件、向模型返回路径,页面通道保持纯文本优先;本 PR 将图片存入附件存储后以内容块直接进入模型上下文。由此本 PR 每次截图少一次工具调用——#116 的模型拿到路径后,需再调用读文件工具才能看到图片;连续多张截图时该差异会成倍放大。纯文本模型由运行时投影为占位符,不受影响。

权限路线:#116 采用 optional debugger 与 CDP 回退,权限授予经由设置页的用户手势完成;本 PR 采用 <all_urls> 主机权限。一个实测发现:captureVisibleTab 不接受域名级 http/https 权限,会报 Either the '<all_urls>' or 'activeTab' permission is required;清单中的 activeTab 亦不构成豁免(仅在用户手势触发时临时生效)。#116 的 CDP 回退不依赖该权限,但每次截图需附加调试器,伴随"正在被调试"横幅、与浏览器自带 DevTools 互斥、Firefox 上不可用。

审批:本 PR 对每次调用弹出侧边栏审批,仅"完全控制浏览器"可跳过。

受保护页面:chrome:// 等页面上所有工具均被扩展拒绝执行;#116 单独放行截图(captureVisibleTab 由浏览器在渲染层直接拍摄,无需向页面注入脚本);本 PR 在这些页面拒绝截图并说明原因。

附带改动:本 PR 另包含侧边栏粘贴、拖拽添加图片。

dsh 0.2.1 把 Gateway/Connection 的调用方身份改成必填:wireStream.open、invoke、
createSharedFetchHandler().fetch 都必须显式传入 PeerScope,缺失时会在 Gateway 内部
以 stream-failed 崩掉(Cannot read properties of undefined (reading 'signal'))。
bridge 现在通过 connection.createPeer 自建一个 owner principal、interactions=answer
的 in-process Peer,统一用于每次调用、 流和 /result 回传。

同时跟随 0.2.1 的插件契约变化:
- 移除运行时 invariant 插件与 ./invariant 导出(0.2.1 已删除该扩展点)
- 清单补 dsh.manifestVersion=1、engines.dsh 与 node 引擎范围
- 新增 locale/en.json、locale/zh.json 与 icon.svg,供插件页展示
- session-persistence-jsonl 改为 function-style 插件,测试改用命名空间导入
- smoke 断言改为:keepInbox 下未认领的页面快照跨重启保留,不再被取消
@graydovee

Copy link
Copy Markdown
Author

概述 / Overview

浏览器桥插件与扩展跟上了 dsh 0.2.1 的插件接口:在新版 dsh 上恢复加载、建立连接并调用浏览器工具,同时在插件管理页显示自己的标题、简介与图标。

动机 / Motivation

dsh 0.2.1 收紧了插件契约:Host 调用与流需要显式的调用方身份(Peer)、运行时 invariant 扩展点被移除、会话持久化后端改为函数式插件、插件清单新增版本与本地化字段。未适配的插件在握手后第一次 Host 调用就会失败,用户侧表现为侧栏一直「重连中」、所有浏览器工具不可用。

改动内容 / Changes

  • 桥插件为扩展连接建立独立的 in-process 调用方身份(宿主所有者主体、可应答用户提问),Host 调用、事件流与事件回执统一使用该身份;Host 与服务未提供该能力时以明确错误拒绝加载,而不是半可用状态。
  • 移除已废弃的运行时 invariant 伴生入口及其依赖与测试装配。
  • 插件清单补齐清单版本、运行时版本范围与 Node 版本范围;新增中英本地化标题/简介与图标,插件页读取这些元数据时无需激活插件。
  • 会话持久化后端的测试改用新版函数式插件加载方式。
  • 真机冒烟断言随 0.2.1 行为更新:重启后未认领的页面快照保留下来,而不是被取消。

测试 / Testing

  • pnpm run check:runtime、pnpm run typecheck、pnpm run test:全部通过(桥插件 189 通过 / 1 跳过——仅 POSIX 生效的文件权限断言;扩展 545 通过)。
  • node scripts/smoke-runtime.mjs:通过。真实 dsh 0.2.1-rc.2 下覆盖发现、token 认证、创建/列表/历史、模型选择、权限预设、Host 命令与 skills、V2→V4 迁移、页面快照注入,以及重启后的投影。
  • 真机手工验证(dsh 0.2.1-rc.2 + Chrome):侧栏经真实桥协议完成握手、列标签页、读文本、滚动(含增量快照)、截图(图片附件落盘并作为图片块回传)、元素与 CSS 检查、页面上下文 JS 求值、网络抓包状态查询。

影响范围 / Impact

  • 运行时不再兼容旧版 dsh:插件声明支持 0.2.1-rc.2 起的同一 0.2.x 系列,旧版会被清单中的版本范围拒绝;工作区的依赖与锁文件同步到该版本。
  • Chrome 与 Firefox 扩展的行为与配置不变,扩展侧无需重新设置。
  • 浏览器工具仍为纯文本通道,截图仍是独立工具;权限与审批语义未变。

@graydovee graydovee changed the title [功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线 [功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线(已兼容0.2.1-rc.2) Oct 17, 2026
DSH Desktop 启动 Host 时固定 `--port 0`,本地 Web 端口每次启动都由系统
随机分配,扩展原有的固定端口探测(3080/3081/3090/14389)无法命中。

- 桥接插件新增固定回环信标:在 43189–43198 范围内取第一个空闲端口回答
  `/ext/bridge-config`,通告真实桥地址与进程元数据(pid/启动时间);只绑
  127.0.0.1、不发 CORS 头、校验 Host 头(防 DNS rebinding)、不携带 token,
  端口冲突按序重试,全部被占只告警不影响桥。
- 扩展启动顺序:已填地址优先(回环地址先预检);失败才做一次自动探测
  (上次地址 → 默认端口 → 信标端口 → 扫描平台临时端口区间),命中即连;
  全空显示「未找到服务」并在本次面板租约内不再重试。
- 设置页新增「自动检测」:手动触发完整枚举(必定扫全区间、不早退),
  列出本机所有实例(地址/来源/PID/当前使用),点击条目填入地址;地址仍可
  手动填写。
- 协议仅新增可选字段(pid/startedAt/beacon、status.discovery/address 与
  discovery.* 面板消息),旧版本互相兼容。
- 测试:新增信标、端口区间、探测编排、面板交互用例;smoke 在真实 dsh
  `--port 0` 下断言信标返回同一桥地址。

验证:pnpm run typecheck、pnpm run test(桥 208 / 扩展 572)、pnpm run build、
node scripts/smoke-runtime.mjs 全部通过。
@graydovee

Copy link
Copy Markdown
Author

概述 / Overview

侧栏现在能在 DSH Desktop 每次启动随机分配端口的情况下重新找到本机 dsh:桥接插件新增固定回环信标,扩展在打开面板时只自动探测一次,设置页新增「自动检测」可列出本机所有实例并点选填入地址。

The side panel now finds a local dsh even though DSH Desktop assigns a new random port on every launch: the bridge plugin advertises a fixed loopback beacon, the extension makes a single startup pass, and Settings → Detect lists every local instance so you can pick one.

动机 / Motivation

DSH Desktop 用 --port 0 启动 Host,本地 Web 端口每次都由系统重新分配(Windows/macOS 49152–65535,Linux 默认 32768–60999),扩展原有的固定端口探测(3080/3081/3090/14389)几乎必然落空,只能让用户手工填地址。另外 dsh web 本身没有 3081/3090 回退链(绑定失败即启动失败),旧注释与实际行为不符。

改动内容 / Changes

  • 插件新增 src/discovery-beacon.ts:在 43189–43198 范围内顺序重试绑定,取第一个空闲端口;只绑 127.0.0.1,只回答 GET/HEAD /ext/bridge-config,对非 127.0.0.1/localhost 的 Host 返回 403(防 DNS rebinding),不发 CORS 头,unref() 不影响关停,端口全被占只告警一次。新增 beacon/beaconPorts 配置项(默认开启);宿主 /ext/bridge-config 响应补充 pid/startedAt,信标响应带 beacon: true;宿主绑定非回环接口时跳过信标。
  • 扩展新增 src/background/discovery.ts 与 src/background/port-scan.ts:探测顺序为「上次成功的地址 → dsh web 默认端口 → 信标端口 → 平台临时端口区间扫描」,组内并行、组间顺序、命中即停;扫描按平台选区间(win/mac 49152–65535,linux 32768–60999),并发 64、单探 400ms、总预算 20s、可取消。
  • 启动顺序改为「已填地址优先」:回环地址先做一次 /ext/bridge-config 预检,失败才自动探测一次;非回环地址(远程部署)失败不回落到本机探测。确认未找到后写入 storage.session 闸门,keepalive 与重复打开设置都不再重试。
  • 面板新增「自动检测」按钮(可取消、流式进度)与实例列表(地址 / 来源 / PID / 当前使用),点击条目把地址填入输入框;未找到时状态栏显示「未找到服务」;地址仍可手动填写。
  • 协议变更全部为新增可选字段(pid/startedAt/beacon、status.discovery/address)与新增 discovery.start / discovery.cancel / discovery.progress / discovery.result 面板消息,旧版本互相兼容。

测试 / Tests

  • pnpm run typecheck、pnpm run test:桥插件 208 通过 / 1 跳过(win32 专属),扩展 572 通过。
  • pnpm run build 与 pnpm --filter dsh-browser-extension run build:firefox 均成功。
  • node scripts/smoke-runtime.mjs:真实 dsh 0.2.1-rc.2 以 --port 0 启动,断言固定端口信标返回与宿主相同的 wsUrl,并校验 pid/startedAt。
  • 新增用例:tests/discovery-beacon.spec.ts(真实回环绑定、占用顺延、404/405/403、释放端口)、tests/background-discovery.spec.ts(顺序、早退、多实例去重合并、取消、进度)、tests/port-scan.spec.ts、tests/panel-discovery.spec.ts;更新 tests/background-bridge-lifecycle.spec.ts(已填地址优先、失败才探测、远程地址不回落、闸门不再重试)。
  • 扫描代价实测(Windows 11,Node 22,49152–65535 共 16384 个端口):并发 32/64/128 均约 2.5 秒。

影响范围 / Impact

  • 涉及 Chrome/Firefox MV3 扩展与桥接插件;不改 dsh 上游,也不改扩展 manifest(现有 CSP 已允许回环任意端口的 HTTP/WS)。
  • 新增一个回环监听端口(信标,默认 43189 起)。响应不含 token,网页读不到响应体,端口被占只降级不影响桥。
  • 多实例场景:自动探测取最先命中的信标端口;需要精确选择时使用「自动检测」列表。
  • 远程 --host 部署不启动信标;Firefox 仍需从 ~/.dsh/ext-bridge-token 填入 token。

agent-loop 在优雅关闭时调用 machine.cancel({ kind: 'disposed' }),不带
keepInbox(只有用户的停止按钮会保留待处理输入),所以未认领的页面快照会被
记成一条 canceled 的 agent/inbox/spliced。原断言假设 dsh 会用 keepInbox 保留,
与 0.2.1-rc.2 的实际行为相反,导致 test:smoke 在 main 上一直失败。

断言改为校验真实契约(恰好一条 canceled splice、removedCount=1);信标探测在
本机已有其他 dsh 占用更早端口时,优先选择指向本次 host 的应答。
content-selection.spec.ts 每个用例都新建 SelectionWatcher 但从未 disarm。
watcher 残留的 selectionchange 监听与 debounce 定时器可能跨到 jsdom 环境销毁
之后才触发,CI 偶发报 unhandled ReferenceError: document is not defined
(run #7 的 clean-install 即因此失败)。改为在 afterEach 统一 dispose。
graydovee added a commit to graydovee/dsh-browser that referenced this pull request Oct 19, 2026
- 5a62443 fix(smoke): 按 dsh 0.2.1 的 dispose 语义断言 inbox 取消
- 08c18d1 test(selection): 释放 watcher 定时器,消除 jsdom 拆环境后的未处理错误
- 来源:承载分支 omdsh-dev/dsh-browser(上游 PR omdsh-dev#121 的 head)
@graydovee

Copy link
Copy Markdown
Author

概述 / Summary

测试与真机冒烟基础设施修正:smoke 断言改为 dsh 0.2.1 的真实 dispose 语义,并修掉一个会让 CI 偶发失败的 selection 测试定时器泄漏。无产品行为变化。

动机 / Motivation

  • dsh-agent-loop 在优雅关闭时调用 machine.cancel({ kind: 'disposed' }),不带 keepInbox(只有用户点停止才保留 inbox),未认领的页面快照会被记成一条 canceled splice;原 smoke 断言假设它会被保留,在 0.2.1-rc.2 上必然失败。
  • content-selection.spec.ts 每个用例新建 SelectionWatcher 却从不 dispose,残留定时器可能在 jsdom 销毁后触发 document is not defined,导致 CI 偶发失败。

改动内容 / Changes

  • smoke:断言重启后恰好一条 agent/inbox/spliced(outcome: canceled、removedCount: 1);信标探测在多实例并存时优先选择指向本次 host 的应答。
  • 测试:content-selection.spec.ts 的 watcher 统一在 afterEach dispose。

测试 / Testing

  • node scripts/smoke-runtime.mjs:通过
  • pnpm run typecheck / pnpm run test(572 通过)/ pnpm run build:通过
  • 承载分支 CI 与同步到 main 的 PR 均通过

影响范围 / Impact

仅测试脚本与用例;无 wire 协议、权限、依赖或运行时行为变化。

页面交接提示里新增第一个动作「跳转回到助手页面」:保持助手绑定不变,把用户前台标签页切回助手所在页面(跨窗口时先聚焦该窗口),状态随即回到 following。只在 handoff 状态出现,携带面板看到的 revision,过期点击失败关闭;受控页已关闭时转入 lost。同时按主体重命名三个选项:助手留在原页面 / 助手跟随当前页面 / 助手留在原页面并不再询问。
@graydovee

graydovee commented Oct 19, 2026 •

Copy link
Copy Markdown
Author

概述 / Summary

页面交接提示新增第三个选择「跳转回到助手页面」:当助手仍绑定原页面、用户切到别的标签页时,可以一键把浏览器的前台标签页切回助手正在操作的页面(跨窗口时连同该窗口一起带到前台)。同时把三个选项按主体重新命名,让「谁留在哪里」一眼可辨。

对应代码改动与 changelog 条目见 fork 仓库 PR #10(已合入承载分支 omdsh-dev/dsh-browser)。

动机 / Motivation

原交接提示只有两个选择:「留在原页面」让助手留在原页、用户继续看新页;「跟随当前页面」把助手改绑到新页。当用户其实想回到助手所在的页面时两种都不合适——只能自己找回那个标签页。另外两个选项的名字都没写主体,容易混淆。

改动内容 / Changes

  • 交接提示首行新增「跳转回到助手页面」按钮,只在交接尚未决定时出现;点击后绑定不变,前台标签页切回助手页面,提示随之消失。
  • 三个选项按主体重命名:助手留在原页面 / 助手跟随当前页面 / 助手留在原页面并不再询问。
  • 跨窗口:先聚焦助手页面所在窗口,再激活该标签页;任一环节失败即整体失败,不改变绑定,也不留下部分切换状态。
  • 失败关闭:点击携带面板看到的版本号,状态已变化就忽略这次点击;受控页已关闭则转入「受控标签页已关闭」;窗口无法聚焦或激活被拒时在侧栏给出错误提示。
  • 扩展仍然不会静默切换用户正在看的标签页;除用户主动点击该按钮外,原有行为不变。
  • 文档:README 中英同步补充该动作;changelog 中英各一条。

测试 / Testing

  • pnpm run typecheck、pnpm run check:runtime、pnpm run test(69 文件 / 600 用例)、pnpm run build:全部通过。
  • 新增用例覆盖:按钮出现条件、请求携带的版本号与失败码、后台激活与窗口聚焦顺序、受控页已关闭、窗口聚焦失败、状态回到已跟随。
  • 真机(Chrome):重新加载扩展后手测三个选项、跨窗口、受控页已关闭与连点。

影响范围 / Impact

  • 仅影响 Chrome(sidePanel)与 Firefox(sidebar_action)侧栏的页面交接提示;桥插件 wire 契约未变,无需重启 dsh。
  • 只新增一个可选动作并调整文案,既有 keep / follow / pin 语义与失败关闭边界不变。

The devtools capability test waited only for the server-side tool
registration, then immediately looked up the hello.ok ack frame in the
client's frame list. The ack is delivered asynchronously, so the find
could run before the frame arrived and the assertion saw undefined
(intermittent CI failures on main and on the release branch).

Wrap the lookup in waitFor so the assertion polls until the ack frame
arrives.
自动发现原本在信标全部落空后还会扫一遍平台临时端口区间(Windows/macOS
16384 个、Linux 28232 个端口),用来兼容没有发现信标的旧宿主。现在插件与
扩展一体安装、旧宿主的混搭场景很窄,这条兜底路径代价明显更大,因此移除:

- 删除 port-scan.ts(区间、并发、超时与扫描上限常量)及其用例;
- discovery.ts 只保留固定端口组(上次地址 → 常用端口 → 信标端口),
  进度改为按组上报;
- 面板文案从「扫描」改为「探测」,实例来源去掉 scan;
- README 中英同步去掉临时端口区间扫描的描述。
@graydovee

Copy link
Copy Markdown
Author

概述 / Summary

浏览器工具从「按编号点击/输入」扩展为一层通用输入能力:指针手势与坐标、组合键与按住、光标插入与逐键输入、剪贴板(文本/富文本)、文件上传、单 iframe 精读。新增 browser_clipboard、browser_upload 两个工具,并扩展 browser_snapshot、browser_click、browser_type、browser_press、browser_scroll、browser_follow_tab。

动机 / Motivation

富文本编辑器、画布/SVG 白板、代码编辑器和拖拽界面没有语义角色,快照清单点不到;原 browser_press 只有单键且是合成事件,Cmd+A / Cmd+V 不生效;编辑器自持文档模型,直接写 value 会被回滚。缺口是输入原语,不是应用适配,所以按「新的输入介质」新增工具、其余扩展现有工具。

改动内容 / Changes

  • 指针:browser_click 支持 index / selector / point 三选一,action(click/dblclick/move/down/up/drag)、button、clicks、modifiers、to、steps、trusted;元素默认走 DOM 事件序列(含 pointerdown/mousedown),point 与手势走真实鼠标。
  • 键盘与文本:browser_press 支持组合键、action: down/up 跨调用按住、repeat、聚焦目标;browser_type 支持 selector、mode: auto/insert/keystrokes、trusted。
  • 剪贴板:browser_clipboard 的 write 写系统剪贴板(Chrome 离屏文档),paste 支持合成粘贴事件与真实系统快捷键;粘贴事件未被消费时对普通 input 回退光标插入。
  • 文件:browser_upload 在宿主侧校验绝对路径/存在/普通文件,再经 CDP 设置 file input;扩展不读取文件内容。
  • 定位:browser_snapshot { query } 按文本/选择器/角色定位任意元素(含隐藏可聚焦代理),返回 CSS 选择器与 rect;browser_snapshot { frame } 单读一个 iframe 并占满预算。
  • 输入通道:共享 chrome.debugger broker(devtools 与 input 共用单标签页附加,输入空闲 20s 释放);input 只用 Input.* 与 Emulation.setFocusEmulationEnabled;输入状态按标签页保存并在导航/关页重置;frame 局部坐标经 frameElement 链换算到标签页视口。
  • 平台适配:macOS 编辑快捷键补 commands(selectAll/copy/paste/cut/undo/redo);keystrokes 模式显式携带大写字符;滚轮要求活动标签页 + 聚焦窗口(后台冻结页快速失败并提示 follow_tab {activate:true});截图拒绝未聚焦窗口,避免过期帧;导航只释放 input 占用,devtools 抓包跨 reload 存活。
  • 文档:中英 README、组件 README、设计记录(2026-10-21-browser-input-layer)与 changelog 同步;新增 10 个测试文件。

测试 / Testing

  • pnpm run typecheck、pnpm run test(桥 222 + 扩展 700)、pnpm run build、Firefox 构建、pnpm run check:runtime、node scripts/smoke-runtime.mjs 全部通过。
  • 真机(macOS Chrome 155 + DSH Desktop,Confluence 草稿页 / 临时标签页 / 本地 fixture):三轮 94 / 40 / 21 项;最终 20 PASS / 0 FAIL / 1 SKIP。首轮 12 个失败项全部修复并复测通过:selector-only 目标、Meta+A/Meta+V、keystrokes 大写、滚轮前台/后台守卫、抓包跨 reload、upload 路径校验、截图新鲜度、paste 回退、错误码包装。
  • 截图正向路径:写入唯一标记 → 截图可见 → 清空 → 再截图标记消失(两帧哈希不同),确认不是过期帧。
  • 上传成功路径:本地 fixture 页(file input + change 处理器)附加 4 字节文件,页面读回文件名与大小;不触碰 Confluence 正文。
  • SKIP:真实文件上传到 Confluence 正文编辑器(会修改草稿正文,改用本地 fixture 验证成功路径)。

影响范围 / Impact

  • Chrome/Edge:新增 clipboardWrite、offscreen 权限与离屏剪贴板页;真实输入会附加调试器(提示条、该标签页暂不能开 DevTools),空闲 20s 自动释放。
  • Firefox:无真实输入 / 系统剪贴板写入 / 文件上传,自动降级为合成输入并在结果标注 (synthetic);元素寻址、文本、粘贴事件、query 照常。
  • macOS:编辑类 Meta 快捷键依赖 commands;其它平台行为不变。滚轮与截图需要前台/聚焦窗口,属于 Chrome 合成器限制。
  • 输入默认后台执行:不激活标签页、不聚焦窗口、不移动系统鼠标。

对应代码改动与 changelog 条目见 fork 仓库 PR #18

- 工作区 35 个 @deepseek-ai/dsh-* 依赖与桥插件 20 个 devDependencies 升到 0.2.1-rc.3,锁文件重算
- engines.dsh 与 peerDependencies 保持 ^0.2.1-rc.2:rc.3 的插件接口与 rc.2 一致,两个宿主都受支持
- 桥插件 README(中英)、README.i18n.yaml 哈希、cordis.patch.yml 与 manifest 断言注释同步到 rc.3
- 验证:build、typecheck、check:runtime、test(77 文件 / 686 用例)、smoke-runtime 全部通过
graydovee added a commit to graydovee/dsh-browser that referenced this pull request Oct 24, 2026
- CHANGELOG.md / CHANGELOG.zh-CN.md 各一条 ## latest 条目
- 根 README(中英)与扩展 README(中英)的运行时兼容说明、`npx` 示例同步到 rc.3
- scripts/install.sh / install.ps1 的固定版本示例同步到 rc.3(PowerShell 脚本保留 UTF-8 BOM)
- 根与扩展 README.i18n.yaml 哈希回写;.agents/notes/upstream-pr-flow.md 的运行时版本号更新
- 纳入 fork 合入流程文档:AGENTS.md 与 .agents/notes/fork-feature-flow.md
  (承载分支 → 上游 PR omdsh-dev#121 仅 edit 描述 → 从 main 切 PR 分支 --no-ff 合并承载分支并补 changelog)
@graydovee graydovee changed the title [功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线(已兼容0.2.1-rc.2) [功能汇总] fork 仓库的新增功能,后续持续追加,可随时合回主线(已兼容0.2.1-rc.3) Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant