46 KiB
46 KiB
Agent-Employee RPA 迁入指南 V2(基于双侧真实源码核查)
文档性质:对
docs/rpa-core-migration-guide.md(V1)的全面修订版。 核查基线:2026-11-06,双侧真实工作区源码(非快照 ZIP、非审查报告转述)—— RPA 侧D:/code/PRA-only-demo(main,工作区干净)、宿主侧D:/code/Agent-Employee。 与 V1 的逐条差异及审查报告修正记录见docs/rpa-core-migration-guide-v2-diff.md。 状态标记约定:已实现(代码在库)/ 部分实现 / 仅契约(有类型无实现)/ 设计中 / 未实现 / 待确认(不允许猜测)。
0. V2 核心结论(先读这个)
- 宿主底座已大变,V1 的"空壳契约"叙事大部分失效。 V1 说对面 7 个契约包每个只有 1-9 个声明文件、windows-runner 是 0 源文件空壳。实测(2026-11-06):7 个包中 5 个已有实质实现(workflow-engine 25 文件、capability-gateway 321 行、browser-plugin 已接 Playwright、windows-plugin 新增原生观察适配器、runtime-governance 有 readiness 投影),windows-runner 有真实 C# 原生实现(.NET 10 + FlaUI UIA3,observe-only)。仍无实现的只剩两处:computer-control 的 Runner、windows-plugin 的 WindowsRunner.click/type。 → 迁入的本质从 V1 的"拿实现去填契约"变为**"接底座 + 给已有实现让路"**:不重复造 workflow 状态机、不重复造 Playwright 浏览器、不重复造 UIA 观察。
- RPA 侧接入前 P0 整改已于 2026-11-06 完成(迁移阶段 1 收口):节点尝试级 AbortController(超时即真中止底层操作)、取消映射 cancelled 不走 error route、重试改
idempotent元数据门控、图校验器执行前拒非法流程图、createEngine(options)注入参数(driver/hostBridge/subflowSource/registry)、视觉能力 5 处动态import("electron")清零改走 HostBridge.screen 注入、check-deps 覆盖动态 import、catalog 脏值修复、rpa-cli 显式注册重写。★ 标记明细见 §2/§7/§8。接入前本仓库代码活已全部完成(2026-11-06):①NodeState 补waiting_user/unknown两态 +toStepStatus全量映射表(与对面 StepStatus 8 态同构,含契约测试);②A++ 事件负载字段定稿——node.finished增checkpointId/resumable/idempotencyKey(幂等键=runId:nodeId 跨重入稳定,非幂等能力不作为续跑锚点),契约测试覆盖。附带:补 sm-crypto 类型声明(typecheck 归零)。对接面工作全部在对面仓库:rpa-adapter、subtree 迁包、垂直切片;本方仅待对面答复 Q1/Q2 与 rpa.browser 备案。PowerShell 编码差异验证留待阶段 2 迁包后(bun 本机冒烟已于 2026-11-06 完成:bun 1.4.4,engine 37/37 全绿,exceljs/pdf 行为无差异;对面锁 1.4.3 为 patch 级差异)。 - 迁入位置与名称维持 V1 结论:
code/backend/packages/rpa-core→@agent-worker/rpa-core,backend workspace(bun@1.4.3,workspaces 含packages/*)放进去即生效,backend 全家统一@agent-worker/*前缀、workspace:*源码消费。 - 两条硬边界不变且加严(用户红线):
- 所有带副作用的能力必须经 capability-gateway(授权→租约→幂等→执行→审计),不得绕行;
- rpa-core 不得依赖 Electron 主进程(当前仍有 5 处动态 import,是接入阻塞项)。
- 6 项 ADR 全部拍板(2026-11-06),仅剩 2 个小问题(Q1/Q2)需对面口头确认,详见 §10。已定基调:
- R3 桌面执行:C# 路线——五域执行逻辑移植进 windows-runner 原生进程,PowerShell 通道仅限本 demo。
- R6 部署拓扑:按能力域拆分——纯 Node 域进 backend plugin-worker,桌面/视觉/弹窗域装用户电脑 Electron 宿主,同一包按分组加载。
- R1 能力清单:全局一份,权限隔离全交对面网关按租户管。
- R4 浏览器:按场景分工——RPA 场景用咱们 CDP 接管(复用登录态/真实页面),对面 Playwright 留给 AI 智能体;白名单与证据共用对面一套。
- R5 消费方式:源码 git subtree 并入对面仓库统一编译,Bun 锁 1.4.3。
- R2 集成形态(含 A++ 补记):方案 A——整个 RPA 流程注册为
rpa.flow.execute单能力,事件流旁路+人审升级两补丁;事件流再升级为检查点协议(崩溃后带 resumeToken 断点续跑),权威账本始终单 step。两侧改动清单见 §7-A5。
1. 核查方法与证据基线
- 双侧源码逐文件核查(两个独立探查通道 + 关键点人工复核),关键结论均带
文件:行号证据。 - 实测过的事实:
import("electron")逃过 check-deps 正则(构造用例 0 匹配);catalog.json platformTag 分布(null=326 / win32=687 / 数字 1=3);capabilityCount()=719;对面 capability-gateway 租约 TTL=60s、幂等表上限 4096。 - 未验证(不写"通过"):Windows 实机 E2E、Bun 环境 test、对面真实链路联调。
- 审查报告(
docs/RPA-Review-Full.md)与真实源码不一致处,以源码为准并记录修正理由(见 diff 文档第 2 节)。
2. RPA 侧现状事实清单(2026-11-06 实测;★=阶段 1 已于当日修复)
| # | 事项 | 状态 | 证据 |
|---|---|---|---|
| 1 | Driver 惰性 getter + 非 win32 抛 platform_unsupported |
已实现 | engine.ts;error-codes.ts:43;engine-driver.test.ts |
| 2 | Driver 可注入 | ★已实现 | createEngine({driver}) + engine.setDriver();desktop/common-final/system-extended/window-extended 的模块级捕获改惰性 getDriver() |
| 3 | Registry 全局 Map、last-wins、runtime 读全局 getHandler | 属实(ADR-R1 短期形态固化;新增 engine.execute 语义真实入口) |
registry.ts;engine.ts execute() |
| 4 | PLATFORM_GROUPS 单一源(34 域全 win32)+ buildDomainPlatformMap 真实实现 + 守卫测试 | 已实现 | register-all.ts;platform-groups.test.ts |
| 5 | withTimeout 监听 signal 但无 AbortController——超时不中止底层 | ★已修复 | 尝试级 AbortController 汇聚 run 取消+节点超时,handler 收到的 ctx.signal 即尝试信号 |
| 6 | NodeState 类型含 cancelled,但 executeNode catch 把取消标成 failed | ★已修复 | 取消映射 cancelled(不适用 skipOnError、不进异常分支);runtime.cancel.test.ts |
| 7 | 重试上限 100、黑名单式 isRetryable | ★已门控 | CapabilityMeta.idempotent===false 时无视 retryCount |
| 8 | Graph Validator | ★已实现 | engine/graph-validator.ts(重复ID/悬空边/自环/环/孤儿/不可达),runFlow 前置校验 |
| 9 | 动态 import("electron") 5 处(vision.ts×3、cv-vision.ts×2) |
★已修复 | HostBridge.screen 服务注入(requireScreenService),Core 恢复零 Electron |
| 10 | check-deps.mjs 对 import("electron") 零匹配(盲区实测) |
★已修复 | 新增动态 import()/require() 扫描;合成用例命中=1,真实源码 0 违规 |
| 11 | 包依赖缺 3 项:@napi-rs/canvas、pdfjs-dist、@cantoo/pdf-lib | ★已修复 | rpa-core/package.json dependencies 补齐 |
| 12 | main/exports 直指 src 源码、private | 属实(决策项,与对面源码消费一致) | rpa-core/package.json |
| 13 | rpa-cli 副作用全量 import + 全局 getHandler | ★已重写 | 显式按域注册(5 域)+ engine.execute |
| 14 | CDP transport 单命令无超时/无 AbortSignal/pending 仅断连清理 | 属实(未修,A7 迁移前修) | transport.ts:96-118 |
| 15 | 两段式元素定位(当前页优先,失败才跟前台) | 已实现 | session.ts |
| 16 | locate() 不支持 xpath / Shadow DOM(与 withElement() 不一致) | 属实(未修,A7 迁移前修) | session.ts |
| 17 | HostBridge/SubflowSource 模块级单例 | 属实(ADR-R1 范畴;screen 服务已并入 HostBridge) | host-bridge.ts |
| 18 | AI ChatCompletionOptions 无 signal 参数 | 属实(未修,P2) | ai-service.ts |
| 19 | 桌面拾取无 AbortSignal(热键+轮询+deadline 自有机制) | 属实(未修,P1) | desktop-pick.ts |
| 20 | catalog platformTag:win32=687 / null=326 / 数字 1=3(脏值未清洗) | ✅ 已清洗(2026-11-06) | build-catalog.mjs 增白名单归一化(非 win32/darwin/linux 字符串一律重派生),3 条脏值重派生为 win32,全字段 diff 仅 3 条变化 |
| 21 | catalog overrides(fields/removeFields/addFields) | 已实现(+782 个 options 收割修复重生成回归) | catalog-overrides.mjs |
| 22 | 能力 719 个 / 目录组件 1016(vendor 997 + native 16 + trigger 3)/ fields 4299 / 34 域 | 实测 | platform-groups.test.ts;catalog.json counts |
| 23 | 平台守卫测试 5 文件 + driver/platform.ts 唯一入口 | 已实现 | capabilities/*.test.ts;driver/platform.ts |
| 24 | Driver 五域方法均无 AbortSignal 参数 | 属实(未修;运行时取消已能中止监听 signal 的能力内部操作) | driver/types.ts |
3. 宿主侧(Agent-Employee)现状事实清单
| 契约包/服务 | V1 描述 | 2026-11-06 实测 | 状态 |
|---|---|---|---|
| workflow-engine | 9 个声明文件,空壳 | 25 文件完整实现:WorkflowEngine 接口(create/start/beginStep/executeStep(runner)/completeStep/pause/resume/cancel/requestApproval/decideApproval)、状态机迁移表、Memory+PostgreSQL 双存储、recovery、REST API、worker(并发上限/取消/排空) | 已实现 |
| capability-gateway | 空壳契约 | 321 行完整实现:authorize(ref, subjectId, policy) → CapabilityLease(TTL 60s)、execute(lease, runner)、幂等键预占/结算(上限 4096)、高影响审批精确 actionId 放行、结果 leaseId/actionId 回显校验 |
已实现 |
| browser-plugin | 纯契约 | 已接 playwright-core ^1.64.1:PlaywrightBrowserRunner 358 行(navigate/click/type/snapshot),域名白名单三重复检(导航前/落点后/动作前),证据 SHA-256 落盘;定位仅 css/aria/text(无 xpath) | 已实现 |
| windows-plugin | 纯契约 | 契约 + 新增 native-observer.ts(292 行受信宿主适配器):spawn C# 观察进程、证据 realpath/SHA-256/PNG 魔数校验;WindowsRunner{click;type;readText;snapshot} 接口仍无实现;manifest rpa.windows:type=highImpact,全部 idempotencyRequired |
部分实现 |
| computer-control | 纯契约 | 未变:纯类型 + 3 纯函数(selectPreferredTarget 降级链、assertComputerActionAllowed、assertComputerResultEvidence);5 种 target kind、6 种 action、CoordinateSpace(DPI/缩放契约已就绪) | 仅契约 |
| runtime-governance | 空壳 | readiness 投影实现(readiness.ts 117 行),无插件生命周期契约 | 部分实现 |
| plugin-contract | 纯类型 | 类型底座 + assertPluginManifest 校验实现;PermissionScope 13 项(browser.domain/storage、desktop.window/input/process、filesystem.workspace/download、network.http、office.document、messaging.send/read、media.generate、monitoring.capture);CapabilityLease/ActionResult/CapabilityRef(pluginId:capabilityId) |
部分实现 |
| services/windows-runner | 0 源文件空壳 | 17 文件真实 C# 实现(.NET 10 + FlaUI UIA3 + PrintWindow,stdin/stdout JSON 协议,只认 observe,click/type 未实现);TS 宿主适配器校验证据 | 部分实现(观察半边) |
| plugin-registry / plugin-worker | (V1 未提) | registry=清单登记+版本链校验(无动态 loader);plugin-worker=常驻执行进程,PG LISTEN/NOTIFY 认领 workflow/session 动作、租约续期、跨进程取消传播、崩溃接管→unknown。这就是对面当前的插件宿主 | 已实现 |
| model-gateway | (V1 未提) | 21 文件实现包:ModelGateway.stream 流式调用 + ModelControlPlane(每次物理调用向 Java 控制面重新授权,短授权 60s) | 已实现 |
| Java 控制面 | (V1 未提) | code/backend/control-plane/:Spring Boot 4.1.1 / Java 21 / 454 个 Java 文件 / 9 Maven 模块;与 TS 面经 OpenAPI + Outbox + 短授权 grant 通信;端口 8887(Java)/8881(Admin)/8880(TS 执行面) |
已实现 |
| frontend/apps/desktop | Electron+SolidJS | 确认。无 RPA 宿主桥,但有等价物:identity-login-window(弹窗)、execution-context.ts(grant 桥)、zoom.ts(缩放);DPI/坐标契约在 computer-control CoordinateSpace 与 C# Protocol.cs | 部分实现 |
对面安全模型要点(直接影响 RPA 桌面路线):windows-plugin 策略校验只允许 *.exe 进程名、不允许路径;native-observer.ts 设计约束明言"不执行任意 PowerShell";桌面交互 Runner 留宿主、不进 Linux 容器。
4. 原指南(V1)内容分类
| V1 内容 | 分类 | 处理 |
|---|---|---|
| 包现状描述(719 能力、34 域、宿主桥 4 方法、Driver 五域) | 保留(微调) | 仍准确;宿主桥维持 4 方法不变 |
| "完全不依赖 Electron、check:deps 天天检查" | 过时/不实 | 5 处动态 import 逃过护栏;改为"静态依赖已清、动态残留待清",护栏必须升级 |
| 第 -1 步对面契约包全部空壳的叙事 | 过时 | 按 §3 改写:5/7 已实现,"填契约"变"接底座" |
| 第 0 步三件作业(bun 冒烟 / catalog 重生成 / 注册方式决策) | ✅ 全部完成 | catalog 重生成完成且脏值已清洗(platformTag win32=690 / null=326,数字脏值归零);bun 1.4.4 本机冒烟 37/37;注册方式决策并入 ADR-R1 |
| 第 1 步搬包(git subtree → code/backend/packages/rpa-core、改名 @agent-worker/rpa-core、demo 侧不双活) | 保留 | 双侧命名与 workspace 布局核实无误 |
| 第 2 步 A 类契约对齐表 | 需要修改 | capability-gateway/workflow-engine 从"对照后改对面"变"按已实现接口写 adapter";新增 plugin-contract/registry/worker 三层对接 |
| 第 2 步 B 类宿主注入表(浏览器=最大变数) | 需要修改 | 浏览器变数已收敛:对面有 Playwright 实现;变数改为"双路径取舍"(ADR-R4) |
| 第 3 步 7 条验收 | 需要修改 | 扩充为 §9 验收标准(加 gateway 零调用、取消传播、双 Engine 隔离等) |
| 三端计划(PLATFORM_GROUPS 单一源、驱动自动选、分组核查、测试守卫、平台判断收拢) | 已完成,从"待办"改"现状" | 五件小事全部落地;平台硬约束一节保留为长期规范 |
| 附:10 个关键决策 | 大部分保留 | 决策 2"保留全局注册表"与决策 9"双入口"需按 ADR-R1 重新确认;其余不变 |
5. 接入目标架构
┌─ Agent-Employee(宿主:权威状态与治理的唯一来源)──────────────────────┐
│ │
│ Java 控制面 control-plane(:8887) ──OpenAPI/Outbox/短授权 grant──┐ │
│ │ │
│ TS 执行面 apps/api(:8880, Bun) │ │
│ ├─ workflow-engine ← Run/Step 权威状态机(PG 存储+recovery) │ │
│ ├─ capability-gateway← 授权→租约(60s)→幂等→执行→审计【唯一入口】│ │
│ ├─ plugin-registry ← 清单登记 + 版本链校验(无动态 loader) │ │
│ ├─ model-gateway ← AI 流式调用 + 每次调用控制面授权 │ │
│ └─ services/plugin-worker ← 常驻执行进程(LISTEN/NOTIFY 认领) │ │
│ ├─ browser-plugin → PlaywrightBrowserRunner(已实现) │ │
│ └─ windows-plugin → windows-runner(C# FlaUI, observe-only)│ │
│ │
│ frontend/apps/desktop(Electron+SolidJS,用户桌面宿主) │ │
│ └─ RPA 宿主桥实现落点(弹窗/DPI/AI 配置/子流程仓库) │ │
└────────────────────────────────────────────────────────────────┘
▲
│ CapabilityRunner(gateway 包皮,唯一执行通道)
│ Run/Step 事件回传(RPA 不建第二套状态)
┌─ RPA 迁入物(执行器与能力供给方)──────────────────────────────────────┐
│ @agent-worker/rpa-core(packages/rpa-core 迁入,Bun 源码消费) │
│ ├─ Flow Runtime(作为 workflow-engine 的执行引擎候选 / 步骤级 runner)│
│ ├─ 719 能力 handler(纯 Node 部分可在 plugin-worker 服务器侧跑; │
│ │ 桌面/视觉部分只能跑在用户桌面宿主进程——见 ADR-R6) │
│ ├─ WindowsDriver(补齐对面 WindowsRunner.click/type 执行缺口,ADR-R3)│
│ └─ CDP 外部浏览器会话(与 PlaywrightBrowserRunner 的取舍,ADR-R4) │
│ @agent-worker/rpa-adapter(新增薄适配层) │
│ ├─ CapabilityRunner:authorize/execute 包裹 → ref↔componentId 映射 │
│ ├─ RunResult/NodeState ↔ WorkflowStatus/StepStatus 映射表 │
│ └─ 宿主注入装配:HostBridge(4) + SubflowSource(2) + ScreenCaptureHost│
└────────────────────────────────────────────────────────────────────────┘
权责原则(沿审查报告,逐条可执行):
- workflow-engine 是 Run/Step 状态唯一权威;RPA Runtime 只回传事件,不落第二份终态。
- capability-gateway 是唯一授权入口;RPA 侧
getHandler()不对 adapter 之外暴露(rpa-cli 顺手重写以作表率)。 - computer-control 是桌面契约对齐对象;RPA 不新造并行的桌面抽象。
- 宿主服务一律注入,禁用模块级 setter 承载多会话状态(现状 HostBridge 单例是过渡,见 ADR-R1)。
6. 模块对应关系表
| RPA 侧(packages/rpa-core) | Agent-Employee 侧 | 关系 | 现状 |
|---|---|---|---|
engine/runtime.ts 流程执行 |
workflow-engine WorkflowEngine/StepRun |
RPA=执行算法候选,AE=权威状态 | 已拍板方案 A(ADR-R2) |
engine/registry.ts 全局注册表 |
plugin-registry + capability-gateway CapabilityRef |
ref↔componentId 映射层(rpa-adapter) | 映射待建 |
| 719 能力 handler | plugin-contract CapabilityDefinition + PermissionScope 13 项 |
能力清单生成 + 权限映射 | 待建(脚本生成) |
RunContext.signal |
CapabilityExecutionContext.signal |
均 AbortSignal,直通 | 兼容 |
NodeState(idle/running/succeeded/failed/skipped/cancelled) |
StepStatus(+waiting_user/unknown/pending) |
映射表;RPA 缺 waiting_user/unknown | 需补 |
human-dialog 审批弹窗 |
WorkflowApprovalRequest/decideApproval |
人审节点挂宿主 approval 流 | 需 adapter |
driver/windows/*(PowerShell 五域) |
windows-runner C#(observe-only)+ WindowsRunner{click,type} 契约 |
RPA 补执行半边;安全模型冲突 | ADR-R3 |
browser/* CDP 会话(BrowserLike) |
browser-plugin PlaywrightBrowserRunner |
双路径取舍 | ADR-R4 |
ai-service.ts loadAiConfig |
model-gateway(ModelGateway.stream + ModelControlPlane) |
RPA AI 能力改走宿主网关 | 需改造 |
host-bridge.ts 4 方法 |
frontend desktop main 进程(弹窗/坐标/AI 配置等价物已有) | 参考实现照抄本仓库 src/main/index.ts | 落点明确 |
SubflowSource 2 方法 |
对面流程存储 | 包一层 | 小 |
| vision/cv-vision 截图+DPI | computer-control CoordinateSpace + C# PrintWindow |
宿主注入 ScreenCaptureHost | 待建 |
| 运行证据/截图 | evidence-store(S3) + monitoring.capture 权限 |
证据统一落对面 | 待接 |
check-deps.mjs 依赖护栏 |
backend 包边界 | 保留并升级(动态 import) | 需增强 |
7. 逐接入点详单
每项按固定七要素:RPA 位置 / AE 位置 / 兼容性 / 问题 / 改哪侧 / 方案 / 验收。
A1 Engine 与 Driver 注入
- RPA 位置:
packages/rpa-core/src/engine/engine.ts:47-66(惰性 getter +createEngine()无参);capabilities/desktop.ts:9、common-final.ts:11、system-extended.ts、window-extended.ts、office.ts:15、ftp.ts、ocr-caps.ts:11捕获defaultEngine.*(其中 desktop.ts:9 在模块加载时取.driver,非 win32 下 import 即抛错)。 - AE 位置:对面不关心 driver 细节;对齐契约是
computer-control的ComputerRunner{observe;execute}(computer-control/src/index.ts:99-102)与windows-plugin的WindowsRunner。 - 兼容性:部分。平台错误语义(platform_unsupported)已就绪;注入面缺失。
- 问题:宿主无法注入测试替身或 computer-control 适配器;能力文件模块级捕获引擎状态(excelHandles/ftpClient/ocrInstance/driver),多会话共享。
- 改哪侧:RPA。
- 方案(★ 已实现,2026-11-06 阶段 1-A1):
createEngine(options?: { driver?, hostBridge?, subflowSource?, registry? }),全部可选、缺省保持现行为;能力文件改为经 RunContext/engine 参数取 driver 与资源表(模块级捕获改为首用时向 engine 取);幂等句柄表(excelHandles/ftpClient/ocrInstance)迁入 engine 实例字段(部分已是)。 - 验收:FakeDriver 注入测试覆盖五域;两个 Engine 各注入不同 FakeDriver 并行执行互不串用;非 win32 上 import 全部 34 域不抛错、调用桌面能力时才抛 platform_unsupported。
A2 Registry 注册机制与实例隔离
- RPA 位置:
engine/registry.ts:36-45(模块级 Map、last-wins、meta 可残留旧值);runtime.ts:260(全局 getHandler);register-all.ts(34 域 DOMAINS + PLATFORM_GROUPS + buildDomainPlatformMap)。 - AE 位置:
plugin-registry(清单登记+版本链,无动态 loader)、capability-gatewayCapabilityRef(pluginId:capabilityId+ version)。 - 兼容性:结构性错位。对面一切能力调用都带 CapabilityRef 与版本;RPA 是字符串 id 全局表。
- 问题:进程级注册在对面"多租户 + plugin-worker 常驻进程"模型下无法按租户隔离;componentId 与 CapabilityRef 无映射;同 id 覆盖无审计。
- 改哪侧:短期 RPA 侧固化 ADR + 新建 adapter 映射;长期 RPA 侧 engine-scoped registry。
- 方案:①ADR-R1 先定部署模型(单后端单能力集 → 全局表合法,把
registerAll文档语义改为"加载到进程注册表",不假装实例隔离);②rpa-adapter 维护componentId ↔ (pluginId="rpa", capabilityId=componentId, version=catalog 版本)映射,由 catalog.json 生成并做完整性测试;③重复注册策略定为"显式覆盖 + 输出 warn 审计行"。 - 验收:映射表覆盖 719 能力(或明确排除清单);gateway 侧按 ref 解析到正确 handler;重复注册产生可审计日志。
A3 Runtime 执行、超时、取消、重试
- RPA 位置:
runtime.ts:33-56(withTimeout 只 reject 外层)、runtime.ts:334-339(取消标 failed)、runtime.ts:58-60,276(isRetryable 黑名单、retryCount≤100)、driver/types.ts:87-119(五域方法无 signal)。 - AE 位置:
workflow-engineStepRun.attempt/leaseEpoch/idempotencyKey、workflow-worker跨进程取消传播与崩溃接管→unknown、capability-gatewayexecute 的ctx.signal?。 - 兼容性:不兼容。对面以幂等键 + 租约纪元管理副作用安全;RPA 超时/取消/重试语义与它冲突。
- 问题:超时后底层 PowerShell/HTTP/CDP 仍执行(重复副作用);取消状态不一致;非幂等能力可被重试 100 次。这是接入的第一阻塞项。
- 改哪侧:RPA。
- 方案(★ 已实现,2026-11-06 阶段 1-A3):①节点尝试创建独立 AbortController,合并 Run 级 signal 与节点 timeout,贯通 handler→driver→PowerShell 子进程/HTTP/CDP(driver 五域方法加可选
signal参数);②executeNode catch 优先映射 cancelled →state.status="cancelled",不走 skipOnError/error route/retry;③重试改元数据驱动:CapabilityMeta 增idempotent/sideEffect/retryPolicy,非幂等默认 0 次重试;④新增validateFlowGraph(ID 唯一、边合法、入口/出口基数、环、悬空边)。 - 验收:构造 5 秒 Fake Handler + 100ms 超时,断言 handler 收到 abort 并停止、无并发重入;执行中取消后 Run 与 NodeState 均为 cancelled;对 File 写入/点击类能力验证"超时不自动重试";非法图执行前得到稳定错误码。
A4 Capability Gateway(能力注册与权限治理)
- RPA 位置:
registry.ts(handler + meta 无权限字段);resources/catalog.json(仅risk: low|high)。 - AE 位置:
capability-gateway/src/index.ts:75-252(已实现 authorize/execute/租约 60s/幂等/高影响审批);plugin-contractPermissionScope 13 项。 - 兼容性:接口契合度高——
CapabilityRunner = (input, ctx{lease,capability,signal?}) => Promise<ActionResult>,RPA handler(ctx, node, args, component)包一层即可;ActionResult 需回显 leaseId/actionId(adapter 统一填)。 - 问题:①719 能力 ↔ 13 项 PermissionScope 无映射;②CapabilityMeta 无 sideEffect/idempotent/permission/approvalRequired 字段;③存在绕行面(rpa-cli、子流程直接 getHandler)。
- 改哪侧:新建 adapter(AE 仓库内包)+ RPA 补元数据。
- 方案:①rpa-adapter 实现 CapabilityRunner:gateway.execute(lease, runner) → ref→componentId → 构造 RunContext(signal 直通)→ handler → 结果包装 ActionResult;②权限映射表按 34 域 × PermissionScope 初稿生成(files→filesystem.workspace、http→network.http、desktop/windowExtended→desktop.input/window、utilityExtended→独立高影响 scope【待确认:现表无 process 执行域对应,需对面确认】、message→messaging.send);③高风险域标 highImpact 走审批(System_ExecuteCommand、键鼠、文件删除/覆盖、发消息);④meta 增治理字段(与对面 CapabilityDefinition 字段对齐)。
- 验收:审批拒绝/租约过期/权限不在白名单时 handler 零调用(gateway 已有测试语义,adapter 层加 719 全量冒烟:未经 authorize 不得触达 handler);审计可关联 Agent/Run/Capability/审批结果。
A5 Workflow Engine 执行契约
- RPA 位置:
engine/runtime.ts(RunResult/NodeState)、engine/types.ts:142、human-dialog 审批弹窗、SubflowSource。 - AE 位置:
workflow-engine/src/index.ts:278-311(WorkflowEngine 接口)、workflow-runtime.ts、workflow-worker.ts、approval-policy.ts;executeStep(..., runner)的 runner 类型即Parameters<CapabilityGateway["execute"]>[1]。 - 兼容性:状态映射大体可行;RPA 缺
waiting_user/unknown两态;对面 StepStatus 无 RPA 的idle。 - 问题:两套状态权威冲突风险;集成形态二选一未定(整体作为一个 capability vs 节点级映射为 step)。
- 改哪侧:adapter + 双侧小改。
- 方案:已拍板(ADR-R2)方案 A + 两补丁——整个 RPA 流程注册为一个 capability(
rpa.flow.execute),workflow-engine 的一个 step 调它,RunResult→ActionResult、节点级事件→event-bus 事件流(旁路,不进权威账本)、human-dialog→requestApproval 挂对面 approval 流、取消→signal 直通。补丁 1:节点事件流保透明;补丁 2:人审/高危节点照常升级对面审批。方案 B(节点=step 1:1)的触发条件留档:仅当对面产品确认需要"逐步控制 RPA"(单步执行/任意步回退)时局部启用,届时事件流已备好数据不返工。NodeState 增waiting_user/unknown两态(unknown 用于崩溃恢复对齐)。 - A++ 检查点补记(2026-11-06,本方负责人确认):在方案 A 骨架内将节点事件流升级为检查点协议(决策全文见 §10-R2)。
- RPA 侧改动:①事件负载增
nodeId/status/checkpointId/idempotencyKey/resumable字段;②rpa.flow.execute接受可选resumeToken,重入时从最近检查点续跑(幂等句柄表已迁 engine 实例字段,地基现成);③幂等键生成与传递贯通(复用 A3 的idempotent门控,仅补 key 生成与透传)。 - 对面侧改动:①workflow-engine 对
rpa.flow.execute所在 step 的重试/恢复策略允许带 resumeToken 重入(不新建 step、不改租约语义);②event-bus 消费端识别检查点事件并入审计链;③崩溃恢复时把 resumeToken 经 adapter 回传(复用 workflow-recovery 的 unknown→恢复路径)。 - 落地节奏:阶段 2 只做事件负载字段设计定稿(payload 预留,近零成本);阶段 3 垂直切片做最小验证(崩溃→重入续跑);阶段 4/5 规模化时强制执行。
- RPA 侧改动:①事件负载增
- 验收:状态映射契约测试(含 waiting_user/unknown/cancelled 全分支);一次含审批节点、一次执行中取消、一次进程崩溃恢复的端到端演练;对面 Run 状态终态与 RPA RunResult 永远一致;崩溃重入演练——杀掉执行进程后带 resumeToken 续跑,已完成节点不重复执行、幂等键防重复副作用。
A6 Computer Control 与 Windows 桌面执行
- RPA 位置:
driver/windows/*(PowerShell 封装五域)、capabilities/desktop-uia.ts、element.ts。 - AE 位置:
computer-control(仅契约+3 纯函数)、windows-plugin(WindowsRunner{click;type;readText;snapshot} 无实现、native-observer.ts observe-only)、services/windows-runner/native/*.cs(FlaUI UIA3 observe-only)。 - 兼容性:安全模型冲突——RPA 驱动 spawn 任意 PowerShell;对面白名单只许
*.exe、明文"不执行任意 PowerShell"、证据要求 SHA-256。 - 问题:RPA 的执行半边(click/type)正是对面缺口,但实现方式过不了对面安全门。
- 改哪侧:双侧(ADR-R3 已拍板:C# 扩展 actuate,见 §10)。
- 方案:推荐——把 RPA WindowsDriver 的五域执行逻辑移植进 windows-runner 的 C# 原生进程( FlaUI/CGEvent 等价实现 + 现成协议加 actuate 操作),RPA 侧 driver 抽象保留、Windows 实现改为可指向"原生进程通道"或"本地 PowerShell 通道"(后者仅 demo 使用,明确标注不走宿主治理);策略校验/证据断言复用对面
assertComputerActionAllowed/assertComputerResultEvidence。 - 验收:click/type 经策略校验(白名单进程/窗口、allowInput)+ 证据落盘;宿主拒绝时零副作用;同目标 observe→actuate→observe 闭环一致。
A7 浏览器(Browser Plugin vs RPA CDP 会话)
- RPA 位置:
packages/rpa-core/src/browser/*(transport/external,进包部分)+src/main/browser/session.ts(接管/拾取,留守部分);已知缺陷:transport 单命令无超时(:96-118)、locate 不支持 xpath/Shadow DOM、evaluate 默认 follow=true。 - AE 位置:
browser-plugin(PlaywrightBrowserRunner 已实现:白名单三重检、AbortSignal 透传、证据 SHA-256;定位 css/aria/text,无 xpath)。 - 兼容性:双实现并行,语义不同(Playwright 自管浏览器 vs RPA 接管用户已开浏览器/复用登录态)。
- 问题:重复投资;RPA CDP 链路自身有 P1 缺陷;对面定位器无 xpath(RPA 拾取器产出 xpath/css/aria/text 混合 selector)。
- 改哪侧:ADR-R4 已拍板(按场景分工):RPA 场景走咱们 CDP 接管(主力),对面 Playwright 留给 AI 智能体场景。
- 方案:①RPA 浏览器能力迁前先修 transport 单命令超时 + 统一 resolveElement(一次修复覆盖 locate/click/type/getText);②CDP 接管路线接对面 BrowserContextPolicy 白名单与证据体系(不自建白名单);③与对面确认 rpa.browser 插件清单承载咱们的 runner;④PlaywrightBrowserRunner 保持现状服务 AI 智能体场景,双方不重复投资。
- 验收:同一定位用例集(css/aria/text/xpath)在咱们 CDP 路径全部通过;白名单拒绝 URL 时导航前即拦截(走对面策略对象);证据落 evidence-store。
A8 平台适配(Windows / Linux / macOS)
- RPA 位置:
register-all.tsPLATFORM_GROUPS(34 域全 win32)、driver/platform.ts、engine/engine.ts:47-61、5 个 skipIf 测试;catalog win32=690 / null=326,数字脏值已归零(2026-11-06 白名单归一化)。 - AE 位置:
plugin-contractPlatform 类型;windows-runner 明确"留在宿主、不进 Linux 容器"(README)。 - 兼容性:兼容(两边都是 win32-first 务实路线)。
- 问题:①
catalog 3 个已修复(2026-11-06):build-catalog.mjs 白名单归一化,上游 shizai 的数字 1 重派生为 win32(三条均为包内真实现,语义正确);②对面 CapabilityDefinition 未见 platform 字段(待确认:插件清单如何表达平台限制)。platformTag: 1脏值透传 - 改哪侧:RPA(清洗);对面(清单平台字段,待确认后)。
- 方案:build-catalog 归一化——源值不在
win32|darwin|linux|null白名单的一律重派生;三端扩展节奏沿用 V1 第三节(Linux xdotool/AT-SPI、Mac AX/CGEvent/TCC、Office 分端实现),驱动实现统一走 ADR-R3 的原生进程通道。 - 验收:catalog 全量过 schema 校验(1016/1016);非 win32 上 Core 可加载、桌面能力明确报 platform_unsupported;Mac/Linux CI 跑纯逻辑子集。
A9 Electron 依赖与 Core 独立性(含包闭包)
- RPA 位置:vision.ts:18,66,432、cv-vision.ts:51,213(动态
import("electron"));check-deps.mjs:20(正则盲区实测);rpa-core/package.json:17-32(缺 @napi-rs/canvas、pdfjs-dist、@cantoo/pdf-lib;main 直指 src、private)。 - AE 位置:backend 执行面是 Bun(无 Electron);Electron 只在 frontend/apps/desktop;截图/坐标对面等价物是 C# PrintWindow + CoordinateSpace 契约。
- 兼容性:不兼容。视觉能力在对面 backend 进程必然失败。
- 问题:Core 不是 Electron-free;护栏查不出动态 import;单包安装缺 3 个依赖。
- 改哪侧:RPA。
- 方案(★ 已实现,2026-11-06 阶段 1-A9):①抽
ScreenCaptureHost/DisplayCoordinateService接口并入 HostBridge 注入面(弹窗/DPI×2/AI 配置 4 方法 → 增至 6 方法,或独立 host services 包——实现期定,倾向并入 HostBridge 减少 API 面);vision/cv-vision 只依赖接口,宿主未注入时抛host_service_unavailable;②check-deps 升级为覆盖import()/require()/createRequire()(先补正则,中期 AST);③补齐 3 个依赖声明(pdf.js 与 canvas 为原生/大件,评估 optionalDependencies + 能力级降级);④消费方式锁定 Bun 源码消费(对面全家 workspace:* 源码依赖,与现状一致),锁 bun@1.4.3 做 CI 冒烟。 - 验收:无可解析 electron 的纯净 Node/Bun 环境 Core 全量 import 成功;视觉能力未注入 Host 时返回 host_service_unavailable、注入 Fake Host 后可测;隔离目录仅按包声明装依赖跑通 PDF/OCR 代表能力。
A10 插件生命周期、异常隔离与资源清理
- RPA 位置:无插件概念;资源清理散在能力内(PowerShell 子进程、ws、FTP/OCR 句柄);历史上有 catch{} 吞错模式(已部分修复)。
- AE 位置:
plugin-contractPluginManifest(apiVersion/minCoreVersion/entrypoint/rollbackVersion)+ assertPluginManifest;plugin-registry版本链校验;plugin-worker(崩溃接管→unknown、租约续期、跨进程取消)。 - 兼容性:RPA 需要一张插件"外壳"才能进对面宿主。
- 问题:719 能力不可能逐个成插件;RPA 无崩溃恢复语义(对面 unknown 态)。
- 改哪侧:adapter 为主。
- 方案:RPA 以单一插件接入(manifest id 建议
rpa.core,能力按域分批暴露为 CapabilityDefinition 清单,随 catalog 生成);异常隔离靠节点级 try/catch + AbortSignal(A3);资源清理建统一 finally 清单(子进程 kill、ws close、临时文件删除)并纳入取消路径;崩溃恢复复用对面 workflow-recovery(NodeState.unknown 对齐)。 - 验收:杀掉 plugin-worker 进程后 Run 转入 unknown 并可恢复;取消后无残留子进程/连接/临时文件;manifest 通过 assertPluginManifest 与 registry 版本链。
8. 分阶段实施计划
原则:先 RPA 侧收口(便宜、不依赖对面),再垂直切片,再规模化。不为了架构统一搞大重构;每阶段有硬验收门。
| 阶段 | 内容 | 前置 | 验收门 |
|---|---|---|---|
| 0 事实确认(双侧,1 次评审会) | 向对面同步 6 项已拍板结论(R1-R6)并预估 C# actuate 扩展量;确认 2 个小问题(Q1 platform 字段 / Q2 utilityExtended 权限归属);确认事件流接口与 rpa.browser 清单备案 | 无 | Q 有书面结论 |
| 1 RPA 侧收口(本仓库)✅ 已完成(2026-11-06,提交 9b76dc6/1da0082/1a20dd7/5e8fc96) | A3 四件(取消贯通/状态映射/重试元数据/Graph Validator)+ A1 注入参数 + A9(Electron 残留、check-deps 升级、依赖闭包)+ A2 的 ADR 固化 + catalog 脏值清洗 + rpa-cli 重写(显式注册、经 engine 取 handler) | 无 | 审查报告 §7 第一/二阶段清单全绿;纯 Node 环境 Core 全量加载 |
| 2 迁入与 adapter 骨架 | git subtree 迁包改名 @agent-worker/rpa-core;bun@1.4.3 test 冒烟(exceljs/pdf/PowerShell 编码);新建 @agent-worker/rpa-adapter(CapabilityRunner + ref 映射 + 状态映射表);A++ 事件负载字段设计定稿(nodeId/检查点/幂等键,见 §7-A5);demo 侧冻结 | 阶段 1 + ADR-R1/R2 | bun test 纯逻辑全绿;未经 gateway 不可达 handler;719 映射完整性测试 |
| 3 垂直切片 | 一个文件能力 + 一个 HTTP 能力走通:workflow-engine create/start → gateway authorize → adapter → rpa-core handler → 事件/证据回传 → cancel 中途取消;方案 A(rpa.flow.execute 整体注册)+ A++ 检查点续跑最小验证(崩溃→resumeToken 重入,见 §7-A5) | 阶段 2 | 取消/审批/审计全链有证据;对面 Run 终态与 RunResult 一致 |
| 4 浏览器与桌面双 ADR 落地 | ADR-R4(已拍板):RPA 浏览器能力修完 transport/resolver,接对面白名单与证据体系后作为 RPA 场景主力 runner;ADR-R3:windows-runner C# 扩展 actuate(RPA 五域逻辑移植) | 阶段 3 | §7-A6/A7 验收条目 |
| 5 能力规模化 | 34 域按风险分批:files/data/http/ftp → office/excel/word(COM 仅 win32)→ desktop/utility 高影响(末批+审批);CapabilityDefinition 与权限映射随批生成 | 阶段 4 | 每批过 gateway 全量冒烟 + 审批矩阵抽查 |
| 6 平台扩展 | V1 第三节三端计划原样生效(Linux/macOS 驱动按 ADR-R3 原生通道) | 阶段 5 | 三平台 CI 矩阵;产品按 platformTag 置灰 |
不搬的东西(维持 V1 清单):界面渲染层、悬浮框/取色器、本地视觉 onnxruntime、流程存储、内置浏览器编排——由宿主提供或对面重做;其中"本地视觉"明确不进 backend(原生依赖 + 桌面截图依赖),留在宿主桌面进程。
9. 风险清单与总验收标准
风险清单
| # | 风险 | 等级 | 缓解 |
|---|---|---|---|
| R1 | 中 | 阶段 0 与对面确认 actuate 扩展量;RPA 五域逻辑先行整理成移植清单 | |
| R2 | 中 | 阶段 2 按 PLATFORM_GROUPS 分组做宿主子集加载验证 | |
| R3 | Registry 全局单例在多租户 backend 的隔离缺陷 | 高 | 短期按 ADR-R1 限定部署模型;长期 engine-scoped registry 列入 backlog |
| R4 | 浏览器双路径重复投资 | 低(已缓解) | R4 已拍板按场景分工(RPA=CDP 接管,AI 智能体=Playwright),白名单与证据共用一套,无重复投资 |
| R5 | 719 能力的治理映射与元数据补齐工作量失控 | 中 | 脚本从 catalog 生成初稿 + 人工只审高风险域;分批(阶段 5) |
| R6 | Bun 与 Node 行为差异(exceljs/pdf-lib/PowerShell 编码) | 中(部分缓解) | exceljs/pdf 已于 2026-11-06 本机 bun 1.4.4 冒烟通过(37/37);PowerShell 编码差异留待阶段 2 迁包后清单化 |
| R7 | demo 侧与 backend 双活跃漂移 | 中 | git subtree + "迁移后 demo 冻结"纪律(V1 决策 3) |
| R8 | 两套状态机语义漂移(NodeState vs StepStatus) | 中 | 映射表 + 契约测试常驻 CI;A++ 检查点协议(ADR-R2 补记)统一崩溃恢复语义 |
| R9 | catalog 源数据(shizai)上游已删,重生成受阻 | 低 | 已从对面历史恢复至 temp/catalog-source;计划快照入库 |
| R10 | 对面底座继续快速演进,本文行号/接口过期 | 中 | 本文标注核查日期;联调前对关键接口做增量 diff |
总验收标准(迁移完成的定义)
- Bun@1.4.3 下包 typecheck/test 全绿(不以 Node 测试替代)。
- FakeDriver/Host 注入可用,双 Engine 隔离行为符合 ADR-R1。
- 全部已暴露能力经 capability-gateway:审批拒绝/租约过期/无权限时 handler 零调用,审计四元组(Agent/Run/Capability/审批)可追踪。
- 取消/超时/重试测试证明:超时即中止底层、取消不进 error route、非幂等零自动重试、无并发重入。
- Graph Validator 拒绝非法流程图于执行前。
- 纯 Node/Bun 环境(无 electron 可解析)Core 全量加载;视觉路径 Host Mock 可测。
- 隔离目录按包声明安装依赖,代表能力(文件/Excel/HTTP/PDF)可跑。
- 垂直切片端到端演练通过:含一次审批、一次中途取消、一次进程崩溃恢复(unknown→恢复)。
- Windows 10/11 实机回归:UIA/浏览器/Office/DPI/多屏/安装包资源 + 取消场景。
- catalog 1016 项全过平台 schema 校验;能力平台范围与真实实现一致。
10. 决策与待确认清单
已拍板(2026-11-06,本方负责人确认)
| ADR | 问题 | 决定 |
|---|---|---|
| R1 | Registry 作用域:backend 是否多租户并存 | 全局一份能力清单(菜单所有租户共用),权限隔离完全由 capability-gateway 按租户管;长期将清单挂到 engine 实例(已从对面源码确认 WorkflowIdentity 带 tenantId,但清单本身无需按租户复制) |
| R3 | 桌面执行安全模型:RPA PowerShell 驱动 vs 对面"受信 C# 原生进程"红线 | C# 扩展 actuate:把 RPA 五域执行逻辑移植进 windows-runner 原生进程;PowerShell 通道仅限本 demo,不进宿主 |
| R4 | 浏览器双路径 | 按场景分工:RPA 场景走咱们的 CDP 接管路线(复用用户登录态/真实页面——RPA 核心价值);对面 PlaywrightBrowserRunner 留给 AI 智能体场景(无头自管浏览器)。约束:①咱们 CDP 路线必须接对面 BrowserContextPolicy 白名单与证据体系,不自建;②迁移前修完 transport 超时与定位器不统一两缺陷;③需对面在插件清单给咱们的 runner 备案(rpa.browser) |
| R5 | 包消费方式 | 源码并入 + 锁版本:git subtree 进对面仓库统一编译,Bun 锁 1.4.3(与对面全家 workspace:* 源码消费现状一致) |
| R6 | 部署拓扑:rpa-core 各域跑在哪 | 按能力域拆分部署:纯 Node 域→backend plugin-worker;桌面/视觉/弹窗域→用户电脑 Electron 宿主;同一包按 PLATFORM_GROUPS 分组加载,不维护两份代码 |
| R2 | 集成形态:RPA 流程=单个 capability(方案 A)还是节点=step 映射(方案 B) | 方案 A + 两补丁:RPA 流程=rpa.flow.execute 单能力,对面一个 step 一次租约一次结算;节点级事件走 event-bus 旁路(保透明、不进权威账本);人审/高危节点照常升级对面审批。不用 B 的理由(记录在案):双账本一致性(崩溃窗口两边分歧、破坏对面 recovery 的单账本假设)、控制流节点无副作用无法映射 CapabilityRef、审批/重试粒度与业务语义错位。B 的触发条件:对面产品确认需要"逐步控制 RPA"(单步执行/任意步回退)时局部启用,事件流已备好数据不返工。A++ 补记(2026-11-06 二次拍板):方案 A 骨架不变,节点事件流从"透明度日志"升级为检查点协议(nodeId+状态+幂等键+可恢复标记),崩溃后 rpa.flow.execute 带 resumeToken 重入、从最近检查点续跑,权威账本仍为单 step、无双账本;B 的隐藏触发条件(长流程断点续跑,RPA 桌面场景高发)由此覆盖而无需节点=step。业界对照:UiPath Orchestrator=Job 黑盒+日志旁路(≈A);Camunda/Zeebe External Task 的"单引擎假设"不适用于双引擎集成;AWS Step Functions callback≈补丁 2。两侧改动清单与落地节奏见 §7-A5 |
待对面对确认(仅剩小问题,不猜测)
| Q# | 问题 | 评审要点 |
|---|---|---|
| Q1 | CapabilityDefinition 是否需要 platform 字段(对面清单未见) | 建议对面补字段或约定由 catalog platformTag 承载 |
| Q2 | utilityExtended(命令执行)对应哪个 PermissionScope | 13 项中 desktop.process 是候选,需对面确认语义(backend 无桌面,进程执行属哪域) |
已回答:Q3(human-dialog 弹窗落点)已由 R6 回答——用户电脑 Electron 宿主窗口;仅样式/交互细节与对面 UI 对齐。
11. 本指南边界
- 全部结论基于 2026-11-06 双侧工作区源码静态核查 + 少量脚本实测(正则盲区、catalog 统计、capabilityCount);未执行 Windows 实机 E2E 与对面联调,未运行的测试不写成通过。
- 行号会随代码演进过期,以函数/接口名为准。
- 本轮只改文档,不改业务源码(用户指令);阶段 1 起的代码改动另行排期。