Files
skill-template/references/ADAPTER.md

4.6 KiB
Raw Blame History

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

凡是"连接三方系统"ERP、CRM、SaaS、银行等的 skill都应采用本文的 adapter 四档模式。这样同一套业务逻辑可以在不同档位间切换开发用仿真、CI 用 mock、上线用真实互不影响。

为什么要分档

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

API有接口 RPA操作界面
真实系统 real_api 真实 API real_rpa 真实界面
仿真系统 mock 离线仿真 sim_rpa 仿真平台界面
  • mock:纯离线、不联网,给单测 / CI / 开发自测,保证可重复
  • sim_rpa:操作仿真平台(如 sandbox.jc2009.com),跑真实端到端流程但不碰生产,默认开发档位
  • real_api:有官方接口时首选(最稳、最快、最易维护)。
  • real_rpa:没有 API 只能操作生产界面,风险最高、放最后

推荐优先级:real_api > sim_rpa > real_rpamock 永远保留做 CI。

目录骨架

业务逻辑只依赖 base 里定义的接口与数据契约,具体档位实现各自一个文件:

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

参考实现:disburse-payroll-icbc/scripts/service/disburse_adapter/(已有 base.py / mock.py / icbc_simulator_rpa.py)。 模板示例:scripts/service/example_adapter/(复制改名即用)。

引用方式

from service.example_adapter import get_adapter
from service.example_adapter.base import ExampleItem

adapter = get_adapter()  # 由 OPENCLAW_TEST_TARGET 决定档位
result = adapter.do_batch(
    target="https://sandbox.jc2009.com",
    items=[ExampleItem(id="1", label="demo")],
)

mock 档位纯离线验证:

set OPENCLAW_TEST_TARGET=mock
python -c "import sys; sys.path.insert(0,'scripts'); from service.example_adapter import get_adapter; from service.example_adapter.base import ExampleItem; r=get_adapter().do_batch('x',[ExampleItem('1','a')]); print(r.ok, r.serial_no)"

base.py 写法(要点)

  1. 数据契约用 @dataclass:输入项(如 PayrollItem)、批量结果(如 BatchResult{ok, serial_no, error_msg, artifacts})。
  2. 接口方法抛 NotImplementedError:所有档位实现同一签名。
  3. 以"批"为单位返回:真实 RPA 往往是整批提交,结果按批次返回,不要假设逐条。
  4. 结果里带 artifacts:截图/录屏/日志路径,便于排查。
@dataclass
class XxxResult:
    ok: bool
    serial_no: Optional[str]
    error_msg: Optional[str]
    artifacts: Dict[str, Any] = field(default_factory=dict)

class AdapterBase:
    name = "base"
    def do_batch(self, target: str, items: list) -> XxxResult:
        raise NotImplementedError

档位 dispatch

OPENCLAW_TEST_TARGET 统一决定用哪个 adapter与现有测试体系一致

OPENCLAW_TEST_TARGET adapter 用途
unit / mock MockAdapter 单测 / CI离线
simulator_rpa(默认) SimRpaAdapter 开发/演示,操作仿真平台
real_api RealApiAdapter 生产,走官方接口
real_rpa RealRpaAdapter 生产,操作真实界面(最后手段)
# __init__.py
def get_adapter():
    target = (os.environ.get("OPENCLAW_TEST_TARGET") or "simulator_rpa").lower()
    if target in ("unit", "mock"):
        return MockAdapter()
    if target == "real_api":
        return RealApiAdapter()
    if target == "real_rpa":
        return RealRpaAdapter()
    return SimRpaAdapter()   # 默认

实际可改为读 .env 里的运行模式(见 CONFIG.mdOPENCLAW_TEST_TARGET 作为进程级覆盖优先。

测试要求

  • mock 档必须能纯离线跑通,进 CI。
  • 每个 adapter 单测同一组用例(契约测试),保证档位间行为一致。
  • RPA 档的真实联网测试单独标记,不进默认 CI参考 tests/desktop/)。

相关文档

  • RPA.md — 三端 RPA 技术选型与拟人/反反爬范式
  • CONFIG.md.env 里如何配置运行模式与目标地址
  • TESTING.md — 测试 target 与隔离体系