- dev-conventions:平台标记收敛为注册分组表单一源,能力文件不得散写 process.platform - rpa-core-migration-guide:重写为通俗版(现状/搬迁步骤/三端计划) - gen-word-flow.py:Word 报告加工流程生成脚本(此前漏交)
14 KiB
rpa-core 迁入 Agent-Employee 指南(通俗版)
这是一份什么文档?
我们花了两周把 RPA 的"能力层"(跑流程用的几百个能力 + 流程引擎)从现在这个 demo 项目里抽出来,
做成了一个独立软件包,叫 @rpa/core,放在本仓库的 packages/rpa-core/ 目录。
为什么要抽出来? 因为这个包以后要搬到另一个项目 Agent-Employee 里用。 抽成独立包的好处:搬过去时不用改一行代码,两边也不用维护两份一样的代码。
这份文档讲什么? 讲三件事:
- 这个包现在长什么样(现状)
- 到时候怎么搬过去(操作步骤)
- 以后要支持 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 里先补三件作业
这些事当时刻意延后了,搬家前必须补上(都在本仓库做,改起来便宜):
- Bun 冒烟测试。Agent-Employee 用 Bun 跑代码,我们一直用 Node。
搬过去第一件事:用
bun test跑包里的纯逻辑测试,确认 exceljs、pdf-lib 这些库在 Bun 下行为一致, 尤其是调 PowerShell 的部分(编码处理容易有差异)。 - 重新生成能力目录。跑一次
npm run catalog,让每个能力带上platformTag: "win32"标记 (标记逻辑早就写好了,当时因为数据源不在这台机器上没生效)。 - 决定用哪种注册方式。包支持两种注册能力的方式:
旧方式
import "@rpa/core/capabilities"(一导入全注册),新方式await registerAll(engine)(想注册哪几组就注册哪几组)。 建议 Agent-Employee 直接用新方式,旧的以后可以废掉。
第 1 步:搬包(半天)
- 评审:按 Agent-Employee 团队的流程提交一份架构决策记录(ADR),内容就是本文档第一节 + 对面契约对照表 + 包的 README,不用另写。
- 搬代码:把
packages/rpa-core/整个目录用 git 方式搬进code/backend/packages/rpa-core(执行面归 backend workspace;对面 bun@1.4.3 的 workspaces 已含packages/*,放进去即生效)。 用git subtree之类保留提交历史,千万不要复制文件夹另起炉灶——两份代码会越走越远。 - 包名决策:对面 backend 包统一用
@agent-worker/*前缀(如@agent-worker/plugin-contract)。 建议迁入时改名@agent-worker/rpa-core(一次 commit 完成 rename,包内代码不用动)。 - 处理 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 条)
bun test包内纯逻辑测试全绿;npm run rpa-cli的等价物在 Bun 下跑通 5 个代表能力;- 能力注册数对得上(包内 719 个);
check:deps通过(没人在搬家过程中偷偷加回 Electron);- 真实操作一遍:弹一次人机对话框、高分屏上拖一次窗口、调一次 AI——验证宿主桥三条路径通了;
- 契约对齐有书面结论:capability-gateway(能力执行进网关)、workflow-engine(状态模型)、computer-control(driver 抽象)三份对照清单各评审通过;
- 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 侧,按平台写驱动)
- 先对齐对面的
computer-control契约:对面已声明"跨平台观察、定位、动作抽象"的契约(还是空壳)。 写 MacDriver / LinuxDriver 之前,先让五域 driver 接口与这份契约对表,避免两边各长各的。 - 写 MacDriver / LinuxDriver(接口现成,按五个域补实现):
- Linux:鼠标键盘用 xdotool(X11);Wayland 支持受限,是三端里最难的坑;界面元素识别走 AT-SPI;
- Mac:鼠标键盘用 cliclick 或 CGEvent;窗口操作走 AppleScript;界面元素走 AX 辅助功能 API。
- 先评估 macOS 权限问题:Mac 上 RPA 软件必须引导用户开"辅助功能/屏幕录制"授权(系统 TCC 机制), 这是 Mac 端最大的部署摩擦,做之前先摸清。
- Office 替代方案:Excel/Word 的 COM 自动化只有 Windows 有。Mac 可走 AppleScript + Office, Linux 可走 LibreOffice;或者第一版直接标注"仅 Windows"。
- 浏览器路径:外部浏览器启动路径现在写死了 Windows 的(
C:\Program Files\...),要补 Mac/Linux 的路径表。 - 剪贴板等小件:PowerShell 换成
pbpaste/pbcopy(Mac)、xclip(Linux)。 - CI 三个平台各跑一遍;产品界面按能力标注的平台支持情况置灰不支持的项。
一条原则
平台标记必须统一,这是硬约束(三端优先 win):
- 平台归属只有一处权威数据:包内注册分组表
PLATFORM_GROUPS(33 个能力组 × 平台数组)。 - 运行时的
meta.platforms和构建期的 catalogplatformTag都从这张表自动派生,任何代码不得自行声明第二份平台数据。 - 数据里今天只有
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 步) |