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

19 KiB
Raw Blame History

name, description, version, author, metadata
name description version author metadata
hubstudio-bridge HubStudio 浏览器环境 AI 自动化 — 通过 Hermes + Desktop Bridge 操控 HubStudio 浏览器环境/云手机,自然语言驱动:列出环境、启动环境、获取调试端口、对接 Playwright/Selenium。 1.3.0 Hermes Agent
hermes
tags related_skills cron_compatible
hubstudio
浏览器环境
云手机
browser-automation
cross-border
ziniao-bridge
bridge-cdp-agent
drissionpage-toolkit
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 侧新增 HubStudioCDPControllersrc/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.mdOpenClaw 技能包, 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.tsElectron 主进程,无 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}

返回示例:

{
  "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
}

返回:

{
  "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.tsElectron 主进程,无 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.jsonElectron 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/sendTarget.createTarget 直接创建新 tab

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。

请求格式

{
  "action": "hubstudio.open_env",
  "params": {"containerCode": "xxx"},
  "id": "optional-custom-id"
}

响应格式

{
  "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 时,优先用 DrissionPagepip install DrissionPage),无需额外安装浏览器。Playwright 需要 playwright install chromium(下载 ~150MB),仅在 DrissionPage 不兼容时回退。

常见坑

  1. 🛑 Bridge 重启后 Desktop WS 断开,需手动重启 Desktopsystemctl restart cloud-bridge 会断开所有 Desktop WS 连接。Desktop 不会自动重连(需用户手动重启 Desktop App)。重启后 slot ID 会变化(如 desktop-mr2xlvo9desktop-mr372rlv),需重新从 /health 发现新 slot。
  2. 🛑 list_envs 返回空可能是凭证问题,不是代码 bughubstudioAvailable: true 只表示 API 可达。如果 HubStudio API 返回空环境列表(envCount: 0),检查 Desktop Chrome Bridge 页面的 HubStudio 凭证(App ID / App Secret)是否正确。凭证存储在 Windows 本机 ~/.atomk/hubstudio.jsonElectron safeStorage 加密),不在 Bridge 服务器上。
  3. 🛑 HubStudio CDP 端口仅在 Windows 本机可达HubStudio Chrome 的 debuggingPort(如 58289)绑定在 127.0.0.1BridgeLinux)无法直连。所有 CDP 操作必须通过 Desktop 的 HubStudioCDPController 中转。Windows 本地测试可用:Chromium(addr_or_opts='127.0.0.1:58289')
  4. 🛑 DrissionPage pip install 需 --user(无管理员权限时)pip install --user DrissionPage — 直接 pip installC:\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 转换。
  10. 🛑 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-agentreferences/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.status504 = 本 bug。 常见根因(按概率排序): (a) bridge-manager.ts 路由守卫遗漏 hubstudio_cdp 前缀(本项 ⑦)— 源码层面 bugDesktop dev/exe 都受影响 (b) Desktop 运行构建版 .exe 而非最新 dev 代码 — 构建版不含 hubstudio-cdp-controller.ts (c) Bridge 未重启不含 /api/command 端点