dsh-agent-team-ui-testing 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/client.js +767 -33
- package/docs/capture-p0.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/images/tutorial-01-overview.png +0 -0
- package/docs/images/tutorial-02-history-dropdown.png +0 -0
- package/docs/images/tutorial-03-pick-element.png +0 -0
- package/docs/images/tutorial-04-annotate.png +0 -0
- package/docs/index.md +2 -1
- package/docs/tutorial.md +126 -0
- package/docs/verification.md +2 -0
- package/docs/viewport-control.md +6 -2
- package/package.json +2 -2
- package/skills/ui-testing-web/SKILL.md +5 -5
- package/skills/ui-testing-web/references/scenarios/annotations.md +7 -1
package/docs/capture-p0.md
CHANGED
|
@@ -37,7 +37,7 @@ browser_screenshot { "includeAnnotations": true }
|
|
|
37
37
|
browser_screenshot { "includeAnnotations": true, "scale": 1.5, "region": { "x": -100, "y": 0, "width": 800, "height": 600 } }
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
- 只叠加已提交且已由 Host 接受的标注文档;圆形/椭圆(`circle`)、矩形(`rect`)、线段(`line`)、箭头(`arrow`)、画笔(`brush`)、文字(`text
|
|
40
|
+
- 只叠加已提交且已由 Host 接受的标注文档;圆形/椭圆(`circle`)、矩形(`rect`)、线段(`line`)、箭头(`arrow`)、画笔(`brush`)、文字(`text`)的颜色、粗细与填充/外框遵循面板渲染语义。橡皮擦与清除用于编辑文档,不是额外形状;面板的「选择」「框选」与选中光晕/包围框同属编辑 UI,也不进入叠加结果。
|
|
41
41
|
- 面板标注栏的「截图」按钮通过 `POST /plugins/ui-testing/screenshot {includeAnnotations:true}` 拿同一份合成 PNG 交给聊天框附件(不起新标签、不落盘);
|
|
42
42
|
- 写这份文档的入口有**两处**:面板认证的 `POST /plugins/ui-testing/annotations`,以及 Agent 工具 `browser_annotation`(`read`/`draw`/`erase`/`clear`,`draw` 追加形状、`clear` 清空)。两者写的是同一份文档,所以 `includeAnnotations:true` 会把人类画的与 Agent 画的形状一起叠加;写动作的前台门禁、`expectRevision` 冲突与软限额见[视口、画布与标注](viewport-control.md)。
|
|
43
43
|
- 页面与标注使用同一 `region`/`scale` 映射和裁剪。画布点 `d` 在截图中的连续像素位置为 `(d − region.origin) / capture.mapping.cssPerPixel`(逐轴计算,通常等于乘以 scale);线宽、文字与笔迹同步缩放。负坐标和画布空白区域也沿用该映射。
|
package/docs/getting-started.md
CHANGED
|
@@ -73,11 +73,11 @@ browser_screenshot {out} # 留一张可复核的 PNG
|
|
|
73
73
|
- **实时预览**:CDP screencast 帧,WebSocket 推送优先、HTTP 轮询兜底。
|
|
74
74
|
- **尺寸栏**:宽屏 / 横屏 / 平板 / 手机预设,X/Y 画布位置,宽 × 高,显示比例,`拖拽 | 适应窗口 | 默认` 模式。
|
|
75
75
|
- **混合画布**:视口可像画布一样定位,支持负坐标、空白区域、拖拽平移与滚轮缩放。
|
|
76
|
-
-
|
|
76
|
+
- **标注**:圆形、矩形、线段、箭头、画笔、文字六种形状,橡皮擦与「选择」「框选」等编辑工具(实时框选,Shift 框选加选 / Alt 减选,选中后有品牌色光晕与包围框,可拖动移动、Shift 约束方向、方向键微调、Delete 删除,详见[标注操作](viewport-control.md#标注));标注锚定画布坐标,模式内页面不接收输入。用户提到画/圈/框/箭头/笔迹等面板标注时,Agent 先读 `browser_state.annotations`,再用 `browser_screenshot {includeAnnotations:true}` 查看 Host 已接受的文档叠加像素;不含未提交草稿与工具栏。`includeAnnotations` 为 boolean,默认 false;默认截图及 T3/T4 原始源不含面板标注,详见[截图与图片交付](capture-p0.md)。
|
|
77
77
|
- **内部标签页**:真人点击 `target=_blank` / `window.open` 时,面板会在地址栏下方新增内部标签并自动切过去,原页面保留为另一个标签;标签栏由「标注」左侧开关控制显隐,单标签时也显示并可新建;`+` 只在标签栏内,工具栏不常驻。Agent 工具默认操作各自会话的 selectedTab(无选择 primary),可用 `browser_tabs` 查看/选择;GUI 切页不改 Agent 选择。自动弹窗与未授权弹窗仍被阻断。
|
|
78
78
|
- **调试工具**:「更多 → 打开调试工具」为当前页面请求一个独立窗口,加载 Chrome 自带的 DevTools(与 F12 等价)。需要当前工作区的浏览器运行时已启动;只有 GUI 与 DSH 同机、且通过 loopback(127.0.0.1/localhost)访问时可用,远程 GUI 暂不支持。弹窗被浏览器拦截时,面板会显示提示和「在新标签页打开调试工具」链接。
|
|
79
79
|
- **共享状态**:面板与 Agent 使用同一 `expectedRevision`,冲突会明确报告而不是静默覆盖。
|
|
80
|
-
- **地址栏**:地址栏右侧的时钟按钮展开「最近访问」下拉,按栈展示最近 7 条已访问的 HTTP(S) 地址(最近的在上;重复访问只置顶不重复;空地址、`about:blank`
|
|
80
|
+
- **地址栏**:地址栏右侧的时钟按钮展开「最近访问」下拉,按栈展示最近 7 条已访问的 HTTP(S) 地址(最近的在上;重复访问只置顶不重复;空地址、`about:blank` 与应用自身地址不记录)。条目点击直接跳到该地址。历史按**工作区隔离**:存进浏览器 `localStorage` 的 `dsh-agent-team-ui-testing:address-history:v2:<工作区作用域 id>`(同一工作区的多个面板共享,不同工作区互不可见),最多 7 条;作用域尚未解析时不读也不写,旧版本共用的 `v1` 历史不会迁移。鼠标点下拉外部或按 <kbd>Esc</kbd> 收起,切换作用域或进入标注模式也会收起。地址栏与标签页按钮之间的 **转到** 按钮等同按 <kbd>Enter</kbd> 提交当前地址(同一套校验与错误提示,标注模式或导航中禁用)。
|
|
81
81
|
|
|
82
82
|
## 设置页
|
|
83
83
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/index.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
| 文档 | 内容 |
|
|
8
8
|
| --- | --- |
|
|
9
|
+
| [新手图文教程](tutorial.md) | 从打开调试视图到让 Agent 完成一次可复核的操作:加载页面、观察、操作、选元素、标注与取证,全部带截图 |
|
|
9
10
|
| [快速开始](getting-started.md) | 安装要求、安装与接入、打开面板与首次调用 |
|
|
10
11
|
| [诊断状态码(中英对照)](diagnose-reason-codes.md) | 诊断页每个状态码的英文机器契约与中文界面文案、出现阶段、动态码族与维护方式 |
|
|
11
12
|
| [工具参考](tools.md) | 37 个工具的参数、返回与错误分类 |
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
| 文档 | 内容 |
|
|
17
18
|
| --- | --- |
|
|
18
19
|
| [多标签页](multi-tab.md) | 页面组按 (workspace, provider, 团队根) 分组、双选择(work/observe)、`browser_tabs` 九动作含队长 acquire/release/transfer、长期归属与控制权、GUI 内部标签栏与 `+` |
|
|
19
|
-
| [视口、画布与标注](viewport-control.md) |
|
|
20
|
+
| [视口、画布与标注](viewport-control.md) | 共享视口、坐标、缩放、拖拽、光标跟随、标注选择/实时框选/键盘操作与并发控制 |
|
|
20
21
|
| [页面右键菜单](panel-context-menu.md) | 页面自绘菜单优先、默认菜单常用操作、可信事件观测与失效边界 |
|
|
21
22
|
| [选元素加入聊天框](element-picker.md) | 面板选元素模式、悬浮框选、文档坐标、`@` 元素引用 chip(显示紧凑、模型文本完整)、原生下拉浮层与绑定写回、降级与限制 |
|
|
22
23
|
| [截图与图片交付](capture-p0.md) | 截图区域、分辨率、includeAnnotations 标注叠加、文件留存与证据边界 |
|
package/docs/tutorial.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 新手图文教程:从打开调试视图到让 Agent 真正动手
|
|
2
|
+
|
|
3
|
+
这篇教程只用**一个本地静态页**演示完整闭环:打开调试视图 → 加载页面 → 让 Agent 看见并操作 → 拿到可复核的证据。全程不需要写代码,也不需要配置模型。
|
|
4
|
+
|
|
5
|
+
> 截图来自一个**只装了本插件**的隔离 DSH 实例(独立 `DSH_HOME`、临时端口、一次性 Chromium),所以画面里没有其它插件的影响。
|
|
6
|
+
|
|
7
|
+
## 0. 前置条件(一次性)
|
|
8
|
+
|
|
9
|
+
1. 已安装 DSH,并且本机有 Chrome / Chromium(插件不自带浏览器)。
|
|
10
|
+
2. 把插件装进要用的 profile,然后**重启一次 DSH**:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
dsh plugin --profile web add dsh-agent-team-ui-testing
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
3. 确认工具面在:随便开一个会话,问 Agent「你现在有哪些 browser_ 工具」,应能列出 37 个(T1 程序化、T2 结构化 GUI、T3 静态视觉、T4 动态行为、网络 P0、多标签页、标注)。
|
|
17
|
+
|
|
18
|
+
## 1. 打开调试视图
|
|
19
|
+
|
|
20
|
+
两个入口,效果相同:
|
|
21
|
+
|
|
22
|
+
- 左侧 **更多 → 调试视图**;
|
|
23
|
+
- 右侧边栏的插件卡片。
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
从上到下依次是:
|
|
28
|
+
|
|
29
|
+
| 区域 | 用途 |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| 顶部一行 | 后退 / 前进 / 刷新、**地址栏**、最近访问、转到、标签页、标注、尺寸调整、选元素、更多 |
|
|
32
|
+
| 标签栏 | 一个标签一个页面;真人点击页面里的 `target=_blank` 会在这里新开一个 |
|
|
33
|
+
| 预览区 | 目标页的实时画面,鼠标键盘都可以直接操作 |
|
|
34
|
+
| 底部状态栏 | 空闲 / Agent 操作中、帧率、帧间隔 |
|
|
35
|
+
|
|
36
|
+
## 2. 在地址栏打开要调试的页面
|
|
37
|
+
|
|
38
|
+
把地址粘进地址栏按 <kbd>Enter</kbd>,或点它右边的 **转到** 按钮(等价于回车)。这里用 `http://127.0.0.1:8199/index.html` 这个演示页。
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
- **红色框 = 最近访问**:点开下拉,按栈展示最近 7 条访问过的地址(最近的在上,重复访问只置顶)。历史**按工作区隔离**,换个工作区就是另一份记录;点任意一条直接跳过去。
|
|
43
|
+
- **蓝色框 = 转到**:等同回车提交地址栏里的内容,校验与报错跟回车完全一致。
|
|
44
|
+
- **橙色框 = 下拉展开后的样子**:标题里的 `3/7` 表示已有 3 条、上限 7 条。
|
|
45
|
+
|
|
46
|
+
页面加载后,预览区就是**真的**那个页面的实时画面:在这里点击、输入、滚轮滚动,页面收到的都是真实事件。
|
|
47
|
+
|
|
48
|
+
## 3. 让 Agent 先「看」,再「动」
|
|
49
|
+
|
|
50
|
+
新手最容易犯的错是让 Agent 直接点。正确顺序是**先观察、再定位、最后动作**,典型对话:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
你:打开 http://127.0.0.1:8199/index.html,看看页面上有哪些控件
|
|
54
|
+
Agent:browser_navigate { url } → browser_snapshot
|
|
55
|
+
(拿到 ref 列表:textbox "订单号" [ref=e2]、button "查询" [ref=e3] …)
|
|
56
|
+
你:在订单号里填 A-1001,然后点查询
|
|
57
|
+
Agent:browser_fill_form { fields: [{ ref: "e2", type: "textbox", value: "A-1001" }] }
|
|
58
|
+
browser_click { ref: "e3" }
|
|
59
|
+
browser_node_state / browser_eval 回读结果
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
三条经验:
|
|
63
|
+
|
|
64
|
+
1. **先 snapshot 拿 ref**:ref 形如 `e2`,每次导航或刷新都会失效,失效就重新 snapshot。
|
|
65
|
+
2. **动作后必须回读**:`browser_click` 返回 `dispatched:true` 只说明事件发出去了,页面是否真的变了要自己再读一次。
|
|
66
|
+
3. **点不动是结论,不是障碍**:元素被遮挡、持续运动、在 iframe 里,工具会明确报 `NOT_INTERACTABLE`,不要换个坐标硬点。
|
|
67
|
+
|
|
68
|
+
## 4. 把元素直接发给 Agent:选元素
|
|
69
|
+
|
|
70
|
+
不知道元素叫什么、又不想手写 selector 时,用工具栏的**选元素**:
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
1. 点工具栏的准星图标进入选元素模式(页面零输入,滚轮仍可滚动);
|
|
75
|
+
2. 鼠标划过预览,被命中的元素会出现蓝框与 `标签#id` 标签;
|
|
76
|
+
3. 点一下,元素信息会作为 `@` 引用塞进聊天框,直接继续提问即可;
|
|
77
|
+
4. <kbd>Esc</kbd> 退出。
|
|
78
|
+
|
|
79
|
+
## 5. 画标注、截图给 Agent
|
|
80
|
+
|
|
81
|
+
需要指位置时别用文字描述——直接画:
|
|
82
|
+
|
|
83
|
+

|
|
84
|
+
|
|
85
|
+
- 最左侧的**选择**与**框选**用来改已画的标注:点选、Shift 点击切换多选,空白处拖框时实时高亮;`Shift` 框选加选、`Alt` 减选、`Shift+Alt` 取交集。选中后拖动整体移动,`Shift` 拖动锁定水平/垂直,`Esc` 取消当前手势,`Delete` 删除。画布获得焦点后,`V` / `M` 切换选择 / 框选,方向键微调(`Shift` 为 10 像素)。选中图形有品牌色光晕和包围框,多选还有整体边界框;底部状态栏在延迟后面显示「已选 N 个」,完整操作见[视口、画布与标注](viewport-control.md#标注);
|
|
86
|
+
- 标注按**画布坐标**锚定,可以画在画面外的空白带上;
|
|
87
|
+
- 标注模式下页面不接收指针与键盘输入,<kbd>Esc</kbd> 退出;
|
|
88
|
+
- 工具条最后的**截图**按钮,会把「当前画面 + 已提交标注」合成一张 PNG **直接放进聊天框**,Agent 立刻能看到你圈的是哪块;
|
|
89
|
+
- Agent 也能反过来读/写这份标注文档(`browser_annotation`),但只有你正在调试视图里看着这个标签页时才允许写。
|
|
90
|
+
|
|
91
|
+
## 6. 需要证据时
|
|
92
|
+
|
|
93
|
+
| 你想要 | 用哪个 |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| 一张可复核的截图 | `browser_screenshot { out: "output/capture/step1.png" }` |
|
|
96
|
+
| 断言颜色/位置/差异 | T3:`browser_vision_image` / `browser_vision_compare` / `browser_vision_check` |
|
|
97
|
+
| 接口为什么 404/500、请求发了几次 | 网络 P0:`browser_network_session start` → `browser_network_events` / `browser_network_detail` |
|
|
98
|
+
| 动画卡不卡、有没有闪烁 | T4:`browser_dynamic_session` → `browser_motion_observe` → `browser_motion_analyze` |
|
|
99
|
+
| 页面变了什么 | `browser_snapshot` 前后对比,`browser_state` 看 URL/标题/视口 |
|
|
100
|
+
|
|
101
|
+
## 7. 常见问题
|
|
102
|
+
|
|
103
|
+
**点了页面没反应?**
|
|
104
|
+
先看工具栏:**标注**、**选元素**、**尺寸调整**三者互斥,任一开启时页面不接收普通输入。<kbd>Esc</kbd> 或再点一次按钮退出。
|
|
105
|
+
|
|
106
|
+
**画面提示「画面同步中,暂时无法操作」?**
|
|
107
|
+
视口刚改过尺寸,面板在等新帧对齐(最长约 1 秒),等下或点「重试同步」。这期间工具会拒绝派发,而不是点到错的位置。
|
|
108
|
+
|
|
109
|
+
**地址栏历史里没有我刚在别的窗口访问的地址?**
|
|
110
|
+
历史按工作区隔离,不同工作区各有一份,这是设计行为。
|
|
111
|
+
|
|
112
|
+
**改了 `client.js` 没生效?**
|
|
113
|
+
面板要刷新一次;改 `index.js`、工具 schema 或内置 Skill 则需要重启 DSH。
|
|
114
|
+
|
|
115
|
+
**面板里看不到原生弹窗(alert / 文件选择器)?**
|
|
116
|
+
它们由浏览器 UI 层绘制,不在页面画面里,面板无法显示也无法操作。
|
|
117
|
+
|
|
118
|
+
**Agent 说页面在「别的标签页」?**
|
|
119
|
+
每个 Agent 会话有自己的选中标签,互不抢占;用 `browser_tabs` 查看和切换,真人切标签不会改变 Agent 的选择。
|
|
120
|
+
|
|
121
|
+
## 下一步
|
|
122
|
+
|
|
123
|
+
- [快速开始](getting-started.md):安装、设置页、环境选择
|
|
124
|
+
- [工具参考](tools.md):37 个工具的参数与错误分类
|
|
125
|
+
- [能力分层与限制](capability-tiers.md):什么时候该用 T1 / T2 / T3 / T4
|
|
126
|
+
- [选元素加入聊天框](element-picker.md)、[视口与标注](viewport-control.md)、[网络调试](network-p0.md)
|
package/docs/verification.md
CHANGED
|
@@ -18,6 +18,7 @@ node tests/acceptance/annotation-capture.mjs # includeAnnotations:六形状
|
|
|
18
18
|
node tests/acceptance/game-target.mjs # 人工靶机 tests/manual-target/game-target.html 的自评在真实浏览器里跑到 8/8
|
|
19
19
|
node tests/acceptance/input-state.mjs # browser_input 状态机:多键按住/修饰键合成、相对鼠标、光标探测
|
|
20
20
|
node --test tests/contracts/panel-cursor.test.mjs # 预览光标:尾沿查询、换帧重试、迟到响应与生命周期失效
|
|
21
|
+
node --test tests/contracts/panel-annotation-selection.test.mjs # 标注移动:同步回复、取消、切页保留与提交边界
|
|
21
22
|
node --test tests/contracts/panel-address-bar.test.mjs # 地址栏历史:栈语义、7 条上限、持久化与接线
|
|
22
23
|
node tests/acceptance/panel-address-gui.mjs # 真实面板:历史下拉顺序/去重/持久化、Esc 关闭与「转到」按钮
|
|
23
24
|
node tests/acceptance/gui-annot-shot.mjs # 面板「截图」:/screenshot 的 includeAnnotations 合成、旧回复形状与拒绝
|
|
@@ -83,6 +84,7 @@ node tests/acceptance/audit-a11-scope.mjs # 会话级环境选择
|
|
|
83
84
|
|
|
84
85
|
```bash
|
|
85
86
|
node tests/acceptance/viewport-gui.mjs # 隔离 DSH + 无头 Chrome 的面板断言
|
|
87
|
+
DSH_VIEWPORT_GUI_ONLY=V16c node tests/acceptance/viewport-gui.mjs # 选择手感:实时框选、组合键、拖动/取消、键盘与缩放命中
|
|
86
88
|
node tests/acceptance/canvas-wheel.mjs # 隔离 DSH + 无头 Chrome 的滚轮消费/命中/A2 瞬态
|
|
87
89
|
node tests/acceptance/popup-tabs.mjs # 隔离 DSH + 无头 Chrome 的内部标签页/target=_blank/关闭回收
|
|
88
90
|
node tests/acceptance/devtools-gui.mjs # 隔离 DSH + 无头 Chrome 的 DevTools 弹窗断言
|
package/docs/viewport-control.md
CHANGED
|
@@ -39,7 +39,11 @@ view = { version, mode, x, y, canvasX, canvasY, width, height, scale, source, re
|
|
|
39
39
|
|
|
40
40
|
## 标注
|
|
41
41
|
|
|
42
|
-
-
|
|
42
|
+
- 工具(从左到右):**选择**、**框选**、圆形、矩形、线段、箭头、画笔、文字、橡皮擦;另有填充/外框、颜色、粗细、**截图**与清除画布。
|
|
43
|
+
- **选择工具**:点击选中指针下最上层的图形;细线命中容差保持约 6 屏幕 CSS px,不随预览缩小而变难点。`Shift` / `Ctrl` / `Command` + 点击切换多选,`Alt` + 点击减选。空白处拖动也能框选。从选中图形的**包围框内任意位置**(含空心矩形内部)拖拽会整体移动,多选时所有选中图形一起移动;框选后也可直接在选框内(含成员之间的空隙)拖动整组。移动达到 4 屏幕 CSS px 才启动;启动后可拖回起点,`Shift` 拖动约束为水平或垂直,松开 `Shift` 恢复自由移动。**抬手时才发布**移动后的文档,`Esc` 取消当前移动。
|
|
44
|
+
- **框选工具**:两种选择工具都可拖出虚线矩形,实时高亮**包围盒与矩形相交**的图形;这是标注对象的包围盒选择。`Shift` 框选追加(已有选中项保持),`Alt` 减选,`Shift+Alt` 取交集,`Ctrl` / `Command` 切换命中项;拖动中可切换组合键,结果始终基于起拖前的集合。`Esc` 恢复框选前的集合。未达到 4 屏幕 CSS px 的空白点击清空选择,带组合键的空白点击保留原选择。
|
|
45
|
+
- **键盘**:标注画布获得焦点时,`V` / `M` 切换选择 / 框选;选择工具下 `Ctrl/Command+A` 全选,`Ctrl/Command+D` 取消选择,方向键移动 1 画布 px,`Shift+方向键` 移动 10 画布 px。`Delete` / `Backspace` 或标注栏「删除选中(N)」删除选中项。输入框中的编辑按键仍属于输入框。无手势时,第一下 `Esc` 清空选择,再按退出标注模式。切回绘制/橡皮擦/文字会清空选择,选择与框选之间切换保留。
|
|
46
|
+
- **选中反馈**:被选图形叠加品牌色加粗光晕、半透明包围框,多选时另有整体边界框;面板**底部状态栏**在延迟(`FPS / ms`)后面显示「已选 N 个」。选中态只属于当前面板:不写 Host 文档、不改图形数据,也不进入 `includeAnnotations` 截图(截图只含已接受的形状)。
|
|
43
47
|
- **截图按钮**(标注栏、紧接「粗细」之后):把**当前页面连同已接受的标注**合成一张 PNG,直接作为附件放进本会话的聊天框(`createDrafts` + `addAttachments`,字节随消息发送,不落盘、不占页面队列之外的东西)。它走 Host 的 `POST /screenshot {includeAnnotations:true}`,与 `browser_screenshot {includeAnnotations:true}` 是**同一条离屏合成路径**,所以像素与证据一致;成功时不弹任何提示(附件缩略图本身就是结果),只有失败才在按钮旁给出具体原因。截图前若还有待发布的笔画会先 flush(≤260ms),避免少一笔;聊天框处于发送中(busy)时按钮报「聊天框正忙」并**立即释放**已注册的附件,不留孤儿。
|
|
44
48
|
- 锚定在**画布坐标**中,可画在空白区域;标注模式下页面不接收任何指针或键盘输入。
|
|
45
49
|
- 标注是独立文档,不进入页面 DOM;默认截图、T3 原始源图与 T4 帧源不含面板标注。`browser_screenshot {includeAnnotations:true}` 可叠加当前目标已提交且经 Host 接受的六种形状(`circle/rect/line/arrow/brush/text`),渲染语义与面板一致。
|
|
@@ -52,7 +56,7 @@ view = { version, mode, x, y, canvasX, canvasY, width, height, scale, source, re
|
|
|
52
56
|
- **软限额与裁剪**:与面板写面相同(`maxShapes` 128、单笔画笔 512 点、文档总点数 8192、文字 200 字符、文档 65536 字节),Host 确定性裁剪并如实回 `truncated` / `truncation`。
|
|
53
57
|
- **不碰页面**:不启动浏览器、不进页面串行队列、不占 single-owner lease、不写页面 `lastError`、不改页面 DOM/CSS;只写 Host 侧文档,面板下一次 `/state` 轮询就会画出来。`includeAnnotations:true` 的截图会把 Agent 画的与人类画的形状一起叠加。
|
|
54
58
|
- 带标注截图与页面共用 `region`/`scale` 映射、裁剪和缩放;不包含未提交草稿、工具栏、选中控件或其它面板 UI,详见[截图与图片交付](capture-p0.md)。
|
|
55
|
-
-
|
|
59
|
+
- **按 Runtime 隔离,也就是每个标签页一份**,不是整个工作区一份:面板在 A 标签画的,Agent 默认目标若在 B 标签(`primary` 与 GUI 弹出的 `child` 是两个 Runtime)就读不到——先 `browser_tabs list` 对 `url`、或比对 `read` 返回的 `context.runtimeId` 与目标 tab 的 `runtimeId`,不一致就 `browser_tabs select` 过去。同一标签页内重挂面板、切换会话保留;导航换文档时清空;不同工作区互不可见。
|
|
56
60
|
- **写面有两处,写的是同一份文档**:面板通过认证的 `POST /plugins/ui-testing/annotations` 提交(带 `clientRevision` 幂等与 `409 annotation-context-stale`),Agent 通过 `browser_annotation` 提交;两者共用 Host 侧软限额(图形数、单笔点数、总点数、文字长度、文档字节数)与确定性裁剪。
|
|
57
61
|
|
|
58
62
|
## 截图比例
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agent-team-ui-testing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Frontend GUI debugging and testing for DeepSeekHarness agents: Web/Chromium is implemented with 37 browser_* tools for structured GUI automation, visual comparison, dynamic frame analysis, annotation read/write and network debugging; Windows/Linux/macOS desktop, Android, TUI, HarmonyOS, mini programs, games and 3D (nine environments) are planned.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"./locale/*.json": "./locale/*.json",
|
|
14
14
|
"./icon": "./icon.png"
|
|
15
15
|
},
|
|
16
|
-
"files": ["index.js", "client.js", "select-control.js", "context-menu.js", "frame-source.js", "frame-push.js", "browser-safety.js", "capture-p0.js", "annotation-capture.js", "vision-t3.js", "vision-baseline.js", "network-p0.js", "dynamic-t4.js", "cordis.patch.yml", "locale/*.json", "icon.png", "banner.png", "banner_zh.png", "docs/*.md", "core/", "targets/", "integration/", "skills/**"],
|
|
16
|
+
"files": ["index.js", "client.js", "select-control.js", "context-menu.js", "frame-source.js", "frame-push.js", "browser-safety.js", "capture-p0.js", "annotation-capture.js", "vision-t3.js", "vision-baseline.js", "network-p0.js", "dynamic-t4.js", "cordis.patch.yml", "locale/*.json", "icon.png", "banner.png", "banner_zh.png", "docs/*.md", "docs/images/", "core/", "targets/", "integration/", "skills/**"],
|
|
17
17
|
"dsh": {
|
|
18
18
|
"bundle": { "patch": "./cordis.patch.yml" },
|
|
19
19
|
"client": { "platform": "web", "immediately": true, "inject": [] }
|
|
@@ -19,8 +19,8 @@ description: 调试与测试已授权 Web 页面的默认入口——下列常
|
|
|
19
19
|
| 截个图、放大看看、和设计稿/上一版对比、这块颜色对不对 | `browser_screenshot` / `vision_image` / `vision_compare` / `vision_baseline` | T3 |
|
|
20
20
|
| 这个动画卡不卡、过渡顺不顺、有没有闪烁、拖拽跟手吗 | `dynamic_session` → `motion_observe/analyze/control` | T4 |
|
|
21
21
|
| 接口返回什么、为什么 404/500、请求发了几次、有没有重复、慢在哪 | `network_session start` → `events`/`detail`/`trace` | 网络 P0 |
|
|
22
|
-
| **看我标注/画的、框的、圈的是这里、这个箭头/笔迹是什么** | **先读 `browser_state.annotations
|
|
23
|
-
| **你圈一下 / 标给我看 / 在这儿写个问号**(要你在他眼前的调试视图上画) |
|
|
22
|
+
| **看我标注/画的、框的、圈的是这里、这个箭头/笔迹是什么** | **先读 `browser_state.annotations`(读到空先 `browser_tabs list` 对齐面板所在标签),再 `browser_screenshot {includeAnnotations:true}`** 查看标注像素,不要问他编号 | 通用标注 |
|
|
23
|
+
| **你圈一下 / 标给我看 / 在这儿写个问号**(要你在他眼前的调试视图上画) | 先 `browser_tabs list` 对齐面板所在标签,再看 `annotations.foreground`;human 选中该标签时用 `browser_annotation {action:"draw"}` | P0-D |
|
|
24
24
|
| 新开了个标签页、弹窗怎么没出来、切到那个标签 | `browser_tabs` list/select/wait | P0-E |
|
|
25
25
|
| 这个环境能用吗、为什么工具不可用、现在跑的是 Chrome 还是 Edge | `browser_capabilities` + 就绪六轴 + `adapter.declaration` | 诊断 |
|
|
26
26
|
| 给我证据、复现一下、留个截图存档 | 证据 envelope + 落盘 PNG(`out`) | 全部 |
|
|
@@ -132,10 +132,10 @@ browser_viewport { "action": "set", "canvasX": 300, "canvasY": 200 } // 画
|
|
|
132
132
|
|
|
133
133
|
### P0-D(1 个,标注读写)
|
|
134
134
|
|
|
135
|
-
`browser_annotation`
|
|
135
|
+
`browser_annotation` 读写调试视图里的**面板标注文档**(**每个标签页一个 Runtime、各持一份**;面板可能正显示另一个标签页,先 `browser_tabs list` 对齐再读写;与面板认证的 `POST /plugins/ui-testing/annotations` 是同一份;权威契约见 `docs/tools.md`、`docs/viewport-control.md`)。参数:`action` 必填,`read`/`clear` 只接受 `action`;`draw` 给 `shapes`(1–64,**追加**不是替换);`erase` 给 `ids`(1–64)和/或 `point{x,y,radius?}`(默认半径 8 画布 px);写动作可选 `expectRevision`(与当前文档 revision 不同则 `ANNOTATION_REVISION_CONFLICT`,零写入)。`read` 与写后返回同一形状:`revision/shapes/shapeCount/truncated/truncation/foreground`。
|
|
136
136
|
- 形状:`type` ∈ `circle|rect|line|arrow|brush|text`(面板的圆形/矩形/线段/箭头/画笔/文字);`id` 可省略(Host 续分配 `a<N>`);`color` `#rrggbb`(默认 `#ff3b30`);`strokeWidth` 1–20(默认 3,即「粗细」);`style` ∈ `stroke|fill`(「外框/填充」,仅 `circle`/`rect`;`text` 固定 fill、`line|arrow|brush` 固定 stroke;也可给 `fill`/`stroke` 布尔但不可与 `style` 同给);几何 `rect{x,y,width,height}`、`circle{cx,cy,rx,ry}`、`line|arrow{x1,y1,x2,y2}`(head 由 Host 派生)、`brush{points:[[x,y],…]}`、`text{x,y,text,fontSize?=20}`。
|
|
137
137
|
- **前台硬约束**:`draw`/`erase`/`clear` 只在目标标签页**正被人类在调试视图里选中且可见**时才允许(面板在认证请求上带前台心跳,约 1.5s 新鲜窗口;切走标签、关面板、DSH 标签页后台化都会过期),否则**零写入**并报 `ANNOTATION_NOT_FOREGROUND`;先读 `browser_state.annotations.foreground={active,ageMs,maxAgeMs}`,`read` 不受此限。页面未运行时报 `INVALID_ARGUMENT`(reason `annotation-runtime-not-running`)。
|
|
138
|
-
- **整份替换语义**:人类下一次编辑会整体发布自己的形状列表(其中已含 Agent 形状,因为面板采纳 Host 文档),人类「清除画布」会连 Agent
|
|
138
|
+
- **整份替换语义**:人类下一次编辑会整体发布自己的形状列表(其中已含 Agent 形状,因为面板采纳 Host 文档),人类「清除画布」会连 Agent 形状一起清掉——别把标注当持久存储。面板的「选择」「框选」只改人类本地选中态(光晕/包围框/「已选 N 个」),移动或删除才写同一份文档;选中态不出现在 `annotations` 里,也不进带标注截图。
|
|
139
139
|
- **限额与边界**:与面板写面同一软限额(128 图形/单笔 512 点/8192 点/200 字符/65536 字节,确定性裁剪并报 `truncated`);不启动浏览器、不进页面队列、不占租约、不写页面 `lastError`、不改 DOM/CSS,面板下一次 `/state` 轮询即画出;`browser_screenshot {includeAnnotations:true}` 会把两方的形状一起叠加。
|
|
140
140
|
|
|
141
141
|
### T2(7 个,结构化 GUI)
|
|
@@ -491,7 +491,7 @@ browser_http_request {
|
|
|
491
491
|
|
|
492
492
|
- **入口**:`browser_state()` 顶层 `annotations`(与已认证 `/state` 的 `ui.annotations` 同源,含 `foreground` 前台心跳);`browser_annotation {action:"read"}` 读同一份文档;`browser_capabilities().annotations` 给读取方式/`space`/`limits`。`browser_screenshot` 的 `includeAnnotations?:boolean=false` 只控制本次截图叠加。默认截图、T3 原始源与 T4 两种帧源不含面板标注;T3 `annotations` 是独立的图片后处理参数。
|
|
493
493
|
- **叠加边界**:`includeAnnotations:true` 仅绘制当前目标已提交且经 Host 接受的 `circle/rect/line/arrow/brush/text`,颜色、粗细与填充/外框遵循面板语义;不含未提交草稿、工具栏或选中控件。图形与页面共用 region/scale 映射,截图连续像素坐标 `u=(d−region.origin)/mapping.cssPerPixel`(逐轴);用 `capture.annotations` 核对 revision/context、新鲜度、截断与 `source.trusted=false`,不能把旧文档当最新画面。`capture.canvas.composite` 描述画布合成,不能单凭它判断是否叠加标注。
|
|
494
|
-
- **反向:给他画**。用户说「你圈一下 / 标给我看 / 在这儿写个问号」时用 `browser_annotation
|
|
494
|
+
- **反向:给他画**。用户说「你圈一下 / 标给我看 / 在这儿写个问号」时用 `browser_annotation`:先确认目标标签页就是面板在看的那个(`browser_tabs list` 对 `url`,或比对 `read` 的 `context.runtimeId` 与 tab 的 `runtimeId`),再看 `browser_state.annotations.foreground.active`,为 false 就先请他选中那个标签页并保持面板可见,否则写入会被 `ANNOTATION_NOT_FOREGROUND` 拒绝(画了看不见等于没画)。`draw` 只追加,形状 id 交给 Host 分配;写完用 `browser_screenshot {includeAnnotations:true}` 复核自己画的位置对不对;对方「清除画布」会连你的形状一起清掉。
|
|
495
495
|
- **坐标**:shapes 是画布 CSS px `d`,页面坐标 `p = d − S`(`S` 用**当前** `view.x/y`,不能用发布时的 `annotations.view`);`scale`/DPR 不参与。
|
|
496
496
|
- **图形**:`rect/line/arrow`(箭头尖为 `(x2,y2)`)、`circle`(PS 包围盒椭圆 `cx/cy/rx/ry`)、`brush`(只有 `points`)、`text`(唯一带原文)。
|
|
497
497
|
- **手写笔迹**:`brush` 结构化数据只有点集,`text.text` 才有文字原文;先查看带标注截图中的实际笔迹,无法可靠辨认时如实说明,不从点集猜字或伪造原文。
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- `browser_capabilities()` 的 `annotations` 段声明读取方式、`space`(恒为 `canvas-css-px`)与 `limits`;**工具面是 37 个已注册的 `browser_*`(当前 Web 环境注册并准入的那些)**。读取结构化标注既可以用 `browser_state` 的一个字段,也可以用 `browser_annotation {action:"read"}`(同一份文档,返回 `revision/shapes/shapeCount/truncated/truncation/foreground`)。
|
|
9
9
|
- `browser_screenshot {includeAnnotations:true}` 叠加当前目标已提交且经 Host 接受的六种形状,渲染与面板的颜色、粗细、填充/外框语义一致;不包含未提交草稿、工具栏、选中控件或其它面板 UI。
|
|
10
10
|
- `includeAnnotations?:boolean=false` 默认关闭。默认截图、T3 原始源与 T4 的 screencast/screenshot-loop 帧源均不含面板标注;默认图里没有线不能说明用户没画。`capture.canvas.composite` 仅说明画布合成,标注叠加看 `capture.annotations`;T3 的 `annotations` 参数是独立的图片后处理标记。
|
|
11
|
+
- 面板的「选择」「框选」是**人类侧编辑工具**:只改本地面板选中态(品牌色光晕、包围框、底部状态栏的「已选 N 个」),拖动移动或删除才改同一份文档;选中态不写文档、不进入 `annotations` 读取结果,也不进带标注截图。不要从标注文档推断「当前选中了哪几个」。
|
|
11
12
|
|
|
12
13
|
## 2. 反向:给人类画标注(`browser_annotation`)
|
|
13
14
|
|
|
@@ -74,8 +75,10 @@ annotations = {
|
|
|
74
75
|
|
|
75
76
|
## 8. 生命周期与隔离(v3)
|
|
76
77
|
|
|
77
|
-
- 文档按 `documentKey`
|
|
78
|
+
- 文档按 `documentKey` 绑定:**导航/刷新/换文档会清空**;重挂面板、切换会话**保留**(客户端按文档身份水合)。
|
|
79
|
+
- **按 Runtime 隔离,也就是每个标签页一份**,不是「整个工作区一份」。面板在 A 标签画的,与 Agent 打 B 标签读到的,是两份不同文档;「切页签仍保留」指的是那几个标签各自持有自己的文档,不是共享一份。
|
|
78
80
|
- **按工作区隔离**:不同工作区各有一份,互不串;读取时用当前会话的 `browser_state` 即可,不要跨工作区拼装。
|
|
81
|
+
- 所以「`shapes:[]` / `revision 0` / `staleReason:"not-running"` / `foreground.active:false`」有两种可能:面板确实没开,**或者面板在看另一个标签页**。先用 §10 的对齐步骤排除后者,再请用户配合,不要把两种情况混成「用户没画」。
|
|
79
82
|
- `stale:true`(`panel-unseen`)表示来源面板心跳过期,**不代表标注不存在或已删除**:形状照常可读,如实说明"可能不是最新"即可;不得伪造心跳或 revision。
|
|
80
83
|
- 显式「清除画布」会让 `shapes` 变空(`revision` 递增),不要把它当成"读取失败"。
|
|
81
84
|
|
|
@@ -97,6 +100,9 @@ annotations = {
|
|
|
97
100
|
| 按 `scale` 缩放页面输入坐标 | 页面输入按 `p=d−S`;截图像素另按 region 与 `mapping.cssPerPixel` 换算 |
|
|
98
101
|
| 把箭头 `(x1,y1)` 当尖 | 尖端是 `(x2,y2)` |
|
|
99
102
|
| 把 `stale` 当"数据没了" | 只是心跳过期,形状仍可读 |
|
|
103
|
+
| 读到 `shapes:[]` / `revision 0` / `not-running` 就断定「用户没画」或「面板没开」 | 标注文档按 Runtime(每个标签页)一份。先 `browser_tabs list` 对 `url`(面板地址栏)、把 `read` 的 `context.runtimeId` 与目标 tab 的 `runtimeId` 比对;不一致就 `browser_tabs select {tabId}` 过去再读 |
|
|
104
|
+
| `foreground.active:false` 就断定「用户没打开面板」 | 先确认 Agent 目标标签就是面板显示的标签(上一行);`foreground.viewId` 是该 tabId(runtime 活着时才有值),对得上再谈心跳与 1.5s 窗口 |
|
|
105
|
+
| 换到别的标签就以为标注「丢了」或被清空 | 不同标签是不同文档;切回原标签,形状与 `revision` 都还在。真正清空只有导航/刷新换文档或「清除画布」 |
|
|
100
106
|
|
|
101
107
|
## 11. 参考
|
|
102
108
|
|