browser-harness:补两条浏览器复用纪律(用户当场点破)+ 入库积压的「调 AI 工具提问方法」
- 🔴 先探测、能复用就复用:动手第一件事查 9223 上有没有已在跑的实例, 有就直接连(netstat / curl /json/version 两种探法),⛔ 不再起第二个。 专治「为了量一次尺寸就另起一个 headless 实例」这类小活 (用户原话:「为什么要重新开浏览器,先检查之前是否开过浏览能否复用」) - 🔴 一个页面只开一个标签:同一页面全程一个标签,换路由改 hash、换视口走 Emulation, 只有并排对比两个不同页面才开第二个、用完立刻关;收工前 list_tabs() 复核, 不给自己留尾巴、也不关别人的页 (用户原话:「后续调试网页 一个页面开一个标签就行了不要反复开」) - ⛔ 别自建取数通道:要 DOM 数值就用 js(...),别为「量一个高度」另写脚本去起 Chrome 同文件另有 2026-10-07 定案的「用 browser-harness 调 AI 工具(ChatGPT 等)的提问方法」一节, 一直是未提交状态,随本次一并入库(常驻后台任务守端口、独立实例 9223、profile 复用保登录态)。
This commit is contained in:
1 parent
7a476f9400
commit
44d42b0943
1 file changed
+86
-1
@@ -18,9 +18,94 @@ Direct browser control via CDP. For task-specific edits, use `agent-workspace/ag
|
||||
- ⛔ **不附着用户日常 Chrome**。下面「Local Chrome」一节说的"默认附着正在运行的 Chrome"
|
||||
在本机**不适用** —— 那样会弹「允许远程调试?」去动用户自己的浏览器(2026-09-26 实际踩到)。
|
||||
⇒ 必须起**独立实例**:`BU_CDP_URL=127.0.0.1:9223`(不要用用户 Chrome 默认的 9222)。
|
||||
- ✅ **动手前先 `list_tabs()`** 看清有哪些标签页,别盲点。
|
||||
- 🔴 **先探测、能复用就复用**(2026-10-08 用户当场点破:「为什么要重新开浏览器,先检查之前是否开过浏览能否复用」)。
|
||||
动手第一件事是查 `9223` 上**有没有已经在跑的实例**;有 ⇒ 直接连,⛔ 不要再起一个。
|
||||
⛔ 「量个尺寸 / 截个图 / 取个数」这类小活最容易犯这个错 —— 为了量一次就另起一个 headless 实例,
|
||||
既违了上面的禁令,又会和常驻实例抢同一个 profile。
|
||||
探法(第一条最轻,够用):
|
||||
`netstat -ano | grep -E "127\.0\.0\.1:9223 .*LISTENING"` ⇒ 有 pid = 在跑;
|
||||
`curl --noproxy '*' -s http://127.0.0.1:9223/json/version` ⇒ 回 JSON 说明端口后面确实是 CDP。
|
||||
确认在跑之后按下面第 2 条的 env 写法连上去,先 `list_tabs()` 摸清现有页,
|
||||
自己需要的页用 `new_tab()` 开 —— ⛔ 不碰别人的页,也⛔ 不为自己方便关掉现有页。
|
||||
- 🔴 **一个页面只开一个标签,⛔ 不要反复开**(2026-10-08 用户令:「后续调试网页 一个页面开一个标签就行了不要反复开」)。
|
||||
这条接在上一颗子弹后面:**先复用浏览器**是做对了,但**别在同一个浏览器里再反复开页**。
|
||||
典型的错法就是调试一个原型:量一次 `new_tab(原型)` 一次,量完还忘了关 —— 一次会话下来
|
||||
共享实例里就堆出一串**同一个页面**的标签(用户 2026-10-08 亲眼看到,才出的这条令)。
|
||||
正确做法,按便宜的排:
|
||||
- **同一个页面**(同一个 URL / 同一份原型)**从头到尾就那一个标签**。
|
||||
- 换路由 ⇒ 改 hash(`js("location.hash='#/x'")`)或 `goto_url()`,⛔ 不要 `new_tab()`。
|
||||
- 换视口 ⇒ `cdp("Emulation.setDeviceMetricsOverride", width=…, height=…)` 在**同一个标签**里改,
|
||||
⛔ 不要为了量另一个宽度再开一个标签;量完 `cdp("Emulation.clearDeviceMetricsOverride")` 还原。
|
||||
- 要**并排对比两个不同页面**(比如参照物 vs 我方)⇒ 这时才开第二个,**用完立刻 `close_tab()`**。
|
||||
- 完全不需要页面时(只取一个数、截一张图)⇒ 复用**当前那个**标签,别再开。
|
||||
- 🔴 **收工前必须 `list_tabs()` 复核一遍,把自己开的一个不留**。共享实例是别人的工作现场,
|
||||
⛔ 别留尾巴;反向也一样 —— ⛔ 别顺手关掉不是自己开的页。
|
||||
- ✅ **动手前先 `list_tabs()`** 看清有哪些标签页,别盲点。(这条同时是上面那条的**收工复核**用的)
|
||||
- ⛔ **别自建取数通道**:需要 DOM 数值就用 `js(...)`、需要截图就用 harness 的截图helper,
|
||||
⛔ 不要为了「量一个高度」另写一个脚本去起 Chrome。
|
||||
- ✅ 静态页 / 公开 API 取数**优先 `curl` 或 WebFetch** —— 用不着浏览器就别起。
|
||||
|
||||
## 用 browser-harness 调 AI 工具(ChatGPT 等)的提问方法
|
||||
|
||||
> 2026-10-07 用户定案。适用于「打开 ChatGPT / Claude 网页版求建议、核对方案、做结构评审」这类活。
|
||||
|
||||
### 1. 🔴 浏览器要由**常驻后台任务**开着
|
||||
|
||||
本机沙箱会在**父进程退出时连带杀掉子进程**。实测对照:
|
||||
|
||||
- 普通(同步)调用里起 Chrome ⇒ 端口 1 秒内就绪,**调用一返回 Chrome 立刻死**(随后 `curl` 报 `WinError 10061`)。
|
||||
- 丢进**后台任务、且该任务一直不退出**(起完浏览器就守着端口)⇒ 浏览器**全程常驻**。
|
||||
|
||||
⇒ 做法:先起一个**常驻任务**把浏览器开着(守端口,掉了就写日志),之后每次操作**只连不起**。
|
||||
⛔ 别让每次调用各自起一遍浏览器 —— 父进程一退全没,而且多个实例会抢同一个 profile。
|
||||
|
||||
### 2. 起独立实例(端口 9223)
|
||||
|
||||
```bash
|
||||
chrome.exe --remote-debugging-port=9223 \
|
||||
--user-data-dir=E:/ProgramData/.workbuddy/tmp/bu-chatgpt-profile \
|
||||
--proxy-server="socks5://127.0.0.1:10800" about:blank
|
||||
```
|
||||
|
||||
- 端口用 **9223**(用户日常 Chrome 是 9222);`--user-data-dir` 固定复用 ⇒ **登录态保留**。
|
||||
- `BU_CDP_URL` **必须带 scheme**:`http://127.0.0.1:9223`。
|
||||
- 必须清掉沙箱代理变量(`HTTP_PROXY` / `HTTPS_PROXY` 会劫持本地 CDP ⇒ `502 Bad Gateway`):
|
||||
`env -u HTTP_PROXY -u HTTPS_PROXY -u http_proxy -u https_proxy NO_PROXY=127.0.0.1,localhost BU_CDP_URL=http://127.0.0.1:9223 browser-harness`
|
||||
- 可执行体写全名:`~/.local/bin/browser-harness.exe`。
|
||||
|
||||
### 3. 提问怎么写
|
||||
|
||||
- **说清「意图和目标」+ 给「完整上下文」**,末尾一句明确提问 —— 用户口径:不用写太多控制指令。
|
||||
- ⛔ **它看不到你的本机路径**。要么**把全文逐字内联**,要么**上传文件**;⛔ 不要用「见 xxx.md」「文件在 E:/…」代替内容。
|
||||
- 一轮一个主题。
|
||||
|
||||
### 4. ✅ 消息发出去的硬证据 = **输入框被清空**
|
||||
|
||||
⚠️ **页尾出现你写的提问 ≠ 已发出** —— 输入框本身就在 `main` 里,它的内容会落在 `innerText` **尾部**,看起来就像已发送。发送动作之后**回读输入框长度归零**才算数。
|
||||
|
||||
### 5. ChatGPT 当前页面(实测,UI 会换代)
|
||||
|
||||
| 项 | 写法 |
|
||||
|---|---|
|
||||
| 输入框 | `div.ProseMirror[role="textbox"]`(`#prompt-textarea` 已不存在) |
|
||||
| 发送按钮 | `#composer-submit-button` → `button[data-testid="send-button"]` → `button[aria-label="发送"]` |
|
||||
| 取正文 | `(document.querySelector('main')||document.body).innerText` |
|
||||
| 上传文件 | `input[type=file]` + `cdp("DOM.setFileInputFiles", files=[路径], nodeId=...)` |
|
||||
| 切分锚点 | `你说:` / `ChatGPT 说:` / `ChatGPT 可能会出错` |
|
||||
|
||||
三个易误判点:
|
||||
|
||||
1. 一页可能有**多个** `ChatGPT 说:`(历史轮次)⇒ 取正文用 **`rfind` 取最后一个**,`find` 会切到上一轮。
|
||||
2. **「ChatGPT 可能会出错」不是完稿信号**(它一直在页面上)⇒ 完稿判据 = **正文长度连续两次采样不变**。
|
||||
3. **「思考」是输入框工具栏的按钮文案**,不是「正在生成」状态。
|
||||
|
||||
### 6. 脚本怎么写
|
||||
|
||||
- ⛔ 不要在 Python 里拼 heredoc + 转义引号喂给 harness(嵌套转义 ⇒ `SyntaxError`)。
|
||||
- ✅ 每一步脚本**写成独立 `.py` 文件**,驱动脚本读文件后经 stdin 喂给 harness。
|
||||
- ✅ 全程**日志落盘**(每步 rc + 关键读数),失败能直接定位到哪一步。
|
||||
- 多标签页时:先 `cdp("Target.getTargets", flatten=True)` 看清有哪些页,必要时关掉重复页再 `new_tab(目标URL)`;各步落在不同标签页上会导致读数错乱。
|
||||
|
||||
## When Not to Use
|
||||
|
||||
A basic fetch of public information needs no browser. If a plain HTTP request can read it — a public page, an API, docs — use `curl` or your fetch tool, and leave the browser alone. Use browser-harness when the task needs interaction (click, type, navigate), the user's logged-in session, JS rendering, or a bot-protected page. If a direct fetch fails or returns a shell page, then escalate to the browser.
|
||||
|
||||
Reference in new issue
Block a user