agent-gavel 0.1.0__tar.gz
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.
- agent_gavel-0.1.0/.gitignore +24 -0
- agent_gavel-0.1.0/AGENTS.md +39 -0
- agent_gavel-0.1.0/LICENSE +21 -0
- agent_gavel-0.1.0/PKG-INFO +226 -0
- agent_gavel-0.1.0/README.md +208 -0
- agent_gavel-0.1.0/agent_gavel/__init__.py +0 -0
- agent_gavel-0.1.0/agent_gavel/browser_manager.py +265 -0
- agent_gavel-0.1.0/agent_gavel/channels/__init__.py +0 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/__init__.py +0 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/adapter.py +376 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/catalog.py +81 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/catalog_data.py +174 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/diff.py +91 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/normalize.py +108 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/server.py +652 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/templates/calc_add.json +48 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/templates/wechat.json +40 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/templates/wechat_delete.json +41 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/templates.py +133 -0
- agent_gavel-0.1.0/agent_gavel/channels/desktop/wait.py +64 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/__init__.py +0 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/adapter.py +583 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/server.py +310 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/baidu.json +51 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/baike_search.json +52 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/bing_search.json +56 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/cnblogs_search.json +51 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/douban_movie_search.json +52 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/google.json +54 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/runoob_search.json +23 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates/zhihu_login.json +69 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/templates.py +274 -0
- agent_gavel-0.1.0/agent_gavel/channels/dom/verify.py +393 -0
- agent_gavel-0.1.0/agent_gavel/main.py +75 -0
- agent_gavel-0.1.0/docs/internal-beta.md +184 -0
- agent_gavel-0.1.0/docs/roadmap.md +80 -0
- agent_gavel-0.1.0/docs/wechat-perf-optimization.md +136 -0
- agent_gavel-0.1.0/pyproject.toml +50 -0
- agent_gavel-0.1.0/run-mcp.sh +19 -0
- agent_gavel-0.1.0/tests/browser_manager_smoke.py +119 -0
- agent_gavel-0.1.0/third_party/computer-use-linux/README.md +78 -0
- agent_gavel-0.1.0/third_party/computer-use-linux/fast_app_filter.patch +193 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
*.txt
|
|
12
|
+
|
|
13
|
+
# Runtime debug call logs (debug=1 dumps JSON per call)
|
|
14
|
+
logs/
|
|
15
|
+
|
|
16
|
+
# Template runtime stats (consecutive-fail tracking, regenerated on run)
|
|
17
|
+
templates/stats.json
|
|
18
|
+
|
|
19
|
+
# Python cache / build
|
|
20
|
+
__pycache__/
|
|
21
|
+
*.py[oc]
|
|
22
|
+
|
|
23
|
+
# Optimized computer-use-linux binary (build locally from third_party patch)
|
|
24
|
+
bin/computer-use-linux-fast
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# agent-gavel 开发与测试约定
|
|
2
|
+
|
|
3
|
+
## 工作原则(最重要)
|
|
4
|
+
|
|
5
|
+
**陌生环境先探索,再正式执行。** 面对一个没验证过的应用/界面/操作:
|
|
6
|
+
1. 先做充分的一步步探索(读树、试原子操作、确认每个前置条件)
|
|
7
|
+
2. 确认每个步骤真的可行后,再把它组合成"正式"流程/模板/批量执行
|
|
8
|
+
|
|
9
|
+
**不要假设能一次跑通。** 曾经踩过的坑(真实案例):
|
|
10
|
+
- 微信删除消息"写死坐标"右键:坐标随消息内容/滚动微变,一次成功一次脱靶
|
|
11
|
+
- 计算器 `press_key "+"`:computer-use-linux 不认 `+` 键(需 Shift+= 或 KP 键)
|
|
12
|
+
- 计算器 `C` 键:在表达式输入框里把 `c` 当字符打进去,不是清屏
|
|
13
|
+
- GNOME 计算器按钮 AT-SPI bounds 全为 0,0(相对坐标缺失),label 是按钮文本非显示区
|
|
14
|
+
- 每次遇到新 app,显示区/输入焦点/可点区域都要实测确认,不能凭想当然
|
|
15
|
+
|
|
16
|
+
## 测试安全红线
|
|
17
|
+
|
|
18
|
+
- 微信等社交应用:**只用文件传输助手**,绝不碰真实联系人/会话
|
|
19
|
+
- 破坏性操作(删除/发送/覆盖)前先确认目标,测试残留要清理
|
|
20
|
+
|
|
21
|
+
## 性能与优化
|
|
22
|
+
|
|
23
|
+
- agent-gavel 默认走优化版 computer-use-linux(`COMPUTER_USE_LINUX_BIN` + `AGENT_GAVEL_FAST_APP_FILTER`),见 `third_party/computer-use-linux/README.md`
|
|
24
|
+
- `act_and_verify` 只在 `debug=1` 且 ambiguous 时截图;常规调用不触发 portal 截屏
|
|
25
|
+
|
|
26
|
+
## 代码约定
|
|
27
|
+
|
|
28
|
+
- 桌面模板存 `~/.config/agent-gavel/desktop_templates/*.json`(用户保存)或包内
|
|
29
|
+
`agent_gavel/channels/desktop/templates/`(随包自带),支持 `locate` 动态定位
|
|
30
|
+
(读树算坐标,勿写死)
|
|
31
|
+
- 坐标类操作优先动态定位(`locate`),不要硬编码屏幕坐标
|
|
32
|
+
|
|
33
|
+
## Shell 陷阱(真实踩过)
|
|
34
|
+
|
|
35
|
+
- **`pkill -f <pattern>` 会杀掉执行它的 bash 自己**:bash 命令行里含该 pattern,
|
|
36
|
+
pkill 匹配自身进程链 → opencode 终端会话卡住直到超时。
|
|
37
|
+
正确写法:`pkill -f "[g]nome-calculator"`(拆字符让模式匹配不到自身)
|
|
38
|
+
- 进程名 >15 字符时 `pkill -x` 会拒绝(comm 截断),此时用拆字符的 `-f`
|
|
39
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agent-gavel contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agent-gavel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 验证驱动的多端操作框架:动作发出去,程序断言判成败,省掉一次模型往返
|
|
5
|
+
Project-URL: Homepage, https://github.com/Rottenwooood/agent-gavel
|
|
6
|
+
Project-URL: Repository, https://github.com/Rottenwooood/agent-gavel
|
|
7
|
+
Author: Rottenwooood
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agent,atspi,automation,browser,cdp,dom,mcp,web
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.13
|
|
15
|
+
Requires-Dist: mcp[cli]>=2.1.1
|
|
16
|
+
Requires-Dist: websockets>=17.1
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
<div align="center">
|
|
20
|
+
|
|
21
|
+
# agent-gavel
|
|
22
|
+
|
|
23
|
+
**AI 操作浏览器/桌面,动作发出后由程序断言判成败,省掉一次"把页面喂回模型判断"的往返。**
|
|
24
|
+
|
|
25
|
+
 
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
## 这是什么
|
|
32
|
+
|
|
33
|
+
agent-gavel 是一个给 AI 用的 MCP server(stdio 模式),提供"操作网页 / 桌面 + 程序化验证"。
|
|
34
|
+
|
|
35
|
+
典型的浏览器 agent 循环是:动作 → 页面快照喂回模型 → 模型判断成败 → 下一步。agent-gavel 改成:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
AI 声明动作 + "做完后页面应该长什么样" → 执行 → 程序断言 → 返回 pass/fail + 实际值
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
成败由程序判定,模型不用回头"看"一遍页面。省掉每次动作后的一次模型往返(慢 + 费 token + 靠"看"容易漏)。
|
|
42
|
+
|
|
43
|
+
**两个通道,可独立安装:**
|
|
44
|
+
|
|
45
|
+
| 通道 | 干什么 | 需要什么 |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| **DOM**(网页,主通道) | 通过 Chrome CDP 操作真实浏览器:填表 / 点击 / 搜索 / 登录,全部 `isTrusted=true` 真实输入 | 本机 Chrome + Python 3.13,纯 Python 依赖 |
|
|
48
|
+
| **AT-SPI**(桌面,可选) | 通过无障碍树操作桌面应用 | 额外 `npm i -g computer-use-linux` |
|
|
49
|
+
|
|
50
|
+
不装 computer-use-linux 也能用 DOM;装了才解锁桌面工具(不装时桌面工具返回 `atspi_unavailable` 的明确提示)。
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
**兼容性(诚实说明)**:Linux + Python 3.13 验证过,需本机有 Chrome/Chromium。Windows/macOS 未适配(见文末 TODO)。
|
|
55
|
+
|
|
56
|
+
三种安装方式,按场景选:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
# ① 一次性运行(不装任何东西,临时缓存即装即跑)——适合"先试试"
|
|
60
|
+
uvx agent-gavel
|
|
61
|
+
|
|
62
|
+
# ② 全局安装(推荐正式用)——命令装进 ~/.local/bin,全局 PATH 可用
|
|
63
|
+
uv tool install agent-gavel
|
|
64
|
+
|
|
65
|
+
# ③ 装进当前 Python 环境(项目 venv / conda env)
|
|
66
|
+
pip install agent-gavel
|
|
67
|
+
|
|
68
|
+
# 桌面操作(可选):不装则 DOM 照常可用,只是桌面工具返回 atspi_unavailable
|
|
69
|
+
npm install -g computer-use-linux
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
装好后在 MCP 客户端(见下)里配置 `["uvx", "agent-gavel"]`(方式①)或 `["agent-gavel"]`(方式②③,命令已在 PATH),重启后 `doctor` 工具会报告 DOM / AT-SPI 双通道状态——这就是安装成功的信号。
|
|
73
|
+
|
|
74
|
+
### 开发者:clone 源码运行
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
git clone https://github.com/Rottenwooood/agent-gavel.git
|
|
78
|
+
cd agent-gavel
|
|
79
|
+
uv sync # 装依赖(Python 3.13)
|
|
80
|
+
uv run python3 -m agent_gavel.main # 起 MCP server(等价 ./run-mcp.sh)
|
|
81
|
+
uv run python3 tests/browser_manager_smoke.py # Chrome 生命周期冒烟测试
|
|
82
|
+
uv build # 本地构建 wheel/sdist
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
源码跑通后,想贡献你验证过的模板 → 见文末"贡献你验证过的模板"。
|
|
86
|
+
|
|
87
|
+
## 安装后到底发生了什么(流程说明)
|
|
88
|
+
|
|
89
|
+
### 三种安装方式的区别
|
|
90
|
+
|
|
91
|
+
**`uvx agent-gavel`** —— 一次性运行,不装进任何环境:
|
|
92
|
+
- uvx 在 `~/.cache/uv` 建**临时虚拟环境**装包,跑完即弃(缓存留档,下次秒起)
|
|
93
|
+
- 适合"先试试",不污染你的 Python;代价是每次 `uvx` 首次要解析依赖
|
|
94
|
+
|
|
95
|
+
**`uv tool install agent-gavel`** —— 全局安装(推荐正式用):
|
|
96
|
+
- uv 把 agent-gavel 装进 `~/.local/share/uv/tools/` 的独立环境
|
|
97
|
+
- 可执行命令 `agent-gavel` 链接到 `~/.local/bin/`(已在你的 PATH 里)
|
|
98
|
+
- 任何目录都能直接 `agent-gavel` 起 server,类似 `npm i -g`
|
|
99
|
+
|
|
100
|
+
**`pip install agent-gavel`** —— 装进当前 Python 环境(项目 venv / conda env):
|
|
101
|
+
- `agent_gavel/` 包落到 `<venv>/lib/python3.13/site-packages/`
|
|
102
|
+
- 同时生成可执行命令 `agent-gavel`(指向 `agent_gavel.main:main`),在所在环境 PATH 里
|
|
103
|
+
|
|
104
|
+
三种方式最终效果一致:**启动一个在 stdio 上说话的 MCP server 进程**,等 MCP 客户端连它。区别只在命令装在哪、是否全局可用。
|
|
105
|
+
|
|
106
|
+
### 怎么接到 opencode
|
|
107
|
+
|
|
108
|
+
opencode 通过 `command` 数组拉起这个进程,两者用 stdio 通信:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
// ~/.config/opencode/opencode.json
|
|
112
|
+
{
|
|
113
|
+
"mcp": {
|
|
114
|
+
"agent-gavel": {
|
|
115
|
+
"type": "local",
|
|
116
|
+
"command": ["uvx", "agent-gavel"], // 一次性
|
|
117
|
+
// 或 ["agent-gavel"] // uv tool install 或 pip install 后(命令已在 PATH)
|
|
118
|
+
"enabled": true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
重启 opencode,工具列表出现 `agent-gavel_dom_*` 系列。**无需手动开 Chrome**——首次 DOM 调用时 server 自动用独立 profile 拉起可见窗口的调试 Chrome,崩溃自动重拉,退出自动清理。
|
|
125
|
+
|
|
126
|
+
### 模板存在哪
|
|
127
|
+
|
|
128
|
+
- **随包模板**:安装自带的模板在 `site-packages/agent_gavel/channels/{dom,desktop}/templates/`(只读默认,如百度/必应/豆瓣等 8 个验证过的)
|
|
129
|
+
- **你的模板**:`dom_save_template` / `desktop_save_template` 保存到你自己的用户目录 `~/.config/agent-gavel/{templates,desktop_templates}/`——跨 uvx 缓存、跨安装版本持久存在,不会被升级覆盖
|
|
130
|
+
- 读取时**用户目录优先**:你保存的同名模板覆盖自带模板;失效检测记录(stats)也存用户目录
|
|
131
|
+
|
|
132
|
+
## 实测耗时(优化前后对比)
|
|
133
|
+
|
|
134
|
+
### DOM 通道:固定等待 → 断言轮询
|
|
135
|
+
|
|
136
|
+
早期版本每个动作后固定 `sleep 3s` 再断言——`set_value` 这种立即生效的动作也白等 3s。改成动作后直接轮询断言(0.25s 间隔,满足即返)后,模板总耗时降 2.5–5.3x:
|
|
137
|
+
|
|
138
|
+
| 模板 | 优化前总耗时 | 优化后总耗时 | 提速 |
|
|
139
|
+
|---|---|---|---|
|
|
140
|
+
| baidu 搜索 | 13.8s | **4.3s** | 3.2x |
|
|
141
|
+
| baike 搜索 | 14.1s | **3.2s** | 4.4x |
|
|
142
|
+
| bing 搜索 | 13.8s | **3.3s** | 4.2x |
|
|
143
|
+
| douban 电影搜索 | 13.7s | **3.3s** | 4.2x |
|
|
144
|
+
| zhihu 登录填表 | 16.8s | **3.2s** | 5.3x |
|
|
145
|
+
| runoob 站内搜 | 7.6s | **3.0s** | 2.5x |
|
|
146
|
+
|
|
147
|
+
剩余耗时基本是 `navigate` 单步(~3.1s,页面真实加载,省不掉)。动作步本身:`set_value` 5–25ms,`click / enter` 100–1200ms。全部模板 pass,无回归。
|
|
148
|
+
|
|
149
|
+
### AT-SPI 桌面通道:computer-use-linux 优化补丁
|
|
150
|
+
|
|
151
|
+
给上游 computer-use-linux 打补丁(`third_party/` 保存):AT-SPI 连接复用 + doctor 缓存 + `fast_app_filter` 跳过全桌面 pid 反查 + 坐标操作不再触发 portal 截屏。桌面 70 节点应用实测:
|
|
152
|
+
|
|
153
|
+
| 阶段 | 原版 | 优化后(fast=true) |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| doctor_report | ~150ms | ~0ms(缓存) |
|
|
156
|
+
| app_filter | ~280ms | ~0ms(按 pid 直选) |
|
|
157
|
+
| snapshot_tree | ~145ms | ~140ms |
|
|
158
|
+
| **合计/次读树** | **~630ms** | **~220ms**(2.9x) |
|
|
159
|
+
|
|
160
|
+
agent-gavel 端到端:`read_state` 620→235ms(2.6x);`act_and_verify` 单次闭环 ~1.5s→0.65s(2.3x)。微信发消息模板整条流程 6.8s→4.8s。树内容与动作结果和原版一致,无回归。
|
|
161
|
+
|
|
162
|
+
## 功能一览
|
|
163
|
+
|
|
164
|
+
### DOM(网页)
|
|
165
|
+
|
|
166
|
+
- **Chrome 自管**:首次调用自动起独立 profile 调试 Chrome(可见窗口,永不用 headless),崩溃自愈,退出清理
|
|
167
|
+
- **`dom_step`**:通用单步闭环(动作 + 选择器 + 断言一次调用),`navigate / set_value / click / press_enter / clear / focus`
|
|
168
|
+
- **`dom_explore`**:枚举页面可交互元素,给验证过唯一的锚点(`#id` / `input[name=q]` / `__text__:登录` / 同名按钮用 `__text_nth__:N::`)
|
|
169
|
+
- **模板复用**:跑通的流程存 JSON(`templates/`,按网站组织:`site` 纯站名,文件名 `site_功能.json`),换参数直接跑
|
|
170
|
+
- **失败诊断**:环境错误(Chrome 没起 / DISPLAY 缺失 / CDP 断)返回 `reason + hint`,不会让 agent 对着一个 "Error executing tool" 猜
|
|
171
|
+
- **断言降级重试**:fail 自动换策略(trusted 翻转 → 重新 explore 换锚点 → 滚动 → 切换等待模式);`strict` 参数关掉降级暴露真实 fail(写模板/排查时用)
|
|
172
|
+
- **模板失效检测**:连续失败 ≥3 次标 suspected,再跑返回 warning 建议重新探索;任何一次 pass 清零
|
|
173
|
+
|
|
174
|
+
### AT-SPI(桌面,可选)
|
|
175
|
+
|
|
176
|
+
- `act_and_verify` / `run_operation` / 桌面模板,经 computer-use-linux 无障碍树操作桌面应用
|
|
177
|
+
- 默认走优化补丁版(`bin/computer-use-linux-fast`,连接复用 + fast_app_filter)
|
|
178
|
+
|
|
179
|
+
### 验证机制(两个通道共用)
|
|
180
|
+
|
|
181
|
+
- 断言:`eq / neq / exists / not_exists / contains`(特征用 JS 表达式提取)
|
|
182
|
+
- 等待:`poll`(轮询断言)/ `event`(MutationObserver,DOM 一变即醒,适合异步长等待)
|
|
183
|
+
- 每动作返回 `cost.phase` 毫秒级拆分(before_read / action / wait / after_verify),性能可观测
|
|
184
|
+
|
|
185
|
+
## TODO
|
|
186
|
+
|
|
187
|
+
"可用"和"正式发布"之间的差距:
|
|
188
|
+
|
|
189
|
+
- [ ] **适配 Windows**:AT-SPI 桌面通道是 Linux 无障碍树,Windows 应走 UI Automation 或对应后端;DOM 通道理论上跨平台但只在 Linux 验证过
|
|
190
|
+
- [ ] **完善模板共享机制**:当前模板存本地用户目录,缺少"模板共享/导入"通道(如按站点从远端拉模板、版本化、社区模板源)
|
|
191
|
+
- [ ] **登录态模板**:Chrome profile 登录态保留,覆盖真实登录类流程
|
|
192
|
+
- [ ] **多步骤 / 分页 / 滚动模板**:现有模板多是"导航+填+提交",缺连续点进详情、无限滚动、多 tab
|
|
193
|
+
- [ ] **断言语言增强**:`eq/neq/exists/contains` 之外,补数值比较 / 正则 / 列表断言(结果条数等)
|
|
194
|
+
- [ ] **权限 / 确认机制**:高危操作(提交表单 / 发送)前人工确认
|
|
195
|
+
- [ ] **可观测性**:debug 日志之上,补任务级 trace / 会话重放
|
|
196
|
+
|
|
197
|
+
## 贡献你验证过的模板(PR template)
|
|
198
|
+
|
|
199
|
+
agent-gavel 的模板按网站组织(`site` 纯站名,文件名 `site_功能.json`),随包带 8 个验证过的。你在一台机器上跑通了新网站的流程,**PR 给我**,合并后所有用户随包可用。
|
|
200
|
+
|
|
201
|
+
仓库内的验证过的模板:百度 / 百度百科 / 必应 / 博客园 / 豆瓣电影 / Google / 菜鸟教程 / 知乎登录填表。
|
|
202
|
+
设计说明见 [docs/internal-beta.md](docs/internal-beta.md),路线见 [docs/roadmap.md](docs/roadmap.md)。
|
|
203
|
+
|
|
204
|
+
### 模板去哪、怎么存
|
|
205
|
+
|
|
206
|
+
模板默认读**用户目录**优先(`~/.config/agent-gavel/{templates,desktop_templates}/`),随包模板在 `agent_gavel/channels/{dom,desktop}/templates/`。
|
|
207
|
+
|
|
208
|
+
贡献模板的路径:源码 clone → 用 `dom_explore` + `dom_step` 现场探索跑通 → `dom_save_template` 存 JSON → 确认稳定后放进仓库对应目录提 PR。
|
|
209
|
+
|
|
210
|
+
### 模板 PR 检查清单
|
|
211
|
+
|
|
212
|
+
模板 PR 要能直接合并,请过一遍:
|
|
213
|
+
|
|
214
|
+
- [ ] 模板 JSON 在 `agent_gavel/channels/dom/templates/<site>_<func>.json`(或 desktop 对应目录)
|
|
215
|
+
- [ ] `site`(DOM)/ `app`(desktop)字段是纯站名,不含功能名;文件名 `站名_功能`
|
|
216
|
+
- [ ] 真实跑通过(`dom_run_template` / `desktop_run_template` 全 pass),PR 描述里贴结果
|
|
217
|
+
- [ ] 步骤含断言(`page_features` + `expected_feature`),不是只发动作不验证
|
|
218
|
+
- [ ] 用了稳定锚点(`#id` / `input[name=x]` / `__text__:`),没有写死易变的 CSS 路径
|
|
219
|
+
- [ ] 涉及登录/个人数据时用假凭据,PR 里说明依赖的登录态
|
|
220
|
+
- [ ] 描述里写清:站点 URL、功能、测过的关键词/参数
|
|
221
|
+
|
|
222
|
+
模板存疑或失效会走失效检测(连续失败 ≥3 次标 suspected),无需担心一次不完美。
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# agent-gavel
|
|
4
|
+
|
|
5
|
+
**AI 操作浏览器/桌面,动作发出后由程序断言判成败,省掉一次"把页面喂回模型判断"的往返。**
|
|
6
|
+
|
|
7
|
+
 
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
## 这是什么
|
|
14
|
+
|
|
15
|
+
agent-gavel 是一个给 AI 用的 MCP server(stdio 模式),提供"操作网页 / 桌面 + 程序化验证"。
|
|
16
|
+
|
|
17
|
+
典型的浏览器 agent 循环是:动作 → 页面快照喂回模型 → 模型判断成败 → 下一步。agent-gavel 改成:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
AI 声明动作 + "做完后页面应该长什么样" → 执行 → 程序断言 → 返回 pass/fail + 实际值
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
成败由程序判定,模型不用回头"看"一遍页面。省掉每次动作后的一次模型往返(慢 + 费 token + 靠"看"容易漏)。
|
|
24
|
+
|
|
25
|
+
**两个通道,可独立安装:**
|
|
26
|
+
|
|
27
|
+
| 通道 | 干什么 | 需要什么 |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| **DOM**(网页,主通道) | 通过 Chrome CDP 操作真实浏览器:填表 / 点击 / 搜索 / 登录,全部 `isTrusted=true` 真实输入 | 本机 Chrome + Python 3.13,纯 Python 依赖 |
|
|
30
|
+
| **AT-SPI**(桌面,可选) | 通过无障碍树操作桌面应用 | 额外 `npm i -g computer-use-linux` |
|
|
31
|
+
|
|
32
|
+
不装 computer-use-linux 也能用 DOM;装了才解锁桌面工具(不装时桌面工具返回 `atspi_unavailable` 的明确提示)。
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
**兼容性(诚实说明)**:Linux + Python 3.13 验证过,需本机有 Chrome/Chromium。Windows/macOS 未适配(见文末 TODO)。
|
|
37
|
+
|
|
38
|
+
三种安装方式,按场景选:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
# ① 一次性运行(不装任何东西,临时缓存即装即跑)——适合"先试试"
|
|
42
|
+
uvx agent-gavel
|
|
43
|
+
|
|
44
|
+
# ② 全局安装(推荐正式用)——命令装进 ~/.local/bin,全局 PATH 可用
|
|
45
|
+
uv tool install agent-gavel
|
|
46
|
+
|
|
47
|
+
# ③ 装进当前 Python 环境(项目 venv / conda env)
|
|
48
|
+
pip install agent-gavel
|
|
49
|
+
|
|
50
|
+
# 桌面操作(可选):不装则 DOM 照常可用,只是桌面工具返回 atspi_unavailable
|
|
51
|
+
npm install -g computer-use-linux
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
装好后在 MCP 客户端(见下)里配置 `["uvx", "agent-gavel"]`(方式①)或 `["agent-gavel"]`(方式②③,命令已在 PATH),重启后 `doctor` 工具会报告 DOM / AT-SPI 双通道状态——这就是安装成功的信号。
|
|
55
|
+
|
|
56
|
+
### 开发者:clone 源码运行
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
git clone https://github.com/Rottenwooood/agent-gavel.git
|
|
60
|
+
cd agent-gavel
|
|
61
|
+
uv sync # 装依赖(Python 3.13)
|
|
62
|
+
uv run python3 -m agent_gavel.main # 起 MCP server(等价 ./run-mcp.sh)
|
|
63
|
+
uv run python3 tests/browser_manager_smoke.py # Chrome 生命周期冒烟测试
|
|
64
|
+
uv build # 本地构建 wheel/sdist
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
源码跑通后,想贡献你验证过的模板 → 见文末"贡献你验证过的模板"。
|
|
68
|
+
|
|
69
|
+
## 安装后到底发生了什么(流程说明)
|
|
70
|
+
|
|
71
|
+
### 三种安装方式的区别
|
|
72
|
+
|
|
73
|
+
**`uvx agent-gavel`** —— 一次性运行,不装进任何环境:
|
|
74
|
+
- uvx 在 `~/.cache/uv` 建**临时虚拟环境**装包,跑完即弃(缓存留档,下次秒起)
|
|
75
|
+
- 适合"先试试",不污染你的 Python;代价是每次 `uvx` 首次要解析依赖
|
|
76
|
+
|
|
77
|
+
**`uv tool install agent-gavel`** —— 全局安装(推荐正式用):
|
|
78
|
+
- uv 把 agent-gavel 装进 `~/.local/share/uv/tools/` 的独立环境
|
|
79
|
+
- 可执行命令 `agent-gavel` 链接到 `~/.local/bin/`(已在你的 PATH 里)
|
|
80
|
+
- 任何目录都能直接 `agent-gavel` 起 server,类似 `npm i -g`
|
|
81
|
+
|
|
82
|
+
**`pip install agent-gavel`** —— 装进当前 Python 环境(项目 venv / conda env):
|
|
83
|
+
- `agent_gavel/` 包落到 `<venv>/lib/python3.13/site-packages/`
|
|
84
|
+
- 同时生成可执行命令 `agent-gavel`(指向 `agent_gavel.main:main`),在所在环境 PATH 里
|
|
85
|
+
|
|
86
|
+
三种方式最终效果一致:**启动一个在 stdio 上说话的 MCP server 进程**,等 MCP 客户端连它。区别只在命令装在哪、是否全局可用。
|
|
87
|
+
|
|
88
|
+
### 怎么接到 opencode
|
|
89
|
+
|
|
90
|
+
opencode 通过 `command` 数组拉起这个进程,两者用 stdio 通信:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
// ~/.config/opencode/opencode.json
|
|
94
|
+
{
|
|
95
|
+
"mcp": {
|
|
96
|
+
"agent-gavel": {
|
|
97
|
+
"type": "local",
|
|
98
|
+
"command": ["uvx", "agent-gavel"], // 一次性
|
|
99
|
+
// 或 ["agent-gavel"] // uv tool install 或 pip install 后(命令已在 PATH)
|
|
100
|
+
"enabled": true
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
重启 opencode,工具列表出现 `agent-gavel_dom_*` 系列。**无需手动开 Chrome**——首次 DOM 调用时 server 自动用独立 profile 拉起可见窗口的调试 Chrome,崩溃自动重拉,退出自动清理。
|
|
107
|
+
|
|
108
|
+
### 模板存在哪
|
|
109
|
+
|
|
110
|
+
- **随包模板**:安装自带的模板在 `site-packages/agent_gavel/channels/{dom,desktop}/templates/`(只读默认,如百度/必应/豆瓣等 8 个验证过的)
|
|
111
|
+
- **你的模板**:`dom_save_template` / `desktop_save_template` 保存到你自己的用户目录 `~/.config/agent-gavel/{templates,desktop_templates}/`——跨 uvx 缓存、跨安装版本持久存在,不会被升级覆盖
|
|
112
|
+
- 读取时**用户目录优先**:你保存的同名模板覆盖自带模板;失效检测记录(stats)也存用户目录
|
|
113
|
+
|
|
114
|
+
## 实测耗时(优化前后对比)
|
|
115
|
+
|
|
116
|
+
### DOM 通道:固定等待 → 断言轮询
|
|
117
|
+
|
|
118
|
+
早期版本每个动作后固定 `sleep 3s` 再断言——`set_value` 这种立即生效的动作也白等 3s。改成动作后直接轮询断言(0.25s 间隔,满足即返)后,模板总耗时降 2.5–5.3x:
|
|
119
|
+
|
|
120
|
+
| 模板 | 优化前总耗时 | 优化后总耗时 | 提速 |
|
|
121
|
+
|---|---|---|---|
|
|
122
|
+
| baidu 搜索 | 13.8s | **4.3s** | 3.2x |
|
|
123
|
+
| baike 搜索 | 14.1s | **3.2s** | 4.4x |
|
|
124
|
+
| bing 搜索 | 13.8s | **3.3s** | 4.2x |
|
|
125
|
+
| douban 电影搜索 | 13.7s | **3.3s** | 4.2x |
|
|
126
|
+
| zhihu 登录填表 | 16.8s | **3.2s** | 5.3x |
|
|
127
|
+
| runoob 站内搜 | 7.6s | **3.0s** | 2.5x |
|
|
128
|
+
|
|
129
|
+
剩余耗时基本是 `navigate` 单步(~3.1s,页面真实加载,省不掉)。动作步本身:`set_value` 5–25ms,`click / enter` 100–1200ms。全部模板 pass,无回归。
|
|
130
|
+
|
|
131
|
+
### AT-SPI 桌面通道:computer-use-linux 优化补丁
|
|
132
|
+
|
|
133
|
+
给上游 computer-use-linux 打补丁(`third_party/` 保存):AT-SPI 连接复用 + doctor 缓存 + `fast_app_filter` 跳过全桌面 pid 反查 + 坐标操作不再触发 portal 截屏。桌面 70 节点应用实测:
|
|
134
|
+
|
|
135
|
+
| 阶段 | 原版 | 优化后(fast=true) |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| doctor_report | ~150ms | ~0ms(缓存) |
|
|
138
|
+
| app_filter | ~280ms | ~0ms(按 pid 直选) |
|
|
139
|
+
| snapshot_tree | ~145ms | ~140ms |
|
|
140
|
+
| **合计/次读树** | **~630ms** | **~220ms**(2.9x) |
|
|
141
|
+
|
|
142
|
+
agent-gavel 端到端:`read_state` 620→235ms(2.6x);`act_and_verify` 单次闭环 ~1.5s→0.65s(2.3x)。微信发消息模板整条流程 6.8s→4.8s。树内容与动作结果和原版一致,无回归。
|
|
143
|
+
|
|
144
|
+
## 功能一览
|
|
145
|
+
|
|
146
|
+
### DOM(网页)
|
|
147
|
+
|
|
148
|
+
- **Chrome 自管**:首次调用自动起独立 profile 调试 Chrome(可见窗口,永不用 headless),崩溃自愈,退出清理
|
|
149
|
+
- **`dom_step`**:通用单步闭环(动作 + 选择器 + 断言一次调用),`navigate / set_value / click / press_enter / clear / focus`
|
|
150
|
+
- **`dom_explore`**:枚举页面可交互元素,给验证过唯一的锚点(`#id` / `input[name=q]` / `__text__:登录` / 同名按钮用 `__text_nth__:N::`)
|
|
151
|
+
- **模板复用**:跑通的流程存 JSON(`templates/`,按网站组织:`site` 纯站名,文件名 `site_功能.json`),换参数直接跑
|
|
152
|
+
- **失败诊断**:环境错误(Chrome 没起 / DISPLAY 缺失 / CDP 断)返回 `reason + hint`,不会让 agent 对着一个 "Error executing tool" 猜
|
|
153
|
+
- **断言降级重试**:fail 自动换策略(trusted 翻转 → 重新 explore 换锚点 → 滚动 → 切换等待模式);`strict` 参数关掉降级暴露真实 fail(写模板/排查时用)
|
|
154
|
+
- **模板失效检测**:连续失败 ≥3 次标 suspected,再跑返回 warning 建议重新探索;任何一次 pass 清零
|
|
155
|
+
|
|
156
|
+
### AT-SPI(桌面,可选)
|
|
157
|
+
|
|
158
|
+
- `act_and_verify` / `run_operation` / 桌面模板,经 computer-use-linux 无障碍树操作桌面应用
|
|
159
|
+
- 默认走优化补丁版(`bin/computer-use-linux-fast`,连接复用 + fast_app_filter)
|
|
160
|
+
|
|
161
|
+
### 验证机制(两个通道共用)
|
|
162
|
+
|
|
163
|
+
- 断言:`eq / neq / exists / not_exists / contains`(特征用 JS 表达式提取)
|
|
164
|
+
- 等待:`poll`(轮询断言)/ `event`(MutationObserver,DOM 一变即醒,适合异步长等待)
|
|
165
|
+
- 每动作返回 `cost.phase` 毫秒级拆分(before_read / action / wait / after_verify),性能可观测
|
|
166
|
+
|
|
167
|
+
## TODO
|
|
168
|
+
|
|
169
|
+
"可用"和"正式发布"之间的差距:
|
|
170
|
+
|
|
171
|
+
- [ ] **适配 Windows**:AT-SPI 桌面通道是 Linux 无障碍树,Windows 应走 UI Automation 或对应后端;DOM 通道理论上跨平台但只在 Linux 验证过
|
|
172
|
+
- [ ] **完善模板共享机制**:当前模板存本地用户目录,缺少"模板共享/导入"通道(如按站点从远端拉模板、版本化、社区模板源)
|
|
173
|
+
- [ ] **登录态模板**:Chrome profile 登录态保留,覆盖真实登录类流程
|
|
174
|
+
- [ ] **多步骤 / 分页 / 滚动模板**:现有模板多是"导航+填+提交",缺连续点进详情、无限滚动、多 tab
|
|
175
|
+
- [ ] **断言语言增强**:`eq/neq/exists/contains` 之外,补数值比较 / 正则 / 列表断言(结果条数等)
|
|
176
|
+
- [ ] **权限 / 确认机制**:高危操作(提交表单 / 发送)前人工确认
|
|
177
|
+
- [ ] **可观测性**:debug 日志之上,补任务级 trace / 会话重放
|
|
178
|
+
|
|
179
|
+
## 贡献你验证过的模板(PR template)
|
|
180
|
+
|
|
181
|
+
agent-gavel 的模板按网站组织(`site` 纯站名,文件名 `site_功能.json`),随包带 8 个验证过的。你在一台机器上跑通了新网站的流程,**PR 给我**,合并后所有用户随包可用。
|
|
182
|
+
|
|
183
|
+
仓库内的验证过的模板:百度 / 百度百科 / 必应 / 博客园 / 豆瓣电影 / Google / 菜鸟教程 / 知乎登录填表。
|
|
184
|
+
设计说明见 [docs/internal-beta.md](docs/internal-beta.md),路线见 [docs/roadmap.md](docs/roadmap.md)。
|
|
185
|
+
|
|
186
|
+
### 模板去哪、怎么存
|
|
187
|
+
|
|
188
|
+
模板默认读**用户目录**优先(`~/.config/agent-gavel/{templates,desktop_templates}/`),随包模板在 `agent_gavel/channels/{dom,desktop}/templates/`。
|
|
189
|
+
|
|
190
|
+
贡献模板的路径:源码 clone → 用 `dom_explore` + `dom_step` 现场探索跑通 → `dom_save_template` 存 JSON → 确认稳定后放进仓库对应目录提 PR。
|
|
191
|
+
|
|
192
|
+
### 模板 PR 检查清单
|
|
193
|
+
|
|
194
|
+
模板 PR 要能直接合并,请过一遍:
|
|
195
|
+
|
|
196
|
+
- [ ] 模板 JSON 在 `agent_gavel/channels/dom/templates/<site>_<func>.json`(或 desktop 对应目录)
|
|
197
|
+
- [ ] `site`(DOM)/ `app`(desktop)字段是纯站名,不含功能名;文件名 `站名_功能`
|
|
198
|
+
- [ ] 真实跑通过(`dom_run_template` / `desktop_run_template` 全 pass),PR 描述里贴结果
|
|
199
|
+
- [ ] 步骤含断言(`page_features` + `expected_feature`),不是只发动作不验证
|
|
200
|
+
- [ ] 用了稳定锚点(`#id` / `input[name=x]` / `__text__:`),没有写死易变的 CSS 路径
|
|
201
|
+
- [ ] 涉及登录/个人数据时用假凭据,PR 里说明依赖的登录态
|
|
202
|
+
- [ ] 描述里写清:站点 URL、功能、测过的关键词/参数
|
|
203
|
+
|
|
204
|
+
模板存疑或失效会走失效检测(连续失败 ≥3 次标 suspected),无需担心一次不完美。
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
File without changes
|