Bundle
dsh-html-picker-preview
PickDOM:DSH 侧边栏双引擎 Browser,像 Cursor 一样框选本地 HTML 与 http/https 页面元素交给 Agent;本地文件支持可视化编辑并写回源码。
- Source
- xiaobaiyg09
- License
- MIT
- Updated
- Updated 6 days ago
Readme
# PickDOM
**像 Cursor 一样框选元素:你点哪里,Agent 就改哪里。**
PickDOM 是 DSH(DeepSeek Harness)侧边栏的双引擎 Browser 插件。本地 HTML 文件与 http/https Web App 都能在侧边栏直接打开,悬停高亮、点击框选,元素的 selector、文字、outerHTML、尺寸与关键样式即刻进入 Agent 对话。给 Agent "指"一个界面元素,从此只需要一次点击。
```text
打开页面 → 点框选 → 点元素 → Agent 收到引用 → 改完保存
```
> 仓库名 `dsh-pickdom`;npm 包名保持为 `dsh-html-picker-preview`,安装命令以包名为准。

## 它解决什么问题
让 Agent 改前端界面,最贵的环节从来不是写代码,而是"指清楚改哪里":
- **截图标注**:Agent 猜位置,猜错一轮重来
- **手写 selector**:你得先在 DevTools 里翻半天 DOM
- **整页 HTML 粘贴**:上下文爆炸,Agent 在噪音里捞针
PickDOM 把"指"压缩成一次点击,而且交给 Agent 的是结构化引用(selector、文字、outerHTML、尺寸、关键样式),不是一张需要猜的图片。
## 功能演示
### 像 Cursor 一样框选并发送给 Agent
点击工具栏中的框选按钮进入 Picker 模式,在本地 HTML 或 Web App 中悬停并点击目标元素。

选中后,元素引用会直接进入 Agent 输入框。你可以继续补充"改下布局"、"调整颜色"等要求,再把带有精确 DOM 上下文的指令发送给 Agent。

### 直接编辑元素文字
进入编辑模式后,点击页面元素即可定位到对应 DOM,并在多行编辑器中修改内容。

### 复制页面元素
选中元素后点击"复制",PickDOM 会创建副本,并自动重写常见 `id`、ARIA、表单与 SVG 引用,降低引用冲突风险。

复制后的元素仍可继续调整尺寸、编辑文字、删除或发送给 Agent。

## 双引擎
### File Engine · 本地 HTML
在侧边栏打开 `.html/.htm` 文件,相对路径的 CSS、JS、图片、字体与嵌套 iframe 全部正常解析。除了框选,还能直接改:
- Cursor 风格工具栏:后退、前进、刷新、`file://` 地址栏
- 点击选中安全可见元素,父级面包屑切换层级
- 多行文字编辑:普通文本、`input`、`textarea`,`Cmd/Ctrl+Enter` 保存、`Esc` 取消
- 复制元素:自动重写常见 `id`、ARIA、表单与 SVG 引用,避免冲突
- 删除元素,支持撤销 / 重做(`Cmd/Ctrl+Z`、`Cmd/Ctrl+Shift+Z`)
- 右、下、右下手柄调整宽高,`Shift` 保持比例
- 从浮动工具栏一键把当前元素发给 Agent
- 保存写回真实 HTML 文件(含嵌套 iframe 对应的文件)
- 离开编辑模式、导航或刷新前检查未保存修改
- 最近打开记录保存在 GUI localStorage
### Web App Engine · http/https 地址
地址栏输入 `http://localhost:5173`、`localhost:5173` 或 `https://example.com` 即可打开 Web App。它使用 Electron `WebContentsView`(原生 Chromium),而不是 iframe 或反向代理:
- 不受目标站点 `X-Frame-Options` / `frame-ancestors` 限制
- 页面滚动、输入法、拖拽、WebSocket、Vite HMR 都是原生 Chromium 行为
- 通过 CDP `Overlay.setInspectMode` 高亮与选择元素
- 元素引用包含 URL、selector、文字、outerHTML、尺寸与关键 computed styles
- 支持连续框选,`Esc` 或再次点击框选按钮退出
- 独立非持久 partition:DSH 退出后清除该引擎的 Cookie / Storage
- 摄像头、麦克风、定位等权限默认拒绝
## 快速开始
要求 DSH `>=0.1.1-rc.1`。
```bash
dsh plugin --profile <name> add dsh-html-picker-preview
```
或手动在 `~/.dsh/profiles/desktop/cordis.patch.yml` 追加:
```yaml
- insert:
- id: html-picker-preview
name: 'dsh-html-picker-preview'
config:
mediaLimit: 33554432
allowOutsideCwd: false
injectBridge: true
```
更新 Node 宿主路由后需重启 DSH Desktop;仅 client 变化时刷新 GUI 即可。
## 三种模式
工具栏上三个互斥模式,覆盖"看、指、改"完整链路:
| 模式 | 用途 | 行为 |
| --- | --- | --- |
| 浏览 | 正常使用页面 | 链接、按钮、表单全部可交互 |
| 框选 | 给 Agent 指元素 | 悬停描边,点击插入引用;保持框选可连续选择,`Esc` 退出 |
| 编辑 | 直接改本地 HTML | 点击元素出现选择框、面包屑与浮动操作栏 |
## 安全模型
本地文件读写走短生命周期 capability,而不是裸路径:
- **GUI 与预览分源**:GUI 在 `127.0.0.1` 时预览使用 `localhost`,反之亦然
- **每次打开独立 token**:宿主验证会话与 cwd 后签发高熵 token,绑定 session、入口目录、GUI authority 与 preview authority
- **保存 capability**:每个 HTML 响应携带绑定 token、session、文件路径与 baseHash 的 HMAC,保存时同时校验 capability 与签发它的 GUI authority
- **目录围栏**:token 只能读取入口 HTML 所在目录树,借 token 读不到同一 cwd 的其他目录
- **预览页无写权限**:预览 origin 不能申请 token,也不能调用保存 API;页面脚本即使看到 path/hash/capability 也无法绕过
- **乐观锁**:保存前用 SHA-256 校验磁盘文件,被 Agent 或其他编辑器改动后返回 409,不静默覆盖,也没有 `force:true` 绕过
- **原子写入**:临时文件 + rename 覆盖,保留原文件权限;保存成功返回新的 hash/capability,支持连续保存
- **外部 framing 防护**:CSP `frame-ancestors` 只允许当前 preview origin 与对应 DSH GUI origin
预览使用 `allow-same-origin` 以兼容复杂本地原型的 localStorage 与同源嵌套 iframe;安全边界由独立回环主机、作用域 token、GUI authority、HMAC 保存 capability、CSP 与路径围栏共同提供。
## 已知限制
诚实比演示重要,这些是当前版本的真实边界:
- Web App Engine 只提供浏览与框选,**不保存运行时 DOM**。React/Vue 页面需要后续通过组件源码映射与 HMR 修改源码,运行时 DOM 无法可靠序列化回 JSX/SFC
- `WebContentsView` 位于 DSH renderer DOM 之上,覆盖页面区域的 DSH 全局弹窗可能被原生网页遮挡;切换 File Engine、关闭 Tab 或卸载插件时会立即隐藏并销毁 surface
- 最多同时创建 3 个 Web App surface
- DOM 序列化保存可能规范化 HTML 格式、实体、标签结构与 doctype;复杂 React/Vue 页面建议先保存静态快照再编辑
- 保存前会明确确认:页面脚本运行后产生的动态 DOM 状态也可能被序列化进文件
- 编辑模式为 MVP:暂无自由拖动、Frame、组件面板、多选对齐、响应式双断点
- 自动锁定 `html/head/body/script/style/link/meta/template/noscript`;SVG 内部节点只选择完整 SVG,Canvas 只能选择 Canvas 元素;跨域 iframe 只作为 iframe 元素处理,由预览 capability 加载的本地嵌套页面可继续选择和编辑
## 配置
| 键 | 默认值 | 说明 |
| --- | ---: | --- |
| `mediaLimit` | `33554432` | 单文件读取与保存上限(字节,默认 32MB) |
| `allowOutsideCwd` | `false` | 是否允许访问会话 cwd 外的路径;放开后任何本地文件都可被回环请求读取,属自担选项 |
| `injectBridge` | `true` | 是否向 HTML 响应注入 picker/editor 运行时 |
## 架构
```text
dsh-pickdom/
├── package.json
├── cordis.patch.yml
├── lib/
│ ├── index.js # Node:作用域 token、文件资源、保存 API、Browser API
│ ├── browser-surface.js # Electron WebContentsView + CDP Inspect
│ ├── bridge.js # picker 与嵌套 iframe 消息桥
│ ├── editor-runtime.js # 选择、文字、复制、尺寸、undo/redo、序列化
│ ├── editor-runtime.css # 选择框、浮动工具栏、尺寸手柄
│ └── client.js # Browser UI、三模式、Agent 引用、保存协调
└── README.md
```
Browser 通过 `dsh-better-sidebar` 注册 Tab 和 HTML 文件查看器。Agent 引用使用 DSH `inputTriggers` / reference codec;不可用时回退为结构化草稿文本。
## License
MIT
Install
dsh plugin --profile web add github:xiaobaiyg09/dsh-pickdom
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-html-picker-preview from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.