DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-page-annotate

b

dsh-page-annotate

Manifest valid

DSH page annotate 网页标注插件,用于页面批注、元素标记

UI (client)hasBundlePatchMachine translated

dsh-page-annotate

在 DSH 右侧边栏的 HTML 预览里直接圈选元素、写批注,然后把整批批注作为一条消息发进当前会话,让模型按批注改页面。

这就是 Codex 那种「预览里标注 → 回到会话修改」的体验,只是做成了 DSH 的插件。

它解决什么

DSH 自带的文档预览是只读的:没有元素选择器、没有批注模型,iframe 是 sandbox="allow-scripts" 的跨源沙箱,父页面也无法注入脚本进去。所以想「在预览里标注」,只有一条路——由插件自己渲染预览。

这个插件就是这么做的:它注册自己的边栏标签类型,自己建 iframe、自己注入 overlay,因此 postMessage 通道是可控的同源通道,不依赖任何宿主路由,也不依赖「开发者工具」开关。

用法

  1. 在会话里打开一个 HTML 文件的预览(工作区文件树里点它)。
  2. 默认选择「HTML · 页面批注」预览实现,点击预览头部的 「批注」,在同一个 iframe 上开启选择,不新增标签、不重读文件、不关闭已经打开的弹窗,输入与脚本状态保留。 更新前的内置预览或手动选择的其他渲染器无法原地注入;升级后请重新打开页面,并确认使用「HTML · 页面批注」。已有旧批注标签仍兼容旧的读取路径。
  3. 直接在页面上选择元素,无需再点击「选择元素」:
    • 移动鼠标高亮元素,点击它弹出批注框;
    • 默认只显示编号、配置按钮、评论输入框和 ✓,自动聚焦输入;
    • 点配置按钮才展开样式参数(文字颜色、背景颜色、字号、字重、不透明度);元素路径和分类按钮不再显示,但后台定位证据照常发送。颜色支持点击色块打开可视取色面板,调整明暗/饱和度、色相、透明度或输入十六进制值;这些参数读取元素当前值,修改后记录为批注目标,不直接修改页面;
    • Enter 或 ✓ 保存,Shift+Enter 换行,输入法确认不会误保存;取色面板打开时 Esc 先关闭取色器,再按 Esc 才取消未保存编辑并退出选择;已保存批注保留。
  4. 继续标注下一个——保存后不会退出选择模式,所以可以连着点若干个元素、逐个写批注,不必每次重新点「选择元素」。 每个元素上会出现编号角标,点角标可以重新编辑,「删除」可以移除。
  5. 全部标完后二选一:
    • 发送到会话:把所有批注编译成一条消息,直接进会话队列;成功后原地退出批注,保留当前弹窗与输入,失败则保留批注以便重试;
    • 填入输入框:只写进输入框,你可以补充说明再自己发。

多条批注是一次发送、一条消息,按编号成组,不是一条一条发——这样会话侧能一次看到全部修改点,也不会触发多次生成。

页面本身不会被改动——overlay 只在内存里注入,原文件保持可 diff。

防止修改到错误位置

每条批注附带当前 DOM 的精确 CSS 选择器、匹配数量、所属区域/弹窗唯一 ID 与标题、经过限长和清理的目标 HTML 片段。面包屑保留更深祖先,避免多弹窗相似 class 导致混淆。这些是运行时定位证据,不是源文件行号。

消息要求模型先核对源码位置,禁止只按相同文案/通用 class 全局替换;不能唯一确定时先询问,改后检查同名非目标区域不变。此举降低误改风险,但不保证模型完全不会犯错。

蓝色序号、选择框、批注栏均为临时工具标记,消息明确禁止将其写入最终页面;页面原有的业务序号列不受此约束影响。

截图随批注发送

底部默认勾选「附带截图」。保存每条批注时留存当前视口 PNG,编辑该条批注后更新它的截图;发送时同批附带多张真正的 image 附件。不同弹窗/滚动位置可以保留各自画面,不再只截发送时的最后一个视口。

  • 按最终批注顺序排列图片,提示词逐张列出「附图1(S1)对应批注1」,文件名也标注对应批注;完全相同PNG可去重共用一张,映射仍保留。

  • 删除其他批注可能改变最终编号,因此对应表额外保留捕获任务创建时编号;以对应表和元素定位为准,不把历史图里的旧编号当作当前顺序。

  • 排队后的捕获、旧会话恢复/失败后发送时补拍会明确注明不是保存瞬间,绝不声称恢复了历史画面。截图仅内存保留,关闭标签或重启不持久化。

  • 每批最多保留12条批注截图,base64总量最多20MiB;超额会阻止带图发送,须减少批注或取消附图,不能静默丢图。

  • 截图保留批注编号,并为各已保存批注对应的目标绘制蓝色边框与淡蓝底,编号与位置可以直观对应;不包含评论输入浮层或无关的鼠标悬停高亮。边框只在截图克隆中绘制,不改原页面;屏幕外元素以文字定位为准。

  • 可取消勾选,只发送文字;「填入输入框」目前只填文字,不插入图片。

  • 截图失败会明确提示并保留批注,不会自动退回只发文字。模型不支持图片时可取消勾选再重试。

  • 截图库离线随包附带,不访问 CDN 或第三方截图服务;会读取并可能重新请求页面自身的资源。

  • 技术上是 html2canvas DOM 重绘,不是原生屏幕像素截图。部分 CSS、无 CORS 授权的跨域图片、跨域 iframe、视频/WebGL 可能无法准确还原。发送前请确认页面可视内容适合分享给会话模型。

  • 为控制体积,截图最长边不超过 1600px,不按 Retina 倍率放大。

送到会话的消息长什么样

插件启用时,新的批注消息默认折叠显示「2条批注 · 2张截图」,点击即可展开原样完整提示词,再点击收起。缩略图仍使用DSH原生图片附件展示。完整文本与图片照常进入模型上下文,并非删掉定位信息;刷新会话后仍可从稳定标记识别。关闭插件会回退显示完整普通消息,旧版已发送的无标记消息不会自动折叠。「填入输入框」仍是纯文字,不插入图片、不封装为折叠消息。

展开内容示意(实际含定位证据与逐图映射):

请按下面的批注调整「提交工单AI预处理改造设计」。

文件:`业务需求/20260923-提交工单AI预处理改造设计.html`

1. [调整] `table#orders > th.cell`
   > 是否二级订单
   这里调整成加粗字体

2. [删除] `td.cell`
   这一列不需要

批注里没有提到的部分保持原样,只改这里列出的内容。

安装

包声明了 dsh.bundle.patch,所以插件管理器会自己完成三件事:装依赖、把这个包加进 profile 的组合层、插入 Loader 行。不需要手改任何 YAML。

给别人装(推荐:图形界面)

  1. 插件页 →「安装插件」
  2. 粘贴 tgz 的绝对路径(~ 不行),或选「本地目录」
  3. 装完重启一次 DSH

命令行等价写法

# 注意 flags 紧跟在 profile 名后面,否则会被当成 app 参数
dsh plugin --profile <profile> add /绝对路径/dsh-page-annotate-0.1.0.tgz

开发时(软链到自己改的目录)

ln -sfn /Users/baigo/Documents/workspace/projects/dsh-page-annotate \
        ~/.dsh/profiles/desktop/node_modules/dsh-page-annotate
# 并在 profile 的 package.json 里写:
#   "dsh-page-annotate": "link:/Users/baigo/Documents/workspace/projects/dsh-page-annotate"

软链的好处是改完源码立刻生效;代价是目录一移动插件就失效(link: 不是副本)。给别人用请用 tgz,那是 file: 副本,删掉 tgz 也不影响运行。

重启只在首次安装时需要。 profile 对插件包的解析在启动时缓存(profile resolution 不允许热替换同名包),所以第一次把包挂进去必须重启一次。

更新预编译客户端产物后,建议刷新 DSH 页面并重新打开 HTML 预览。宿主包含 HMR 接收机制,但不保证当前安装环境正在构建或推送更新;若仍是旧版本,再重启 DSH。

判断依据:bundle 以 ?rev=<12位hash> 下发且带 cache-control: immutable,rev 不变浏览器就不会重新请求——所以"页面没变"通常意味着 rev 没变(HMR 没看到文件变化),而不是需要重启。

怎么确认自己看到的是哪一次构建:把鼠标停在批注面板左上角的文件名上,tooltip 末尾有 build 2026-10-22 16:34 这样的本地时间戳(构建时写入)。没看到时间戳或时间偏旧,就是旧 bundle 还在跑。

卸载

rm ~/.dsh/profiles/desktop/node_modules/dsh-page-annotate
# 然后从 cordis.patch.yml 删掉那个 insert 条目、从 package.json 删掉依赖

开发

npm run build   # 把 src/ 组装成 lib/client.js
npm test        # 运行全部回归测试
npm run check   # build + 语法检查 + 全部测试

源码结构

文件作用
src/core.mjs纯逻辑:元素定位串、批注规范化、消息编译。无 DOM、无 React,浏览器和 node --test 共用同一份。
src/overlay.js注入到被标注页面里的脚本:选择、高亮、批注框、角标、postMessage 协议。
src/client.factory.js客户端 React 半部分:标签类型注册、边栏 tab body、文档操作按钮、iframe 与协议桥接。
tools/build.mjs组装 lib/client.js。没有打包器、没有 TypeScript——client.js 的格式就是 DSH 的 loader 信封,源码即产物形状,构建只是拼接。

构建做三件事:

  1. 把 src/core.mjs 的 export 去掉后拼进 factory(这样它的 helper 在客户端作用域里可见);
  2. 把 core.mjs + overlay.js 作为字符串嵌进去——overlay 要在被标注页面里跑,那里没法 require;
  3. 套上 window.__ModuleLoader__.load({ id, factory }) 外壳。

客户端 bundle 契约

lib/client.js 不是模块,是 loader 注册脚本:

window.__ModuleLoader__.load({
  id: "dsh-page-annotate",
  factory: (require) => {
    var module = { exports: {} };
    var exports = module.exports;
    let react = require("react");          // 共享模块表,缺什么 require 什么
    /* ... concatenated core + client body ... */
    exports.apply = apply;                 // 客户端插件入口
    exports.inject = inject;               // 需要的 service 名数组
    return module.exports;
  }
});

package.json 里 dsh.client 的 inject 是包名依赖(决定 bundle 加载顺序),exports.inject 是服务名依赖。两者不同,都要维护。

测试覆盖

  • tests/core.test.mjs — 定位串、批注规范化、消息编译等纯逻辑测试。
  • tests/overlay.browser.test.mjs — 真实 Chromium 测试:元素选择、多条批注、Esc 取消与已保存内容保留,并读取真实设计稿验证。
  • tests/client.wiring.test.mjs — 装配与生命周期测试:同位置替换标签、自动选择、加载握手不覆盖 Esc、读取 Remote 信封。
  • tests/packaging.test.mjs — 组合包声明、补丁与中文元数据发布契约。

浏览器测试在缺 Playwright 时自动跳过。

设计取舍

为什么自定义地址。 批注标签的地址是 dsh-resource://page-annotate/session/<sessionId>/<path>,而不是复用 dsh-resource://file/...。因为边栏布局持久化的是 contentId(地址)本身,把 Session 和路径编进地址,刷新后标签页仍然知道自己在显示哪个文件,不需要额外的桥接表。canOpen 会重新解析地址,所以文档预览的地址不会被抢走。

为什么 overlay 不写进文件。 设计稿要保持可 diff、可交付;overlay 是运行期注入的,文件一个字节都不动。

为什么要重新校验。 批注来自一个沙箱 iframe,属于不可信输入。normalizeAnnotations 会在进入 prompt 之前重新检查每个字段(长度上限、类型、kind 白名单)。

发送路径的取舍。 优先「填入输入框」——文本留在编辑器里可见可改。直接发送走 sessions.binding(id).session.prompt([{type:"text",text}], "queue");不用 conversation.send(),因为那个要求调用方处在会话作用域内,而从标签页的 inject 里拿不到。

已知边界

  • 只处理 HTML;Markdown/Excel/图片的预览不显示「批注」按钮。
  • overlay 需要 iframe 允许脚本,因此用 sandbox="allow-scripts allow-same-origin"。被标注的页面里的脚本会照常运行——和自带的交互式预览一致。
  • 页面重挂载时批注会保留(按地址存放在内存 Map 里),但不跨应用重启持久化。
  • 元素在重挂载后按 CSS 选择器重新绑定;页面结构变化后再次标注即可。

Comments

Loading…

Similar plugins

dsh-annotation-patched

by DDDFXYqiming

DSH Web annotation/quote plugin (fork enhanced)

Development & InfrastructureTerminal & ClientsManifest valid

★ 2

MIT

JavaScript

Oct 15, 2026

dsh plugin --profile web add @dsh-external/dsh-annotation-patched

Adds text selection annotation tools and annotation chips to the dsh web composer.

UI & ExperienceManifest valid

★ 0

dsh plugin --profile web add dsh-annotation

by xujian519

对DSH的交付物进行标注的插件,人工标注后,DSH会根据标注执行

Tools & CapabilitiesManifest valid

★ 0

NOASSERTION

TypeScript

Sep 28, 2026

dsh plugin --profile web add dsh-annotator

by zhxnix

Codex-style DSH right-sidebar browser preview, element annotations, context notes, and debugging tools.

UI & ExperienceDevelopment & InfrastructureManifest valid

★ 0

MIT

JavaScript

Sep 22, 2026

dsh plugin --profile web add dsh-sidebar-annotations

by cslkkl

Annotate pages and ask questions inside the existing DeepSeek Harness Browser.

Tools & CapabilitiesUI & ExperienceManifest valid

★ 0

MIT

TypeScript

Oct 3, 2026

dsh plugin --profile web add dsh-web-annotator

by AnLifeX

dsh 提醒插件:别错过需要你的时刻

Terminal & ClientsManifest valid

★ 3

↓ 60/wk

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add dsh-attention