Files

7.8 KiB
Raw Permalink Blame History

适配器标准:真实/仿真 × API/RPA 四档模式

凡是"连接三方系统"(ERP、CRM、SaaS、银行等)的 skill,都应采用本文的 adapter 四档模式。同一套业务逻辑可在不同档位间切换;四档都保留。

先遵守 AI_RPA.md 的授权与技术红线:real_api 只连接公开或明确授权的官方接口;不得通过抓包、逆向或猜测私有协议构造“API”。没有授权 API 时使用正常界面 RPA;正常界面无法闭环且只能绕过安全机制时,停止并上报。

为什么要分档

对接一个外部系统,工程上无非四种方式的组合:

API(有接口) RPA(操作界面)
真实系统 real_api 真实 API real_rpa 真实界面
仿真/离线 mock 纯内存/fixture simulator_rpa 仿真站点/桌面仿真

四档定义

档位 含义 默认策略
mock 纯内存或 fixture,离线 单测 / CI 必过;mock 不通不要往下走
simulator_rpa 仿真站点或桌面仿真,可半集成 按业务场景选用
real_api 真实 API 按业务场景选用(有官方接口时)
real_rpa 真实浏览器/真实系统 模板 .env.example 默认;业务自测与交活用此档
  • mock:纯离线、不联网,给单测 / CI,保证可重复。mock 通 ≠ 开发完成。
  • simulator_rpa:操作仿真平台(如 sandbox.jc2009.com),按场景选用。
  • real_api:有官方接口时按场景选用。
  • real_rpa:真实浏览器路径;模板默认,须真实跑通后再交活。

口径:业务配置默认 real_rpa;单测/CI 用 mock。不得只 mock 通就交活;须 release 到匠厂宿主验收(含用户体验)。

配置读取见 CONFIG.md:bootstrap 之后业务代码只通过 config.get*() 读 OPENCLAW_TEST_TARGET 等项(进程 env > 用户 .env > .env.example)。

目录骨架

scripts/service/<domain>_adapter/
  __init__.py        # dispatch:按档位返回对应 adapter 实例
  base.py            # 数据契约(dataclass)+ AdapterBase 接口
  mock.py            # 离线仿真,给 CI/单测
  real_api.py        # 真实系统 API
  sim_rpa.py         # 薄仿真平台 RPA adapter(委托 *_playwright.py)
  real_rpa.py        # 真实系统 RPA(占位,谨慎实现)

scripts/service/
  <platform>_playwright.py   # RPA 主流程(厚);与薄 sim_rpa.py 并列
  account_client.py            # account-manager subprocess 唯一封装
  browser_session.py           # async persistent context 启动

模板示例(均在 examples/,不在 scripts/):

  • 仿真浏览器 RPA 完整案例:examples/simulator_browser_rpa/ — async mock + simulator_rpa + simulator_playwright.py + sandbox 页面 + adapter 分层 + 测试
  • 真实浏览器 RPA 完整案例:examples/real_browser_rpa/ — 登录/验证码/滚动采集 + account_client.py
  • 真实 API / 仿真 API:examples/real_api/、examples/simulator_api/ — 当前为规划占位,尚未沉淀可复制实现

复制 adapter 分层时,以修正后的 examples/simulator_browser_rpa/(薄 adapter + simulator_playwright.py)与 examples/real_browser_rpa/scripts/service/account_client.py 为权威参考,在新技能中创建 scripts/service/<domain>_adapter/ 并按 README copy map 选择性复制。

先判断属于四象限哪一种(real_browser_rpa / real_api / simulator_browser_rpa / simulator_api),再读对应 examples/*/README.md。示例是参考架构与边界,不是业务代码原样复制。

档位 dispatch

由 OPENCLAW_TEST_TARGET 统一决定用哪个 adapter:

OPENCLAW_TEST_TARGET adapter 用途
unit / mock MockAdapter 单测 / CI,离线
simulator_rpa SimRpaAdapter 开发/演示,操作仿真平台
real_api RealApiAdapter 生产,走官方接口
real_rpa RealRpaAdapter 生产,操作真实界面
# __init__.py
from jiangchang_skill_core import config

def get_adapter():
    target = (config.get("OPENCLAW_TEST_TARGET") or "real_rpa").lower()
    if target in ("unit", "mock"):
        return MockAdapter()
    if target == "real_api":
        return RealApiAdapter()
    if target == "real_rpa":
        return RealRpaAdapter()
    return SimRpaAdapter()

get_adapter() 实现应配合 tests/adapter_test_utils.py 的 profile 策略:默认必跑测试不得误设 OPENCLAW_TEST_TARGET=real_*。

contract tests

每个 adapter 必须覆盖同一套契约测试(复制 tests/samples/test_service_contract.py.sample):

  • 至少覆盖:timeout、unauthorized、invalid response、empty result
  • mock 不允许真实网络
  • 使用 FakeAdapter 或等价 stub 模拟异常路径

兄弟依赖

依赖 account-manager 或其他兄弟技能时:

  1. 在 SKILL.md 的 metadata.openclaw.dependencies.required 声明。
  2. 普通兄弟技能调用,优先走统一 service.sibling_bridge(call_sibling_json),不要在 task_service.py、task_rpa.py 等业务流程文件中到处散落 subprocess.run。
  3. account-manager 账号/租约能力是例外:可参考 examples/real_browser_rpa/scripts/service/account_client.py 与 examples/simulator_browser_rpa/scripts/service/account_client.py,封装为单一 account_client.py;允许在该文件内部集中通过 subprocess 调 account-manager CLI。禁止 import rpa_helpers 等 account-manager 内部模块;simulator_rpa 与 real_rpa 均走同一 pick_web_account / release_lease 模式。
  4. 不允许直接 import account-manager 的内部 Python 模块(如 service/、util/、db/)。
  5. 所有选择路径都必须取得 lease:包括纯数字 DEFAULT_ACCOUNT_ID。account get <id> 只能读取账号,不能单独作为运行结果;必须再通过可定位该账号的 pick 流程取得非空 lease_token。随后必须 finally release lease;进程被 kill 后可能残留 lease,需按 ACCOUNT_MANAGER.md 排查。
  6. 网页 RPA 硬规则(详见 RPA.md §0.2):必须先经 pick_web_account(底层 ensure-web / pick-web --ensure)拿到 profile_dir 再开浏览器;拿不到则失败退出;生产有头;是否站点登录按平台约定,但不等于可以跳过 account-manager。登记账号 ≠ 站点已登录。
  7. 账号选择优先级:纯数字 DEFAULT_ACCOUNT_ID → 校验指定账号后带租约 pick;DEFAULT_LOGIN_ID / 非数字标识 → ensure-web --login-id --lease;皆空 → 按平台 ensure-web --lease。人读展示优先 login_id / account_label,不要只用数字 id。多条匹配或无法确保拿到指定 ID → ERROR:AMBIGUOUS_ACCOUNT。
  8. 运行前校验:profile_dir 和 lease_token 均须非空;账号平台必须匹配;缺任一字段立即失败,不打开浏览器。
# 普通兄弟技能 — 走 sibling_bridge
from service.sibling_bridge import call_sibling_json

result = call_sibling_json("account-manager", ["list", "--limit", "10"])
# account-manager 账号/租约 — 集中在 account_client.py(ensure-web)
from service.account_client import pick_web_account, release_lease

account = pick_web_account(platform="target_platform", login_id=None)
try:
    ...
finally:
    release_lease(account.get("lease_token"))

相关文档

  • RPA.md — 三端 RPA 技术选型与拟人/反反爬范式
  • ACCOUNT_MANAGER.md — 账号、Profile、租约、多账号、查看与排障标准
  • CONFIG.md — .env 里如何配置运行模式与目标地址
  • TESTING.md — 测试 target 与隔离体系