Files
atomk-hermes-skills/skills/cross-border-ecommerce/hubstudio-bridge/SKILL.md
T

480 lines
19 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.
---
name: hubstudio-bridge
description: "HubStudio 浏览器环境 AI 自动化 — 通过 Hermes + Desktop Bridge 操控 HubStudio 浏览器环境/云手机,自然语言驱动:列出环境、启动环境、获取调试端口、对接 Playwright/Selenium。"
version: 1.3.0
author: Hermes Agent
metadata:
hermes:
tags: [hubstudio, 浏览器环境, 云手机, browser-automation, cross-border]
related_skills:
- ziniao-bridge
- bridge-cdp-agent
- drissionpage-toolkit
cron_compatible: true
---
# HubStudio Bridge
通过 Hermes + AtomK Desktop 连接 HubStudio Local API,用自然语言管理浏览器环境与云手机。
**触发词:** "HubStudio" / "hubstudio" / "浏览器环境" / "云手机" / "启动环境" / "列出环境"
---
## 架构总览
```
自然语言指令
Hermes Agent (解析意图)
Bridge POST /api/command {action: "hubstudio_cdp.navigate", params: {...}}
↓ WS → type: "command"
AtomK Desktop bridge-manager.ts
↓ messageRouter.dispatch()
├─ hubstudio.* → HubstudioClient → HubStudio API (6873)
└─ hubstudio_cdp.* → HubStudioCDPController → Playwright connectOverCDP
→ HubStudio 独立 Chrome (58289)
```
**前提条件:**
- HubStudio 客户端与 AtomK Desktop 在同一台 Windows/Mac 机器
- HubStudio 客户端已启动(Local API 模式)
- API 凭证已配置(app_id + app_secret
- Desktop 已更新到包含 `hubstudio-cdp-controller.ts` 的版本
### ✅ CDP 中继:hubstudio_cdp.* 命令(Desktop v4.0.x+
Desktop 侧新增 `HubStudioCDPController``src/main/hubstudio-cdp-controller.ts`),
通过 Playwright `connectOverCDP` 连接 HubStudio 独立 Chrome 实例。
Bridge 通过 `POST /api/command` 端点(`cloud-bridge/server.py`)转发命令。
| 命令 | 参数 | 说明 |
|------|------|------|
| `hubstudio_cdp.navigate` | `{envCode, url, waitUntil?, timeout?}` | 在 HubStudio Chrome 中导航 |
| `hubstudio_cdp.evaluate` | `{envCode, expression}` | 执行 JS 并返回结果 |
| `hubstudio_cdp.click` | `{envCode, x, y}` | 在指定坐标点击 |
| `hubstudio_cdp.screenshot` | `{envCode, fullPage?, quality?}` | 截图(返回 base64 JPEG |
| `hubstudio_cdp.snapshot` | `{envCode}` | 获取页面可访问性树快照 |
| `hubstudio_cdp.disconnect` | `{envCode}` | 断开 CDP 连接 |
| `hubstudio_cdp.status` | — | 查看当前 CDP 连接状态 |
**自动连接**`hubstudio.open_env` 成功后自动调用 `hubstudioCdp.connect(containerCode, port)`
响应中会包含 `cdpConnected: true`
**自动断开**`hubstudio.close_env` 会先断开 CDP 再关闭浏览器。
### ⚠️ CDP 端口可达性
HubStudio Chrome 的 CDP 端口(如 58289)只在 Windows 本机(127.0.0.1)可达。
Desktop 通过本机 Playwright `connectOverCDP` 连接,Bridge 通过 Desktop WS 隧道
中转 CDP 命令。不能从 Bridge/Linux 侧直连 HubStudio CDP 端口。
**验证端口可达性:** `scripts/hubstudio-cdp-direct-test.py` — 在 Windows 上运行。
---
## HubStudio Local API
> 📖 完整 API 文档: `references/hubstudio-api.md`(源: api-docs.hubstudio.cn
> 📦 HubStudio Skill 项目: `references/hubstudio-skill-project.md`OpenClaw 技能包, 56 条命令映射)
### 基础 URL
```
http://127.0.0.1:6873
```
### 认证方式
所有请求携带 Header
```
Authorization: Bearer {API_SECRET}
Accept-Language: zh-CN
```
API Secret 来自 Hubstudio 客户端设置页「API 接口」→「复制 API 密钥」
### Desktop 端调用
Desktop v4.0.2 内置 `hubstudio-client.ts`Electron 主进程,**无 CORS 限制**),支持完整的 Hubstudio API
```
hubstudio.list_envs → POST /api/v1/env/list → 列出所有浏览器环境
hubstudio.open_env → POST /api/v1/browser/start → 启动环境 → debuggingPort
hubstudio.close_env → POST /api/v1/browser/close → 关闭环境
hubstudio.opened_envs → POST /api/v1/browser/opened → 已打开环境列表
hubstudio.status → 健康检查
```
## 核心接口
### 1. 列出所有浏览器环境
```
POST /api/v1/env/list
Content-Type: application/json
{"current": 1, "size": 200}
```
返回示例:
```json
{
"code": 0,
"data": {
"records": [
{
"containerCode": "1502764609",
"containerName": "环境A-亚马逊",
"remark": "美西",
"proxyTypeName": "socks5",
"ipAddress": "103.136.249.48"
}
],
"total": 1
}
}
```
### 2. 启动浏览器环境
```
POST /api/v1/browser/start
Content-Type: application/json
{
"containerCode": "1502764609",
"isHeadless": false
}
```
返回:
```json
{
"code": 0,
"data": {
"containerCode": "1502764609",
"debuggingPort": "59591",
"webdriver": "C:\\...webdriver.exe",
"browserPath": "C:\\...chrome_130\\hubstudio",
"statusCode": "0"
}
}
```
### 3. 关闭浏览器环境
```
POST /api/v1/browser/close
{"containerCode": "1502764609"}
```
### 4. 获取已打开环境
```
POST /api/v1/browser/opened
{}
→ {"code":0, "data":["1502764609","11320340"]}
```
---
## 操作模式
### 模式 ABridge 命令路由(Desktop v4.0.2+,推荐)
Desktop v4.0.2 内置完整 `hubstudio-client.ts` + `bridge-message-router.ts` hubstudio.* 路由。
Hermes → Bridge → Desktop 主进程直接调 Hubstudio Local API**无 CORS 限制**。
```
Hermes Agent
→ Bridge WS (type: "command", method: "hubstudio.list_envs")
→ Desktop bridge-manager.ts
→ messageRouter.dispatch()
→ HubstudioClient.listEnvs()
→ POST http://127.0.0.1:6873/api/v1/env/list
→ 返回 → Bridge → Hermes
```
支持的命令:
| 命令 | 参数 | 说明 |
|------|------|------|
| `hubstudio.status` | — | 健康检查/连接测试 |
| `hubstudio.list_envs` | `{page?, size?}` | 列出浏览器环境 |
| `hubstudio.open_env` | `{containerCode, isHeadless?}` | 启动环境 → debuggingPort + **自动连 CDP** |
| `hubstudio.close_env` | `{containerCode}` | 关闭环境 + **自动断 CDP** |
| `hubstudio.opened_envs` | — | 已打开环境列表 |
| `hubstudio_cdp.navigate` | `{envCode, url, waitUntil?, timeout?}` | HubStudio Chrome 中导航 |
| `hubstudio_cdp.evaluate` | `{envCode, expression}` | 执行 JS 返回结果 |
| `hubstudio_cdp.click` | `{envCode, x, y}` | 坐标点击 |
| `hubstudio_cdp.screenshot` | `{envCode, fullPage?, quality?}` | 截图(base64 JPEG |
| `hubstudio_cdp.snapshot` | `{envCode}` | 可访问性树快照 |
| `hubstudio_cdp.disconnect` | `{envCode}` | 断开 CDP 连接 |
| `hubstudio_cdp.status` | — | CDP 连接状态 |
### 模式 BCDP evaluate(备选,有 CORS 问题)
仅在 Bridge 命令路由不可用时使用。CDP Chrome 调 HubStudio API 会被 CORS 拦截。
---
## 典型操作场景
### 场景 1:列出所有环境
**自然语言:** "列出我所有 HubStudio 浏览器环境"
**执行:**
```
GET /api/env/list
→ 解析 → 表格展示环境名称、ID、状态
```
### 场景 2:启动环境 + 获取端口
**自然语言:** "启动 HubStudio 环境 1502764609"
**执行:**
```
POST /api/env/open {"envId": "1502764609"}
→ 获取 debuggingPort
→ Playwright connectOverCDP(port)
→ 可以继续操控该环境
```
### 场景 3:关闭环境
**自然语言:** "关闭环境 1502764609"
**执行:**
```
POST /api/env/close {"envId": "1502764609"}
```
### 场景 4:巡检所有环境状态
**自然语言:** "检查所有 HubStudio 环境状态"
**执行:**
```
GET /api/env/list → 遍历 → GET /api/env/status?envId=xxx
→ 汇总报告
```
---
## Desktop 端调用方式
Desktop v4.0.2 内置 `hubstudio-client.ts`Electron 主进程,无 CORS 限制)。
Bridge 命令通过 `bridge-message-router.ts` 分发到 `HubstudioClient` 方法。
凭证配置:Desktop Chrome Bridge 页面 → 「紫鸟 & Hubstudio API」:
- App ID: Hubstudio 客户端设置 → API 接口 → app_id
- App Secret: 同上 → API 密钥(RSA 私钥,~1600 字符 PEM
- Base URL: `http://127.0.0.1:6873`(默认,本地地址)
存储:`~/.atomk/hubstudio.json`Electron safeStorage 加密)。
## 典型操作场景
### 场景 1:列出所有环境
**自然语言:** "列出我所有 Hubstudio 浏览器环境"
**执行:**
```
hubstudio.list_envs
→ POST /api/v1/env/list {current:1, size:200}
→ 表格展示环境名称、ID、状态
```
### 场景 2:启动环境 + 获取端口
**自然语言:** "启动 HubStudio 环境 1502764609"
**执行:**
```
hubstudio.open_env {containerCode: "1502764609"}
→ POST /api/v1/browser/start
→ 获取 debuggingPort(如 58289
→ ⚠️ 此端口仅在 Windows 本机可达,不能从 Bridge/Linux 连接
→ 在 Windows 上用 DrissionPage 直连: Chromium(addr_or_opts='127.0.0.1:58289')
```
详见上方「架构限制」节和 `scripts/hubstudio-cdp-direct-test.py` 测试脚本。
### 场景 3:关闭环境
**自然语言:** "关闭环境 1502764609"
**执行:**
```
hubstudio.close_env {containerCode: "1502764609"}
→ POST /api/v1/browser/close
```
HubStudio root (127.0.0.1:6873) 在某些情况下 `Page.navigate` 会超时(15s)。
这是因为 CDP Chrome 保持空白 about:blank page 时 navigate 阻塞。
**修复**`/cdp/send``Target.createTarget` 直接创建新 tab
```javascript
fetch('/cdp/send', {
method: 'POST',
headers: {..., 'X-Desktop-Id': '<slot>'},
body: JSON.stringify({method: 'Target.createTarget', params: {url: 'http://127.0.0.1:6873'}})
})
// 返回 {targetId: "6034BA..."} — 可直接用于 evaluate
```
无需后续 `/cdp/attach`,新 target 自动 attach。
### APP Secret 格式
HubStudio APP Secret 是 **RSA 私钥**PEM base64, PKCS#8 格式,~1600 字符)。
不是普通短字符串。存储在 `.env` 文件时必须完整保留,不可截断。
---
## 与 紫鸟(ziniao) 的区别
| | HubStudio | 紫鸟(Ziniao) |
|------|-----------|-------------|
| API 端口 | 6873 | 19481(默认) |
| 认证方式 | Bearer API_SECRET | Bearer apiKey |
| 环境标识 | containerCode | storeId |
| 功能 | 浏览器环境 + 云手机 | 店铺浏览器 |
| Desktop 集成 | v4.0.2 已集成 | v4.0.0 已集成 |
| Bridge 路由 | hubstudio.* (5 methods) | ziniao.* (5 methods) |
| API 文档 | api-docs.hubstudio.cn | 紫鸟开放平台 |
---
## Skill 注册与 Desktop 发现
Hermes Agent 在 Bridge 服务器(Linux)上运行,Desktop 在用户本机(Windows/Mac)。Skill 文件在服务器上创建后,Desktop 看不到。
Desktop 从两个源发现 skill
1. **本地已安装** — Desktop 扫描本机 `~/.hermes/skills/<category>/<name>/SKILL.md`
2. **Gitea 注册表** — Desktop 拉取 `admin9webs/atomk-hermes-skills` 仓库
推送 skill 到 Gitea 注册表的命令:
```
PUT /api/v1/repos/admin9webs/atomk-hermes-skills/contents/skills/<category>/<name>/SKILL.md
```
使用 Basic Authbody 含 base64 编码内容 + `branch: main`
Gitea 注册表根路径:
```
https://gitea9webs.sh3.ikuai7.com/admin9webs/atomk-hermes-skills
```
> ⚠️ Desktop 必须在技能管理页面刷新注册表才能看到新推送的 skill。在 Desktop 中点击"安装"后,skill 文件写入本机 `~/.hermes/skills/`,此后出现在本地已安装列表。
## Bridge /api/command 端点
Desktop 的 hubstudio.* / hubstudio_cdp.* / playwright.* / ziniao.* 命令通过 Bridge 的
`POST /api/command` 端点转发(`cloud-bridge/server.py`):
```
Hermes → POST /api/command {action: "hubstudio_cdp.navigate", params: {...}}
→ Bridge WS → Desktop bridge-manager.ts
→ MessageRouter.dispatch({method: action, params})
→ 返回 {type: "command_response", id, ok, data}
```
**认证**Bearer token + `X-Desktop-Id` header 指定目标 Desktop。
**请求格式**
```json
{
"action": "hubstudio.open_env",
"params": {"containerCode": "xxx"},
"id": "optional-custom-id"
}
```
**响应格式**
```json
{
"action": "hubstudio.open_env",
"ok": true,
"data": {"debuggingPort": "58289", "cdpConnected": true}
}
```
**端点注册**:9228 和 9229 端口都已注册。路由在 `/api/{path:.*}` wildcard 之前。
超时:60 秒(与 proxy_handler 共用 `PROXY_DEFAULT_TIMEOUT`)。
> 📖 安全审查报告:`references/security-review-2026-07.md`
> 📜 Windows 直连测试脚本:`scripts/hubstudio-cdp-direct-test.py`
## 安全特性
### evaluate() 封禁
`hubstudio_cdp.evaluate` 在 Bridge 路由层已封禁(与 `playwright.execute` 一致的安全策略)。
任何通过 Bridge 发送的 `hubstudio_cdp.evaluate` 命令都会返回错误:
`"hubstudio_cdp.evaluate is not available via Bridge (arbitrary JS execution risk)"`
如需在 HubStudio Chrome 中执行 JS,必须在 Desktop 本机通过 `HubStudioCDPController.evaluate()` 内部调用。
### SSRF 防护
所有导航命令(`hubstudio_cdp.navigate` / `playwright.navigate` / `ziniao.screenshot`
共用 `isPrivateHost()` 方法进行内网地址检测,拒绝以下目标:
- localhost / 127.0.0.1 / 0.0.0.0 / ::1 / [::1]
- 10.x / 172.16-31.x / 192.168.x / 169.254.xRFC 1918 + link-local
- IPv4-mapped IPv6 地址(`::ffff:127.0.0.1` 等)
### CDP Session 管理
`hubstudio_cdp.snapshot` 使用 `try/finally detach` 确保 CDPSession 不泄漏。
节点数上限 5000,超出自动截断(防大型页面 OOM)。
### 并发安全
`HubStudioCDPController.connect()` 使用 `pendingConnects` Map 防止同一 envCode
的并发连接导致 Browser 对象泄漏。
## 操作纪律
1. **串行操作**:多环境操作默认串行,避免资源冲突
2. **操作间隔**:启停环境间至少间隔 2 秒
3. **进程清理**:操作完成后关闭不需要的环境释放资源
4. **凭证安全**APP_SECRET 不写入日志、不暴露在 shell 命令中
5. **推送注册表**:新增或修改 server 端 skill 后,必须同步推送到 Gitea 注册表,否则 Desktop 看不到
6. **Windows 直连用 DrissionPage**:连接 HubStudio 独立 Chrome 时,优先用 `DrissionPage``pip install DrissionPage`),无需额外安装浏览器。Playwright 需要 `playwright install chromium`(下载 ~150MB),仅在 DrissionPage 不兼容时回退。
## 常见坑
1. **🛑 Bridge 重启后 Desktop WS 断开,需手动重启 Desktop**`systemctl restart cloud-bridge` 会断开所有 Desktop WS 连接。Desktop 不会自动重连(需用户手动重启 Desktop App)。重启后 slot ID 会变化(如 `desktop-mr2xlvo9``desktop-mr372rlv`),需重新从 `/health` 发现新 slot。
2. **🛑 list_envs 返回空可能是凭证问题,不是代码 bug**:`hubstudioAvailable: true` 只表示 API 可达。如果 HubStudio API 返回空环境列表(`envCount: 0`),检查 Desktop Chrome Bridge 页面的 HubStudio 凭证(App ID / App Secret)是否正确。凭证存储在 Windows 本机 `~/.atomk/hubstudio.json`Electron safeStorage 加密),不在 Bridge 服务器上。
3. **🛑 HubStudio CDP 端口仅在 Windows 本机可达**HubStudio Chrome 的 `debuggingPort`(如 58289)绑定在 `127.0.0.1`BridgeLinux)无法直连。所有 CDP 操作必须通过 Desktop 的 `HubStudioCDPController` 中转。Windows 本地测试可用:`Chromium(addr_or_opts='127.0.0.1:58289')`
4. **🛑 DrissionPage pip install 需 `--user`(无管理员权限时)**`pip install --user DrissionPage` — 直接 `pip install``C:\Python310` 下可能触发 `PermissionError`
5. **🛑 opened_envs 返回 E010006 → 可能是零环境,不是认证错误**:`hubstudio.opened_envs` 返回 `ok: false, error: "internal_error", message: "getOpenedEnvs 失败: code=E010006"` 时,如果同时 `hubstudio.list_envs` 也返回空列表且 `hubstudio.status` 返回 `hubstudioAvailable: true, envCount: 0`,说明 HubStudio API 连接正常但账户下没有任何浏览器环境。这不是凭证问题——应先指导用户在 HubStudio 客户端创建浏览器环境,然后再重试。
6. **🛑 hubstudio_cdp.* 命令超时 = Desktop 代码版本不匹配**:命令超时(60s 无响应)的最常见原因是 Desktop 在运行构建版 `.exe` 而非 `npm run dev` 开发模式。构建版不含最新合并的 `hubstudio-cdp-controller.ts`。解决:`npm run dev` 热加载最新代码,或 rebuild Desktop。
7. **🛑 Desktop rebuild 触发条件**:只改 `src/main/` 下的 TypeScript 在 dev 模式无需 rebuild。只有改 `src/renderer/` 或需要分发包时才需要完整 build。
8. **🛑 Bridge 重启不自动更新 Desktop 代码**:`systemctl restart cloud-bridge.service` 只重启 Bridge Server(使 `/api/command` 等新端点生效)。Desktop 侧的代码更新需 Desktop App 重启(dev 模式热加载)或 rebuild。
9. **🛑 hubstudio_cdp.connect 端口校验**`hubstudio_cdp.connect` handler 强制校验 port 为 1-65535 的数字(`typeof port !== 'number'`),字符串会被拒绝。`open_env` 返回的 `debuggingPort` 是字符串,Desktop 内部已做 `parseInt` 转换。
11. **🛑 SOCKS5 代理延迟(中国→境外)**HubStudio 环境使用境外 SOCKS5 代理时,`hubstudio_cdp.*` CDP 操作非常慢(30-90s)。Cloud Bridge 会话中 browser_console fetch() 的 30s 硬超时会导致所有 CDP 命令超时。`hubstudio.open_env` 等管理命令仍是快速的。解决方案:用 cron no_agent 脚本 + urllib.request(timeout=90) 执行 CDP 操作。详见 `bridge-cdp-agent``references/hubstudio-cdp-socks5.md`
① Desktop 代码版本 — 确认运行的是含 `hubstudio-cdp-controller.ts` 的版本(v4.0.17+),检查 health 返回的 version 字段
② Bridge 代码版本 — 确认 `cloud-bridge/server.py``/api/command` 端点(`grep command_handler server.py`
③ Bridge 是否重启 — `/api/command` 端点生效需 `sudo systemctl restart cloud-bridge.service`(注意:重启会导致 Desktop WS 断开)
④ 构建产物含 handler — `grep "hubstudio_cdp" out/main/index.js` 确认编译正确
⑤ Desktop DevTools Console — 搜索 `[Router]` 看 handler 是否被调用、是否有 JS 错误
⑥ 对比 `playwright.status`(应正常)vs `hubstudio_cdp.status`(超时)— 两者同路径,差异说明问题在 MessageRouter handler 层而非路由层
**🔴 bridge-manager.ts 路由守卫遗漏 `hubstudio_cdp.*` — 字符串前缀不匹配**
`src/main/bridge-manager.ts` L443 的路由条件只检查 `action.startsWith('hubstudio.')`(带**点**),
`hubstudio_cdp.*` 命令使用**下划线**连接(`hubstudio_cdp.status`)。
`'hubstudio_cdp.status'.startsWith('hubstudio.')`**false** → 命令被路由守卫拦截,
掉入 `switch(action)` 无匹配项 → 静默丢弃 → 不发送 `command_response` → Bridge 等 60s 超时 → 504。
**修复**:在 L443 添加 `|| action.startsWith('hubstudio_cdp.')`
PR #14 (commit `89e8c8d`) 已在 2026-07-03 修复,合入 Desktop **v4.0.18+**
**诊断脚本**`scripts/hubstudio-cdp-routing-test.py` — 一键测试三个命令并输出诊断结论。
**诊断实录**`references/hubstudio-cdp-routing-504-diagnosis.md` — 完整的五步诊断过程。
**验证方式**`hubstudio.status`✅ + `playwright.status`✅ + `hubstudio_cdp.status`❌504 = 本 bug。
常见根因(按概率排序):
(a) **bridge-manager.ts 路由守卫遗漏 hubstudio_cdp 前缀**(本项 ⑦)— 源码层面 bugDesktop dev/exe 都受影响
(b) Desktop 运行构建版 .exe 而非最新 dev 代码 — 构建版不含 hubstudio-cdp-controller.ts
(c) Bridge 未重启不含 /api/command 端点