PicoBot/docs/AGENT_BROWSER_INTEGRATION.md

186 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# agent-browser 集成设计
本文描述 PicoBot 1.3.1 的浏览器工具实现。目标是在保持模型侧单一 `browser` 工具协议的同时,用 agent-browser 完全替代 Fantoccini、ChromeDriver 和 WebDriver并让浏览器状态、并发、产物和健康检查服从 PicoBot 的 Session 生命周期。
## 1. 选择与边界
PicoBot 使用 agent-browser CLI 的 `--json` 协议,不直接链接其内部 crate也不把 agent-browser MCP Server 原样暴露给模型。
原因:
- agent-browser 是原生 Rust CLI + daemondaemon 通过 Chrome CDP 驱动浏览器CLI 进程很短,浏览器状态跨命令保存在 daemon 中。
- CLI 是项目的稳定公开边界PicoBot 不需要依赖 agent-browser 的内部 Rust 模块布局。
- PicoBot 包装层可统一绑定 dialog、限制并发和输出、校验 URL、控制截图目录并把图片接入现有 `ToolResultWithMedia`
- 直接暴露 MCP 会让 session ID、文件路径、输出规模和安全策略落到模型参数中也难以自动绑定当前 PicoBot dialog。
这不是把浏览器逻辑重新实现一遍。元素定位、accessibility snapshot、页面交互、Chrome 启动、CDP 通信和 daemon 生命周期均由 agent-browser 负责PicoBot 只负责编排和边界控制。
## 2. 分层
```text
AgentLoop
│ ToolExecutionContext(session_id, turn_id)
BrowserTool 模型侧单一 browser schema
BrowserManager dialog → opaque session并发/空闲/产物
├─ security URL、DNS、私网与 allowlist 前置校验
├─ action browser action → CLI argv
└─ AgentBrowserRunner timeout、env、--json、错误与输出解析
agent-browser CLI → Rust daemon → Chrome/Chromium CDP
```
源文件:
- `src/tools/browser/mod.rs`:工具 schema 与入口。
- `src/tools/browser/action.rs`:严格参数解析和 argv 映射。
- `src/tools/browser/manager.rs`会话表、per-session mutex、空闲回收、截图媒体。
- `src/tools/browser/runner.rs`:无 Shell 的子进程调用、硬超时、JSON/错误解析。
- `src/tools/browser/security.rs`:导航策略。
- `src/tools/traits.rs`:向有状态工具提供 `ToolExecutionContext`;其他工具沿用默认实现。
## 3. 会话与并发
`SessionManager` 为每次 AgentLoop 执行传入完整 PicoBot session ID。BrowserManager 第一次看到该 ID 时生成随机、不透明的 `picobot-<uuid>` agent-browser session模型不能选择或猜测底层 session。
- 同一个 dialog所有浏览器 action 由该 session 的 mutex 串行cookie、storage、历史和当前页面连续。
- 不同 dialog使用不同 agent-browser session可并发执行。
- 子 Agent若显式获准使用 `browser`,沿用发起任务的 PicoBot session因此与主 Agent 共享同一浏览器并受同一 mutex 保护。
- Scheduler使用 `cron:<job-id/name>` 隔离,不与交互 dialog 混用。
- `close`:先从 PicoBot 映射表移除,再调用 agent-browser close重复关闭幂等。
- 空闲回收:创建新会话前移除超过 `idle_timeout_secs` 的映射并尽力关闭底层 session。
- 容量:达到 `max_sessions` 且没有可回收会话时明确失败,不静默复用别人的浏览器。
Gateway 配置重载会构造新的 ToolRegistry/BrowserManager旧运行代按现有 drain 规则退出。agent-browser daemon 的空闲退出时间通过 `AGENT_BROWSER_IDLE_TIMEOUT_MS` 同步设置,避免遗留浏览器无限驻留。
## 4. Action 映射
| PicoBot action | agent-browser 命令 |
|---|---|
| `open` | `open <url>` |
| `snapshot` | `snapshot --interactive --compact [--depth N]` |
| `click` / `fill` / `type` | 同名命令;无 selector 的 type 使用 `keyboard type` |
| `get_text` / `get_title` / `get_url` | `get text/title/url` |
| `focus` / `wait` / `press` / `hover` / `scroll` | 对应原生命令 |
| `click_at` | `mouse move` + `mouse down left` + `mouse up left` |
| `screenshot` | `screenshot <controlled-path> [--full] [--annotate]` |
| `close` | `close` |
每次调用都使用 argv 数组直接启动进程,不经过 Shell。`fill` / `type` 的内容不会写入 PicoBot 日志;日志只记录 action 名和是否绑定 session。
Runner 固定传入 `--session``--json` 和明确的 headed 状态,并设置:
- `AGENT_BROWSER_EXECUTABLE_PATH`(配置后)
- `AGENT_BROWSER_CONTENT_BOUNDARIES`
- `AGENT_BROWSER_MAX_OUTPUT`
- `AGENT_BROWSER_ALLOWED_DOMAINS`(非空时)
- `AGENT_BROWSER_IDLE_TIMEOUT_MS`
非零退出码、JSON 中 `success=false`、无效 JSON和超时都转换为工具失败。stdout/stderr 在返回模型前有长度上限;页面类结果保留 agent-browser `_boundary` 元数据。
## 5. 截图与媒体
截图绝不返回 Base64。调用方可省略 `path` 自动生成文件名,也可提供单个 `.png` 文件名;绝对路径、目录分隔、`.``..` 均拒绝。实际文件始终位于 `browser.artifact_dir`
命令成功后 PicoBot 再验证文件存在、是普通文件且非空,然后返回:
```text
ToolResultWithMedia {
result: ToolResult { output: "Screenshot saved: ..." },
media_refs: [MediaRef { media_type: "image", path: "..." }]
}
```
因此多模态 Provider 可在下一轮直接看到图片,历史中仍只保存短路径清单,不产生 Base64 上下文膨胀。
## 6. 安全模型
默认策略:
- 只允许 `http://``https://`,拒绝 URL userinfo。
- `allow_private_hosts=false` 时拒绝 localhost、`.local`、回环、私网、link-local、未指定和组播地址域名会先解析 DNS任一结果为私网即拒绝。
- `allowed_domains` 非空时 PicoBot 先校验首个 URLagent-browser 再对导航、重定向、子资源、WebSocket、EventSource、sendBeacon 和受支持 Chromium 的 WebRTC 实施域名边界。
- 默认开启 content boundaries并把页面文本限制为 50,000 字符。
- 包装层没有 `eval`、上传、下载、cookie/storage 写入或任意 agent-browser 命令透传,模型只能使用 allowlisted action。
- 截图有单独的产物目录,不能用来覆盖任意文件。
`allowed_domains=[]` 表示不启用 agent-browser 域名过滤,适合通用浏览;这不是 OS 网络沙箱。需要强隔离时,应同时设置明确域名表和容器/主机 egress 策略。允许私网浏览是显式配置,适合本地应用测试,但会扩大 SSRF 风险。
## 7. 安装
验证版本为 `0.33.0`
```bash
npm install -g agent-browser@0.33.0
agent-browser install
```
Linux 自动补系统依赖:
```bash
agent-browser install --with-deps
```
不使用 npm 时:
```bash
cargo install agent-browser --version 0.33.0 --locked
agent-browser install
```
macOS 也可执行:
```bash
brew install agent-browser
agent-browser install
```
`agent-browser install` 下载 Chrome for Testing。已有浏览器时设置
```json
"browser_executable_path": "/usr/bin/chromium"
```
或设置环境变量 `AGENT_BROWSER_EXECUTABLE_PATH`。agent-browser 的 daemon 与 CDP 路径不需要 Node.jsnpm 安装方式只需要 npm 用来放置预编译 CLI。Dockerfile 安装 Debian Chromium、`agent-browser@0.33.0` 并设置 executable path。
## 8. 使用
1. 浏览器工具默认启用;从旧配置删除 `webdriver_url``chrome_path`,加入新的 browser 字段。缺少依赖不会阻止 Gateway 启动,只会让 health 和实际浏览器调用失败。
2. 运行 `picobot health`;应看到 agent-browser CLI 版本和 offline quick doctor 通过。
3. 启动或重载 Gateway。
4. 对 Agent 说“使用浏览器打开 …”。模型的推荐动作序列是:
```text
browser(open, url)
browser(snapshot, interactive_only=true, compact=true)
browser(click/fill/type, selector=@eN)
browser(snapshot) # 页面改变后刷新 refs
browser(screenshot, annotate=true) # 需要视觉上下文时
browser(close)
```
agent-browser 的 `@e` 引用属于当前页面快照。导航、弹窗或 DOM 大幅变化后必须重新 snapshot不能长期缓存旧引用。
## 9. Health 三入口
`src/health.rs``HealthService` 是唯一检查实现:
- `picobot health [--json]`:本机运维入口;核心/配置必需项失败时退出 `1`
- `/health`:当前 Gateway 配置的聊天入口。
- `health` ToolAgent 可调用的只读入口,支持 `json=true`
检查项包括 workspace、Bash、内容/文件搜索后端、可选 systemctl、配置中的 stdio MCP 命令,以及浏览器启用时的 agent-browser 版本、显式浏览器路径和 `doctor --offline --quick --json`。检查不安装软件、不执行 `doctor --fix`、不访问 Provider API也不输出配置密钥。
## 10. 迁移和故障处理
- 配置使用 `deny_unknown_fields`;遗留 WebDriver 字段会在加载时失败,而不是被静默忽略。
- `failed to start 'agent-browser'`CLI 不在 PATH`browser.command` 错误;运行 health。
- doctor 失败:运行 `agent-browser doctor` 查看完整诊断,再安装浏览器/系统库。
- session limit关闭不再使用的 dialog 浏览器,或调整 `max_sessions`;不要让多个 dialog 共享同一底层 ID。
- domain blocked补充站点和必要 CDN 域名;不要用空白 allowlist 绕过生产隔离策略。
- command timeout确认页面/浏览器未卡死,再按部署风险调整 `command_timeout_secs`
- 截图不存在:视为工具失败,不构造失效 MediaRef。
Fantoccini crate、旧 `src/tools/browser.rs` WebDriver 实现、ChromeDriver Docker 包和相关配置已全部删除。Cargo 不链接 agent-browser它是由 health 管理的外部运行依赖。