PRA-only-demo/docs/rpa-core-migration-guide.md
yu 230e3c79ec docs: 平台标记单一源规则与迁移指南通俗版;补交 Word 报告流程生成脚本
- dev-conventions:平台标记收敛为注册分组表单一源,能力文件不得散写 process.platform
- rpa-core-migration-guide:重写为通俗版(现状/搬迁步骤/三端计划)
- gen-word-flow.py:Word 报告加工流程生成脚本(此前漏交)
2026-11-05 17:02:10 +08:00

14 KiB
Raw Blame History

rpa-core 迁入 Agent-Employee 指南(通俗版)

这是一份什么文档?

我们花了两周把 RPA 的"能力层"(跑流程用的几百个能力 + 流程引擎)从现在这个 demo 项目里抽出来, 做成了一个独立软件包,叫 @rpa/core,放在本仓库的 packages/rpa-core/ 目录。

为什么要抽出来? 因为这个包以后要搬到另一个项目 Agent-Employee 里用。 抽成独立包的好处:搬过去时不用改一行代码,两边也不用维护两份一样的代码。

这份文档讲什么? 讲三件事:

  1. 这个包现在长什么样(现状)
  2. 到时候怎么搬过去(操作步骤)
  3. 以后要支持 Mac 和 Linux 怎么办(三端计划)

配套文档:docs/rpa-core-refactor-tasks.md(当时的改造任务清单)、docs/dev-conventions.md(日常开发规范)、packages/rpa-core/README.md(包的技术说明书)。


一、现状:包已经是什么样了

改造已全部完成并合入 main 分支(6 个阶段提交,4139400..a8084dc)。现在:

你可能想知道的 答案
包在哪? packages/rpa-core/,包名 @rpa/core
里面有什么? 流程引擎(跑流程的循环/变量/错误处理)+ 719 个能力(文件/Excel/HTTP/数据库/邮件/桌面操作等)
它依赖 Electron 吗? 完全不依赖。有脚本 npm run check:deps 天天检查,谁往里加 Electron 代码就报错
它怎么用 Electron 的功能? 见下面"宿主桥"的解释
怎么证明它能独立跑? npm run rpa-cli:不启动 Electron,直接跑通 5 个代表能力(桌面点击/Excel/HTTP/文件/屏幕)

几个名词解释(后文会反复出现):

  • 宿主:使用这个包的应用程序。现在宿主是本 demo(Electron 应用),以后宿主是 Agent-Employee。
  • 宿主桥(HostBridge):包偶尔需要"只有应用程序才有"的功能,比如弹一个窗口、读取 AI 配置。 包不直接去拿,而是定了一个接口说"谁来用我,谁把这几个功能递给我"。 宿主启动时调用 setHostBridge(...) 把功能递进来。目前一共只有 4 个功能要递: 弹窗、两组屏幕坐标换算、读 AI 配置。另有 setSubflowSource(...) 递子流程仓库(2 个方法)。
  • 驱动(Driver):真正干"动鼠标、敲键盘、找窗口"这些活的模块。现在的实现叫 WindowsDriver(用 PowerShell 实现)。 能力层不直接碰 PowerShell,而是喊"driver,帮我把鼠标移到 x,y"——所以以后要做 Mac 版,只需要再写一个 MacDriver,能力层一行不用改。

二、到时候怎么搬:三步走

第 -1 步:先知道对面已经有什么(2026-11-05 实地调研)

Agent-Employee(D:\code\Agent-Employee)是 Electron + SolidJS 客户端 + Bun 执行面 + Java 控制面的结构, 前端 code/frontend、后端 code/backend 是两个独立的 bun workspace(bun@1.4.3,workspaces 含 apps/*、packages/*、services/*)。

关键事实:对面已经为我们要搬的东西铺好了契约,但还没有实现。code/backend/packages/ 下有一批契约包(每个只有 1-9 个声明文件):

对面现有契约包 它声明了什么 与 @rpa/core 的关系
workflow-engine workflow / step / approval / failure 状态模型(9 个文件,依赖 plugin-contract、capability-gateway、event-bus) rpa-core 的 runtime 是它的执行引擎候选,迁入时需做状态模型对齐(审批/失败/证据如何挂到我们 RunResult/NodeState 上)
capability-gateway 所有带副作用的能力执行前必须过:授权 → 租约签发 → 租约校验 → 执行约束;契约含 CapabilityRunner / authorize() / execute() 权限治理(6.4)的现成落点。rpa-core 能力执行要包进这个网关,而不是自建 allowlist
computer-control 跨平台观察、定位、动作抽象与桌面会话策略 rpa-core 五域 driver 是它的实现候选;三端设计(第三节)应对齐这份契约
windows-plugin Windows 目标、桌面会话策略、输入类高影响能力、执行器接口 WindowsDriver 的接入契约
browser-plugin 浏览器动作、域名白名单、高影响能力审批边界、证据机制 demo 侧浏览器能力的对面契约
runtime-governance / plugin-contract 运行时治理 / 插件契约 治理对接的参考
services/windows-runner Windows 交互 Runner(空壳,0 个源文件) 对面 README 已明确"Windows 交互 Runner 留在宿主,不放入 Linux 容器"——与 rpa-core 桌面能力只能跑在 Windows 交互会话的约束天然一致

结论:迁入的本质不是"新写一套宿主适配",而是"拿 rpa-core 的实现去填对面的契约"。 这比原计划省了适配层设计,但多了一步契约对齐(接口签名互相对照,差异列清单评审)。

第 0 步:搬家之前,在 demo 里先补三件作业

这些事当时刻意延后了,搬家前必须补上(都在本仓库做,改起来便宜):

  1. Bun 冒烟测试。Agent-Employee 用 Bun 跑代码,我们一直用 Node。 搬过去第一件事:用 bun test 跑包里的纯逻辑测试,确认 exceljs、pdf-lib 这些库在 Bun 下行为一致, 尤其是调 PowerShell 的部分(编码处理容易有差异)。
  2. 重新生成能力目录。跑一次 npm run catalog,让每个能力带上 platformTag: "win32" 标记 (标记逻辑早就写好了,当时因为数据源不在这台机器上没生效)。
  3. 决定用哪种注册方式。包支持两种注册能力的方式: 旧方式 import "@rpa/core/capabilities"(一导入全注册),新方式 await registerAll(engine)(想注册哪几组就注册哪几组)。 建议 Agent-Employee 直接用新方式,旧的以后可以废掉。

第 1 步:搬包(半天)

  1. 评审:按 Agent-Employee 团队的流程提交一份架构决策记录(ADR),内容就是本文档第一节 + 对面契约对照表 + 包的 README,不用另写。
  2. 搬代码:把 packages/rpa-core/ 整个目录用 git 方式搬进 code/backend/packages/rpa-core (执行面归 backend workspace;对面 bun@1.4.3 的 workspaces 已含 packages/*,放进去即生效)。 用 git subtree 之类保留提交历史,千万不要复制文件夹另起炉灶——两份代码会越走越远。
  3. 包名决策:对面 backend 包统一用 @agent-worker/* 前缀(如 @agent-worker/plugin-contract)。 建议迁入时改名 @agent-worker/rpa-core(一次 commit 完成 rename,包内代码不用动)。
  4. 处理 demo 侧:搬走之后 demo 要么改成只读引用,要么归档。两边不能同时活跃改代码。

第 2 步:契约对齐 + 宿主适配(核心工作量)

分两类工作:

A. 契约对齐(对面已铺好,我们填实现)——逐个对照,差异列清单评审后改:

对面契约 对齐内容
capability-gateway 把 rpa-core 的能力执行包进 authorize() / execute() 流程(CapabilityRunner 接口);危险能力(System_ExecuteCommand、键鼠注入等)走它的租约与审批,不再自建 allowlist
workflow-engine 状态模型对齐:我们 RunResult/NodeState(running/succeeded/failed/...)对照它的 workflow/step/approval/failure;人工审批节点(human-dialog)要能挂进它的 approval 流
computer-control / windows-plugin 五域 driver 的观察/定位/动作抽象与它们契约互相对照;WindowsDriver 作为执行器接入
browser-plugin 浏览器能力对齐域名白名单与审批边界

B. 宿主注入(照旧要做,但工作量变小):

要递什么 干什么用 工作量
setHostBridge 4 个方法 弹窗、DPI 坐标换算、读 AI 配置 小。对面也是 Electron(code/frontend/apps/desktop),参考实现照抄本仓库 src/main/index.ts 第 28-50 行
setSubflowSource 2 个方法 子流程的存与取 小。对面有自己的流程存储,包一层即可
内置浏览器(BrowserLike 接口) "浏览器打开网址/点按钮/填表单"这组能力需要宿主提供浏览器 不确定,是最大变数。对面的浏览器方案还没定型(browser-plugin 只是契约);需与对面团队评审后再估工作量
AI 能力配置 ai-caps.ts 需要 baseUrl/apiKey 等 小。对面有模型网关(model-gateway),接它的配置面

不搬的东西(留在 demo / 由 Agent-Employee 重新做): 界面渲染层、悬浮框/取色器、本地视觉(onnxruntime 那套)、流程存储、内置浏览器编排。 完整清单见包 README 的「Electron 相关能力留守清单」。

第 3 步:验收(搬家算不算成功,看这 7 条)

  1. bun test 包内纯逻辑测试全绿;
  2. npm run rpa-cli 的等价物在 Bun 下跑通 5 个代表能力;
  3. 能力注册数对得上(包内 719 个);
  4. check:deps 通过(没人在搬家过程中偷偷加回 Electron);
  5. 真实操作一遍:弹一次人机对话框、高分屏上拖一次窗口、调一次 AI——验证宿主桥三条路径通了;
  6. 契约对齐有书面结论:capability-gateway(能力执行进网关)、workflow-engine(状态模型)、computer-control(driver 抽象)三份对照清单各评审通过;
  7. demo 侧(如果还保留)测试全绿。

三、以后要支持 Mac 和 Linux 怎么办?

好消息:当初设计时已经把口子留好了——能力层只对"驱动接口"说话,不关心底下是 Windows 还是 Mac。 所以三端化不用推翻任何东西,分两批做:

搬家之前(demo 侧,5 件小事)

# 事项 说明
1 平台标记统一机制(三端优先 win) 平台归属收敛为一处权威数据:register-all.ts 分组表 PLATFORM_GROUPS。三个平台类型都能填,但数据只填 win32,darwin/linux 仅类型占位;meta.platforms(运行时)与 catalog platformTag(构建期)都从这张表派生,build-catalog.mjs 删掉自带的 WIN32_GROUPS 硬编码;加一致性守卫测试,两处不一致 CI 直接红
2 驱动改成按系统自动选 现在写死 new WindowsDriver();改成看 process.platform 自动选,Mac/Linux 上没实现就明确报"该平台暂不支持"(加个 platform_unsupported 错误码)
3 检查能力分组 Excel COM、Word COM 这些 Windows 专属能力,确保归在能整组过滤的分组里——将来 Mac 版就不注册这组
4 测试加平台守卫 现在只有 4 个测试文件写了"非 Windows 就跳过",键盘/鼠标/窗口冒烟测试没写。补齐后,Mac/Linux 的 CI 才能跑(跑纯逻辑部分,跳过真桌面操作)
5 开发规范加一条 禁止在能力文件里随手写 process.platform 判断(现在 utility-extended 里已有 2 处,收拢到固定位置),防止平台差异到处扩散

搬家之后(Agent-Employee 侧,按平台写驱动)

  1. 先对齐对面的 computer-control 契约:对面已声明"跨平台观察、定位、动作抽象"的契约(还是空壳)。 写 MacDriver / LinuxDriver 之前,先让五域 driver 接口与这份契约对表,避免两边各长各的。
  2. 写 MacDriver / LinuxDriver(接口现成,按五个域补实现):
    • Linux:鼠标键盘用 xdotool(X11);Wayland 支持受限,是三端里最难的坑;界面元素识别走 AT-SPI;
    • Mac:鼠标键盘用 cliclick 或 CGEvent;窗口操作走 AppleScript;界面元素走 AX 辅助功能 API。
  3. 先评估 macOS 权限问题:Mac 上 RPA 软件必须引导用户开"辅助功能/屏幕录制"授权(系统 TCC 机制), 这是 Mac 端最大的部署摩擦,做之前先摸清。
  4. Office 替代方案:Excel/Word 的 COM 自动化只有 Windows 有。Mac 可走 AppleScript + Office, Linux 可走 LibreOffice;或者第一版直接标注"仅 Windows"。
  5. 浏览器路径:外部浏览器启动路径现在写死了 Windows 的(C:\Program Files\...),要补 Mac/Linux 的路径表。
  6. 剪贴板等小件:PowerShell 换成 pbpaste/pbcopy(Mac)、xclip(Linux)。
  7. CI 三个平台各跑一遍;产品界面按能力标注的平台支持情况置灰不支持的项。

一条原则

平台标记必须统一,这是硬约束(三端优先 win):

  • 平台归属只有一处权威数据:包内注册分组表 PLATFORM_GROUPS(33 个能力组 × 平台数组)。
  • 运行时的 meta.platforms 和构建期的 catalog platformTag 都从这张表自动派生,任何代码不得自行声明第二份平台数据。
  • 数据里今天只有 win32;darwin/linux 只存在于类型枚举里占位,不填任何数据。
  • 将来支持新平台 = 新增能力分组 + 表里加一行,仅此而已;守卫测试保证两处派生永远一致,谁绕过就红。

平台差异只允许出现在两个地方:driver/<平台>/ 目录下的驱动实现,以及极少数白名单能力文件。 引擎、注册表、能力接口、宿主桥,永远保持平台无关。


附:当时的 10 个关键决策(搬家时不要再讨论一遍)

# 决策
1 代码物理搬移(git mv),不是留着引用
2 保留全局注册表;进程级状态收进 createEngine() 工厂
3 集中突击改造,不搞长期双轨
4 宿主桥只留 4 个方法(弹窗 / DPI×2 / AI 配置),能不加就不加
5 浏览器:外部浏览器(CDP)进包,内置浏览器留宿主
6 驱动接口五域划分(鼠标/键盘/窗口/屏幕/元素),Windows 实现原样包装、行为不变
7 能力目录只填平台标记数据,界面置灰以后再说
8 能力元数据(meta)老能力可选、新能力强制
9 注册双入口过渡(副作用导入 + registerAll 显式注册)
10 Bun 冒烟测试延期到搬家时做(本文第二节第 0 步)