Files
FlowPilot/docs/多Flow根治性统一重构方案.md
T
2026-05-21 07:21:34 +08:00

34 KiB

多Flow根治性统一重构方案

1. 背景

当前项目已经完成过多轮从单一 OpenAI 注册链路向多 flow 架构的重构,但现在的状态仍然属于“骨架已多 flow 化,核心 contract 仍保留 openai + kiro 双分支”。

这会带来三个持续性问题:

  • 每新增一个 flow,都需要继续修改 core 语义,而不是只新增 flow 自己的模块。
  • 文件命名、状态命名、配置命名仍带有明显历史负担,读代码和改代码都累。
  • 每次重构都只能修表层,无法保证第三个 flow 接入时不再次爆炸。

本方案的目标不是“再修一轮兼容”,而是一次性把多 flow 架构收口成稳定合同,后续新增 flow 时不再改 core 语义。

2. 总目标

本次重构完成后,项目必须达到以下目标:

  • 新增一个 flow 时,只新增该 flow 目录和注册项,不再修改 core 的配置合同、运行态合同和侧栏核心语义。
  • 所有 flow 都使用同一套配置结构、同一套运行态结构、同一套 source/driver 注册模型。
  • OpenAI 与 Kiro 的代码组织、文件命名、步骤命名、source 命名、driver 命名全部统一到同一规范。
  • 删除长期存在的历史别名和双轨字段,避免后续维护继续被旧命名拖住。
  • 旧配置不再作为运行时输入;旧数据只允许通过导入转换器映射到新 canonical 结构后进入系统。

3. 当前根问题

3.1 配置模型仍然是双轨

当前 settings-schema 只内建 flows.openaiflows.kiro 两套显式结构,同时继续派生:

  • openaiIntegrationTargetId
  • kiroTargetId
  • panelMode

这不是多 flow 通用合同,而是两个 flow 的并排硬编码。第三个 flow 接入时,只能继续增加第三套特判。

3.2 运行态模型是裂开的

当前运行态存在两条体系:

  • OpenAI 使用 runtimeState.flowState.openai
  • Kiro 使用独立 kiroRuntime

这意味着“flow 私有运行态放哪里”没有统一答案。后续新增 flow 时,要么复制第三套运行态入口,要么继续在 core 写例外分支。

3.3 source / driver 仍未彻底注册化

虽然已经有 flow-registrysource-registry,但 core 里仍直接识别:

  • OpenAI host
  • Kiro host
  • OpenAI / Kiro source family

这说明 source 系统还不是“flow 自带定义,core 只消费注册表”,而是“core 知道两个 flow 的页面事实”。

3.4 sidepanel 还是默认 flow 分支思维

当前 sidepanel 很多判断仍然是:

  • 默认 flow 视为 OpenAI
  • 非默认 flow 基本按 Kiro 处理

例如 target 读取、target 持久化、贡献页 target 解析、flow 切换后的字段同步,都带着明显的 openai / kiro 条件分支。

3.5 “按 flow 执行范围”表面通用,内部仍是双 flow 特判

stepExecutionRangeByFlow 在 UI 侧已经接近通用,但写回持久配置时仍只处理:

  • openai
  • kiro

这类设计最危险,因为它会制造“表面支持多 flow,实际只有两个 flow 真能落盘”的假通用。

3.6 文件和命名仍带历史语义

当前仍大量存在下列混合命名:

  • signup-page
  • open-chatgpt
  • platform-verify
  • plus-checkout
  • kiro-*
  • vps-panel

这些名字有的看起来像通用名,实际是 OpenAI 专属;有的则直接带品牌。继续保留会让后续架构再度滑回历史分支。

4. 重构原则

4.1 不做旧配置兼容,只做导入转换

本次不保留“先兼容着跑”的中间态。新系统上线后,运行时、持久化读写、sidepanel 消息、background 内部状态全部只认新合同。

原则是:

  • 旧配置、旧账号记录、旧 flow 产物只能通过导入器转换
  • 导入器是单向转换器,不是长期桥接层
  • 导入完成后的数据必须完全符合新合同
  • 除导入器外,任何模块都不再直接读写 panelModeopenaiIntegrationTargetIdkiroTargetIdkiroRuntime 等旧字段

4.2 通用层只负责“怎么跑一个 flow”

core 只解决这些问题:

  • flow 注册
  • source 注册
  • driver 注册
  • workflow 运行
  • 状态存储
  • sidepanel 动态渲染
  • 通用服务接入

core 不再知道任何 OpenAI 或 Kiro 业务步骤语义。

4.3 flow 私有能力留在 flow 内部

以下能力继续保留为 flow 私有:

  • OpenAI 的 OAuth、Plus、接码、平台绑定
  • Kiro 的 Builder ID、桌面授权、kiro.rs 上传
  • 任意新 flow 的站点特有页面状态机、验证码规则、成功判定和产物结构

4.4 命名必须先统一,再谈长期可维护性

如果 contract 抽象了,但目录和文件名还保留历史语义,后续阅读成本依然很高。本次重构必须把命名一并统一。

5. 第一层功能边界:公共能力与私有能力

这一层只回答一个问题:哪些能力应该是扩展级公共能力,哪些能力必须收回到各 flow 自己内部。

本层结论确定后,后续所有 contract、目录结构和配置模型都必须服从这条边界,不允许再反向把 flow 私有语义塞回公共层。

5.1 扩展级公共能力

当前项目真正应保留为全局公共能力的只有四块:

  • 项目壳层
  • 邮箱服务
  • 账户密码
  • IP 代理

其中:

  • 项目壳层 只包括顶部容器、flow 切换、开始/停止/重试、日志与运行态展示这些外层承载能力。
  • 邮箱服务 是跨 flow 的身份与收件基础设施。
  • 账户密码 指侧栏中的“账户密码”文本框,它的语义是“注册目标账号时使用的共享密码”。
  • IP 代理 是扩展级环境能力,不属于任何单独 flow。

5.2 邮箱服务需要继续重构统一

邮箱服务值得保留为公共层,但必须从历史 OpenAI 语义中继续剥离。

它在功能上只应该负责三类事情:

  • 生成注册邮箱
  • 提供收件与轮询能力
  • 维护当前轮次的邮箱身份

邮箱服务不应该继续承接这些内容:

  • 某个 flow 的验证码命中规则
  • 某个 flow 的页面跳转语义
  • 某个 flow 的身份保留分支
  • 某个 flow 的注册成功或失败判断

因此邮箱层应拆成两部分:

  • 公共邮箱服务 负责邮箱生成、收件、轮询、当前邮箱身份维护
  • flow 私有邮件规则 负责某个 flow 在某一步认哪封邮件、提取什么内容、何时算命中

结论:

  • 邮箱服务是公共能力
  • 邮件规则不是公共能力

5.3 “账户密码”是共享注册密码,不是公共凭据服务

当前侧栏的“账户密码”文本框,其真实产品语义已经确认:

  • 它不是平台后台登录密码
  • 它不是某个管理接口凭据
  • 它不是统一的凭据中心配置
  • 它只是“注册出来的目标账号要设置成什么密码”

因此这里不应再抽象出“公共凭据服务”。

正确做法是:

  • 保留一个全局公共的 共享注册密码
  • 各 flow 自己决定是否使用这份密码
  • 各 flow 自己决定在哪一步使用
  • 如果某个 flow 没有设置密码步骤,则直接忽略

这意味着:

  • 账户密码 是公共输入能力
  • 凭据结构 不是公共能力
  • 凭据产物字段 不是公共能力

5.4 凭据与账号产物必须保持 flow 私有

虽然不做公共凭据服务,但每个 flow 仍然会生成自己的账号产物。

例如:

  • OpenAI 可能产出邮箱、密码、session、OAuth 结果、平台接入结果
  • Kiro 可能产出邮箱、密码、refresh token、clientId、clientSecret、上传结果

这里允许公共的只有“外层展示容器”或“记录壳层”,不允许公共化的内容包括:

  • 主身份字段
  • token 字段
  • 上传字段
  • 绑定字段
  • 各类平台回调字段

结论:

  • 账号产物展示容器可以公共
  • 账号产物字段结构必须 flow 私有

5.5 IP 代理属于扩展级环境能力

IP 代理应直接定义为:

  • 扩展级公共能力
  • 与 flow 无关
  • 由 flow 声明“可用/必需/禁用”,但不拥有它

flow 最多只能声明:

  • 当前 flow 是否允许代理
  • 当前 flow 的哪些页面需要代理约束
  • 当前 flow 是否需要代理检测或 fail-close 策略

但代理配置、切换、应用、检测、诊断,都不属于 flow 私有模型。

5.6 第一层最终边界

本次重构在功能边界上最终固定为:

全局公共能力

  • 项目壳层
  • 邮箱服务
  • 共享注册密码
  • IP 代理

仅允许公共容器,不允许公共字段语义

  • 账号记录容器
  • 产物展示容器

flow 私有能力

  • 账号主身份模型
  • 邮件命中规则
  • 验证码规则
  • 注册步骤
  • 登录步骤
  • OAuth / callback
  • 支付
  • 上传
  • flow 最终凭据与产物字段结构

后续所有重构如果与这条边界冲突,以这条边界为准,不允许再为了省事把 flow 私有字段上提为公共模型。

6. 第二层产品模型:flow 与 target

这一层只回答两个问题:

  • flow 在产品上到底是什么
  • target 在产品上到底是什么

如果这一层不先定死,后面配置模型、侧栏模型和运行态模型就会继续在 panelMode / integrationTarget / targetId 之间摇摆。

6.1 flow 的产品定义

每个 flow 都应被定义为一条独立的“账号生产链路”。

它至少具备以下特征:

  • 有独立入口
  • 有独立步骤顺序
  • 有独立成功判定
  • 有独立最终产物
  • 只按需消费公共能力,例如邮箱、共享注册密码、IP 代理

因此,flow 不是“几步流程的组合”,而是一个完整产品单元。

结论:

  • openai 是一个完整 flow
  • kiro 是一个完整 flow
  • 未来新站点也必须是完整 flow
  • 不允许再把新站点业务塞进现有 flow 里做条件分支

6.2 target 的产品定义

target 不应继续被理解为历史意义上的 panelMode

正确的产品语义应该是:

  • target 是这个 flow 最终产物的去向
  • target 是这个 flow 最终服务的目标系统

例如:

  • OpenAI flow 的 target 可以是 CPA / SUB2API / Codex2API
  • Kiro flow 的 target 可以是 kiro-rs

因此:

  • flow 回答“怎么产出账号或产物”
  • target 回答“产出后要交给谁使用”

这两个概念必须严格分层,不允许再混用。

6.3 每个 flow 都必须自带 target 模型

以后不再允许:

  • 只有 OpenAI flow 有 target
  • Kiro flow 走另一套特殊 target 字段
  • 默认 flow 使用 panelMode,其他 flow 使用 targetId

统一要求如下:

  • 每个 flow 都必须有 selectedTarget
  • 每个 flow 都必须有 targets
  • 单 target flow 只是“只有一个 target”,不是“没有 target 概念”

即使某个 flow 当前只有一个 target,模型里也必须保留 target 层,只是在 UI 上可以隐藏选择器。

这样做的原因是:

  • 未来该 flow 如果新增第二个 target,不需要再次改核心模型
  • sidepanel 和 settings 不需要区分“哪个 flow 才有 target”

6.4 flow 的产品结构

从功能角度,每个 flow 都应至少包含以下部分:

  • flow 基本信息
  • flow 对公共能力的依赖声明
  • flow 私有配置
  • flow targets
  • flow 产物定义

进一步展开:

  • flow 基本信息
    • 名称
    • 说明
    • 是否可自动化
  • 公共能力依赖声明
    • 是否使用邮箱
    • 是否使用共享注册密码
    • 是否允许代理
  • flow 私有配置
    • 仅该 flow 自己理解的设置
  • flow targets
    • 一个或多个目标系统
  • flow 产物定义
    • 该 flow 最终生成什么结果

6.5 第二层最终结论

本次重构在产品模型上最终固定为:

  • flow = 独立账号生产产品线
  • target = flow 产物去向
  • 每个 flow 都必须天然支持自己的 target 模型
  • 全局只保留“当前选中的 flow”
  • 当前 target 永远从当前 flow 自己内部读取

由此带来的直接结果是:

  • panelMode 只允许存在于导入器输入映射里
  • openaiIntegrationTargetId / kiroTargetId 不再是长期 canonical 配置
  • sidepanel 不再需要围绕“默认 flow 是 OpenAI”建立逻辑

后续所有设计如果与这层产品模型冲突,以这层定义为准。

7. 第三层运行模型:统一节点承载,不统一阶段语义

这一层只回答一个问题:

  • 多 flow 体系下,到底应该统一什么样的运行流程模型

本层最终结论是:

  • 统一节点承载方式
  • 不统一跨 flow 的阶段语义

也就是说,core 只负责“如何承载一个 flow 的内部流程”,不负责替每个 flow 规定必须长成同一种产品流程形状。

7.1 不强制统一阶段

本次重构不再要求所有 flow 都映射到一套固定阶段,例如:

  • 准备
  • 进入
  • 验证
  • 成型
  • 接入
  • 交付

这种抽象在文档上容易显得整齐,但对真实多 flow 来说约束过强,后续会重新形成“表面通用、实际不好用”的壳层。

因此:

  • OpenAI 保持自己的内部流程形状
  • Kiro 保持自己的内部流程形状
  • 新 flow 也不需要被迫套进统一阶段模型

7.2 真正需要统一的是节点运行模型

虽然不统一阶段语义,但所有 flow 仍然必须共享同一套“节点承载方式”。

每个 flow 的内部流程都应被理解为:

  • 一组有顺序的节点
  • 节点之间存在前后关系
  • 每个节点都有清晰输入和结果
  • 节点可以被手动执行、自动执行、停止和重试

也就是说,core 只统一:

  • 节点是什么
  • 节点如何排序
  • 节点如何连接
  • 节点如何汇报状态

而不统一:

  • 节点一定属于哪个阶段
  • 某个数字步骤在所有 flow 里都代表什么

7.3 数字步骤只表示 flow 内部显示顺序

以后数字步骤只允许表达:

  • 当前 flow 内部的展示顺序

不再允许表达:

  • 跨 flow 的固定语义
  • 全局共享的产品阶段
  • 某个历史 OpenAI 10 步链路的编号意义

这意味着:

  • Step 4 不再天然等于“验证码步骤”
  • Step 7 不再天然等于“OAuth”
  • Step 9 不再天然等于“平台验证”

这些语义都必须下沉为 flow 私有流程定义。

7.4 节点的最小公共合同

从产品功能角度,每个节点只需要满足以下最小公共合同:

  • 有名称
  • 有顺序
  • 有前后关系
  • 有明确成功结果
  • 有明确失败结果
  • 可以手动执行
  • 可以自动执行
  • 可以停止
  • 可以重试

节点不应该再承载这些“假通用”要求:

  • 必须属于固定阶段
  • 必须服从跨 flow 的相同命名
  • 必须让不同 flow 共享同一种页面语义

7.5 外层统一状态,不统一流程内容

扩展外层只需要理解统一运行状态,不需要理解每个 flow 的内部阶段。

建议外层只保留以下状态集合:

  • 未开始
  • 运行中
  • 等待中
  • 需人工处理
  • 已停止
  • 已失败
  • 已完成

这些状态只服务于:

  • 侧栏展示
  • 自动运行控制
  • 停止 / 重试入口
  • 日志与记录

它们不应反过来要求 flow 把内部步骤硬映射成统一业务阶段。

7.6 执行范围绑定当前 flow 的节点顺序

执行范围 这个能力未来仍然保留,但其产品定义应明确为:

  • 对当前 flow 可见节点顺序的执行限制

它不再代表:

  • 全局统一步骤范围
  • 跨 flow 的阶段范围
  • OpenAI 历史编号的范围

也就是说,执行范围始终只作用于“当前 flow 自己的节点序列”。

7.7 第三层最终结论

本层最终固定为:

  • 不统一所有 flow 的阶段语义
  • 不统一所有 flow 的产品流程形状
  • 每个 flow 自己定义内部流程
  • core 只统一节点承载方式
  • 数字步骤只代表当前 flow 的显示顺序
  • 扩展外层只理解统一运行状态
  • 执行范围只绑定当前 flow 的节点顺序

后续如果有设计要求把所有 flow 再次硬映射成一套跨 flow 固定阶段,以本层结论为准,默认不采纳。

8. 第四层界面分工:公共壳层与 flow 工作面

这一层只回答一个问题:

  • sidepanel 到底哪些界面必须永远公共,哪些界面必须彻底交给 flow 自己

如果这层不先定死,后续所有 flow 接入都会继续把 openai / kiro / new-flow 的条件分支堆进侧栏主文件。

8.1 只保留两层界面

本次重构后,sidepanel 只保留两层界面:

  • 公共壳层
  • flow 工作面

不再增加第三层“伪通用业务面板”。

原因很简单:

  • 公共壳层负责承载扩展级操作
  • flow 工作面负责承载 flow 私有配置与流程内容

这样结构最稳,也最不容易重新膨胀。

8.2 公共壳层放什么

公共壳层只允许放扩展级公共入口与全局控制入口,包括:

  • flow 选择
  • target 选择
  • 开始 / 停止 / 重试 / 自动
  • 当前运行状态
  • 日志区
  • 账号记录入口
  • 文档 / 引导 / 更新提示入口
  • 贡献 / 使用教程按钮
  • 公共能力入口
  • 邮箱服务
  • 共享注册密码
  • IP 代理

这里的“贡献 / 使用教程”按钮属于公共壳层入口,但其功能逻辑必须按当前 flow 适配。

也就是说:

  • 按钮入口位置是公共的
  • 点击后的目标页面、说明内容、贡献适配逻辑由当前 flow 决定

不允许再把它写成某一个默认 flow 的固定行为。

8.3 flow 工作面放什么

flow 工作面只允许承载该 flow 自己的内容,包括:

  • flow 私有配置
  • flow 私有步骤列表
  • flow 私有运行态展示
  • flow 私有人工补位入口
  • flow 私有产物展示字段

例如:

  • OpenAI 的 Plus、OAuth、平台接入、手机验证,只能放在 OpenAI 工作面
  • Kiro 的桌面授权、上传到 kiro.rs,只能放在 Kiro 工作面

未来新增 flow 也必须遵守同样规则。

8.4 步骤列表属于 flow 私有界面

步骤列表不属于公共界面。

公共壳层最多只负责:

  • 放置步骤列表容器
  • 提供统一骨架样式
  • 提供统一按钮状态和颜色规则

但以下内容都必须由 flow 自己决定:

  • 有哪些步骤
  • 步骤叫什么
  • 步骤显示什么说明
  • 哪些步骤可执行
  • 哪些步骤可跳过
  • 哪些步骤需要人工补位

8.5 账号记录采用“公共入口 + 私有内容”

账号记录建议固定为:

  • 公共入口
  • flow 私有内容

也就是说:

  • 记录页或记录弹层入口是公共的
  • 分页、筛选、基础容器可以公共
  • 每条记录里显示哪些字段,按当前 flow 决定

这样既保留统一入口,也避免为了统一记录展示而把所有 flow 的产物字段重新揉成一个假通用结构。

8.6 公共能力入口的边界

公共区可以保留三类公共能力入口:

  • 邮箱服务
  • 共享注册密码
  • IP 代理

但这些公共入口只负责:

  • 配置
  • 当前状态展示
  • 基础校验

它们不负责:

  • 解释某个 flow 的业务步骤
  • 解释某个 flow 的页面语义
  • 承载某个 flow 的专属运行逻辑

这意味着:

  • OpenAI 专属邮箱模式说明,应回到 OpenAI 工作面
  • Kiro 专属密码说明,应回到 Kiro 工作面
  • 某个 flow 的代理特殊策略,也应由该 flow 自己声明和解释

8.7 target 选择器仍属于公共壳层

target 虽然属于当前 flow 的内部模型,但从用户交互角度,它属于“开跑前的全局决策”。

因此:

  • target 选择器放在公共壳层
  • target 的可选项由当前 flow 决定
  • target 的说明文案也由当前 flow 决定

这样用户能在统一入口完成“跑哪个 flow、产物交给谁”的全局决策。

8.8 第四层最终结论

本层最终固定为:

  • sidepanel 只保留“公共壳层 + flow 工作面”两层
  • 公共壳层承载扩展级入口和全局控制
  • flow 工作面承载 flow 私有配置、步骤、运行态和产物
  • 步骤列表属于 flow 私有界面
  • 账号记录采用“公共入口 + 私有内容”
  • 贡献 / 使用教程按钮属于公共壳层入口,但功能逻辑必须按当前 flow 适配
  • 不允许再把任何 OpenAI / Kiro / 新 flow 的专属业务配置继续堆进公共区

9. 目标架构

建议收口为以下目录形态:

core/
  flow-kernel/
    flow-registry.js
    source-registry.js
    driver-registry.js
    settings-schema.js
    runtime-state.js
    workflow-engine.js
    step-registry.js
    tab-runtime.js
    logging-status.js

flows/
  index.js

  openai/
    flow.js
    settings.js
    state.js
    sources.js
    drivers.js
    steps/
    content/
    mail/
      rules.js
    contribution/

  kiro/
    flow.js
    settings.js
    state.js
    sources.js
    drivers.js
    steps/
    content/
    contribution/

imports/
  legacy/
    settings-importer.js
    account-records-importer.js
    flow-artifacts/
      openai.js
      kiro.js

第一阶段可以不强制先物理移动到 core/flow-kernel/,但逻辑上必须先收成这套边界。

补充要求:

  • imports/legacy/ 是全仓库唯一允许理解旧字段、旧结构、旧命名的目录。
  • core/flows/ 不再保留任何旧字段回写逻辑。

10. 统一合同

10.1 配置合同

唯一 canonical 配置结构:

settingsState = {
  schemaVersion,
  activeFlowId,
  services: {
    account,
    email,
    proxy,
  },
  flows: {
    [flowId]: {
      selectedTargetId,
      targets: {
        [targetId]: {}
      },
      autoRun: {
        stepExecutionRange,
      },
      ui: {},
      features: {},
    }
  }
}

要求:

  • selectedTargetId + targets[targetId] 是唯一 target 入口。
  • 不再以 openaiIntegrationTargetIdkiroTargetId 作为 canonical 字段。
  • panelMode 不再作为内部真实配置语义,也不再出现在 sidepanel payload、background 持久化写入路径和运行时配置读取路径中。
  • 每个 flow 都必须使用 selectedTargetId + targets[targetId] 组合。
  • target 专属字段只能挂在对应 targets[targetId] 下,不再允许提升到 flow 顶层或全局顶层。
  • 旧配置文件不能被直接加载运行,只能先经过导入转换器。

10.2 运行态合同

唯一 canonical 运行态结构:

runtimeState = {
  activeFlowId,
  activeRunId,
  currentNodeId,
  nodeStatuses,
  sharedState: {},
  serviceState: {
    account: {},
    email: {},
    proxy: {},
  },
  flowState: {
    [flowId]: {
      session: {},
      nodes: {},
      artifacts: {},
      ui: {},
    }
  }
}

要求:

  • 删除独立 kiroRuntime 作为长期入口。
  • OpenAI、Kiro、未来新 flow 的私有运行态全部进入 runtimeState.flowState[flowId]
  • 顶层不再持久化任何 flow 私有扁平字段。
  • 运行态不做旧快照导入;导入只处理持久配置与持久产物,导入完成后从新运行态起跑。
  • 如需便捷读取视图,只能从 canonical flowState 派生,不能再反向写出独立运行态入口。

10.3 flow 定义合同

每个 flow 统一导出:

{
  id,
  label,
  services,
  capabilities,
  settingsGroups,
  targets,
  settingsShape,
  runtimeStateShape,
  sources,
  drivers,
  workflow,
  artifactSchema,
  importers,
  contributionAdapters,
}

要求:

  • flow-registry 只合并 flow 定义。
  • settings-schemasource-registrydriver-registrystep-registry 都只消费 flow 导出的定义。
  • flow 私有导入转换规则也由 flow 自己提供,core 只负责分发到对应 importer。
  • core 不再直接声明某个 flow 的 target、source、driver。

10.4 source 合同

每个 source 至少声明:

  • id
  • flowId
  • kind
  • label
  • hostPatterns
  • familyMatcher
  • injectFiles
  • readyPolicy
  • cleanupScopes
  • tabReusePolicy

要求:

  • host 判断由 flow source 定义驱动。
  • unknown-source 仅做诊断,不自动回退到任意业务 source。
  • callback cleanup 必须由 cleanupScope -> ownerSource 注册表驱动。

10.5 driver 合同

每个 driver 至少声明:

  • id
  • sourceId
  • commands
  • injectFiles

要求:

  • driver 负责“页面能做什么”
  • source 负责“页面是什么、如何识别、如何复用、如何清理”

10.6 step 合同

每个 step 统一使用:

  • id
  • order
  • key
  • title
  • sourceId
  • driverId
  • command
  • mailRuleId

要求:

  • step key 只表达 flow 内语义,不再混入历史平台词和伪通用词。
  • background/steps/*.js 这种共享目录最终要消失,改由各 flow 自己维护 steps/

11. 命名统一方案

11.1 flow 目录命名

  • flows/openai/
  • flows/kiro/

未来新增 flow 一律使用 flows/<flow-id>/

11.2 source 命名

统一格式:

<flow-id>-<page-role>
mail-<provider>
panel-<target>

例如:

  • openai-auth
  • openai-entry
  • openai-checkout
  • openai-paypal
  • openai-gopay
  • kiro-register
  • kiro-desktop-authorize
  • panel-sub2api
  • panel-cpa
  • mail-gmail

11.3 driver 命名

统一格式:

flows/<flow-id>/content/<page-role>.js
flows/<flow-id>/steps/<step-role>.js

不再使用历史伪通用名作为全局 driver 语义。

11.4 OpenAI 文件重命名建议

以下文件建议统一迁移:

  • flows/openai/content/openai-auth.js -> flows/openai/content/openai-auth.js

  • flows/openai/content/plus-checkout.js -> flows/openai/content/checkout-page.js

  • flows/openai/content/paypal-flow.js -> flows/openai/content/paypal-page.js

  • flows/openai/content/gopay-flow.js -> flows/openai/content/gopay-page.js

  • flows/openai/content/sub2api-panel.js -> flows/openai/content/sub2api-panel-page.js

  • flows/openai/content/vps-panel.js -> flows/openai/content/cpa-panel-page.js

  • flows/openai/background/steps/open-chatgpt.js -> flows/openai/steps/open-entry.js

  • flows/openai/background/steps/submit-signup-email.js -> flows/openai/steps/submit-identifier.js

  • flows/openai/background/steps/fill-password.js -> flows/openai/steps/submit-password.js

  • flows/openai/background/steps/fetch-signup-code.js -> flows/openai/steps/submit-signup-code.js

  • flows/openai/background/steps/fill-profile.js -> flows/openai/steps/submit-profile.js

  • flows/openai/background/steps/wait-registration-success.js -> flows/openai/steps/wait-register-complete.js

  • flows/openai/background/steps/oauth-login.js -> flows/openai/steps/start-oauth-login.js

  • flows/openai/background/steps/fetch-login-code.js -> flows/openai/steps/submit-login-code.js

  • flows/openai/background/steps/confirm-oauth.js -> flows/openai/steps/confirm-oauth-consent.js

  • flows/openai/background/steps/platform-verify.js -> flows/openai/steps/complete-platform-bind.js

11.5 Kiro 文件重命名建议

以下文件建议统一迁移:

  • flows/kiro/background/register-runner.js -> flows/kiro/steps/register-flow.js
  • flows/kiro/background/desktop-authorize-runner.js -> flows/kiro/steps/desktop-authorize-flow.js
  • flows/kiro/background/publisher-kiro-rs.js -> flows/kiro/steps/upload-credential.js
  • flows/kiro/background/state.js -> flows/kiro/state.js
  • flows/kiro/content/register-page.js -> flows/kiro/content/register-page.js
  • flows/kiro/content/desktop-authorize-page.js -> flows/kiro/content/desktop-authorize-page.js

12. 替换式升级与导入转换策略

阶段 1:先定 canonical contract 与最终目录边界

目标:

  • 定义统一的 settings、runtime、flow、source、driver、step 合同
  • 定义 core/flows/imports/legacy/ 三层边界
  • 明确旧字段只允许出现在导入器中

产出:

  • 更新设计文档
  • 明确迁移边界

完成标准:

  • 不再允许出现“新 flow 以后再看放哪”这种模糊点

阶段 2:统一配置模型

目标:

  • 让所有 flow 都走 settingsState.flows[flowId]
  • 停止所有新代码对旧配置字段的直接读写

动作:

  • 重写 core/flow-kernel/settings-schema.js
  • selectedTargetId 作为统一 target 入口
  • 改写 background.jsbuildSettingsStatePatchFromFlatUpdatesbuildAutoRunFreshResetSettingsStatebuildFreshAutoRunKeepState
  • 改写 background/message-router.jssidepanel/sidepanel.js 的设置写入路径,只提交 canonical patch
  • panelMode / openaiIntegrationTargetId / kiroTargetId 从运行时和持久化写入路径移除

完成标准:

  • 任意 flow 都可通过相同 API 读取当前 target 和 flow 设置
  • 正常保存、导出、恢复流程里不再出现旧 target 字段

阶段 3:统一运行态模型

目标:

  • kiroRuntime 并入 runtimeState.flowState.kiro
  • 让 OpenAI 与 Kiro 都按同一种 flow 私有运行态承载方式工作

动作:

  • 重写 core/flow-kernel/runtime-state.js
  • flows/kiro/background/state.js 合并或迁入 flows/kiro/state.js
  • 给 OpenAI 与 Kiro 都定义 flow 私有状态 shape 与 reset 规则
  • 删除独立 Kiro 运行态主入口
  • 停止持久化所有 flow 私有顶层扁平字段

完成标准:

  • core 不再区分“OpenAI 私有状态”与“Kiro 私有状态”的存储方式
  • 自动运行、fresh reset、日志回写都只消费统一运行态结构

阶段 4:建立单向导入转换器

目标:

  • 让旧数据只能通过导入器进入新系统
  • 明确“导入”与“运行时兼容”是两件不同的事

动作:

  • 新建 imports/legacy/settings-importer.js
  • 新建 imports/legacy/account-records-importer.js
  • 按需新增 flows/openai/importers/*flows/kiro/importers/* 用于旧产物字段映射
  • 导入器负责识别 panelModeopenaiIntegrationTargetIdkiroTargetIdstepExecutionRangeByFlowkiroRuntime 以及旧账号记录结构
  • 导入结果统一输出为新 settingsState、新账号记录结构、新 flow 产物结构
  • 明确不导入旧运行态快照

完成标准:

  • 旧配置文件只能通过“导入”按钮进入系统,不能被直接加载运行
  • 导入完成后,系统内部不再保留旧字段副本

阶段 5:统一 flow 注册与 source/driver 注册

目标:

  • 让 flow 目录自带 source、driver、workflow、state、settings 定义

动作:

  • 新建 flows/index.js
  • 把 flow 相关定义从 core/flow-kernel/flow-registry.jscore/flow-kernel/source-registry.jscore/flow-kernel/flow-capabilities.jsdata/step-definitions.jscore/flow-kernel/step-registry.js 拆到各 flow 内
  • source-registry 改为只做合并与查询
  • workflow-engine 与 step registry 改为只消费 flow 导出定义

完成标准:

  • 新增 flow 时只新增 flow 定义,不改 core host 判断语义

阶段 6:统一 sidepanel 驱动方式

目标:

  • sidepanel 完全按 registry 驱动,而不是按 openai / kiro 条件分支

动作:

  • 重写 sidepanel/sidepanel.js
  • 调整 sidepanel/contribution-mode.jssidepanel/account-records-manager.js、相关 flow 私有展示逻辑
  • flow selector、target selector、visible groups、capability 全部从 registry 派生
  • stepExecutionRange 改成真正按当前 flow 通用读写
  • 账号记录区改成“公共列表壳层 + flow 私有渲染器”

完成标准:

  • sidepanel 不再依赖默认 flow 是 OpenAI 的假设
  • sidepanel 不再直接处理 panelModekiroTargetId 两套并列写法

阶段 7:统一目录与文件命名

目标:

  • 把 OpenAI 与 Kiro 都迁入 flows/<flow-id>/

动作:

  • 重命名文件
  • 更新所有 import / importScripts / 注入列表 / 测试引用
  • 删除历史伪通用文件名
  • content/*.jsbackground/steps/*.jsbackground/kiro/* 分别迁入对应 flow 目录

完成标准:

  • 新人看目录时能立即分清 core 与 flow 私有实现

阶段 8:删除旧兼容层与旧字段路径

目标:

  • 删除所有只为迁移存在的旧字段、旧别名、旧路径和旧命名

动作:

  • 删除 signup-page -> openai-auth 长期别名
  • 删除 kiroRuntime 独立入口
  • 删除 panelMode 作为内部真实 target 语义
  • 删除 background.jsbackground/message-router.jsbackground/navigation-utils.jsbackground/auto-run-controller.js 里所有核心旧字段桥接逻辑
  • 删除所有 activeFlowId === 'kiro' / activeFlowId === DEFAULT_ACTIVE_FLOW_ID 的核心结构分支
  • 用新的 canonical contract 测试替换旧兼容写回测试;旧字段只保留导入器测试

完成标准:

  • 仓库里只有 imports/legacy/ 与其测试还认识旧字段
  • core 只理解“某个已注册 flow”,不理解“OpenAI 还是 Kiro”

13. 实施顺序要求

为了避免第三次半重构,本次必须按顺序推进:

  1. 先收口 contract
  2. 再统一 settings
  3. 再统一 runtime
  4. 再建立导入转换器
  5. 再拆 flow registry/source/driver
  6. 再统一 sidepanel
  7. 再迁目录和文件名
  8. 最后删旧字段与旧桥接逻辑

禁止的做法:

  • 先新增第三个 flow,再回头修 core
  • 先重命名文件,但 contract 仍旧双轨
  • 为了快,继续在 sidepanel 或 background 增加新的 openai / kiro / new-flow 三分支
  • 一边写 canonical 结构,一边继续保留旧字段双写
  • 让旧配置在启动时被直接读取并“尽量凑合可用”

14. 完成判定

本次重构只有在满足以下条件时才算完成:

  • 新增一个新 flow 时,不需要修改 settings-schema 核心结构。
  • 新增一个新 flow 时,不需要修改 runtime-state 核心结构。
  • 新增一个新 flow 时,不需要在 sidepanel 主逻辑中增加 flow 名称判断分支。
  • 新增一个新 flow 时,不需要在 source-registry core 里写新 host 判断。
  • OpenAI 与 Kiro 都已经迁入统一命名体系。
  • background.jsbackground/message-router.jssidepanel/sidepanel.js 的正常运行路径不再读写 panelModeopenaiIntegrationTargetIdkiroTargetIdkiroRuntime
  • 旧配置文件不能直接运行,只能通过导入转换器进入新结构。
  • 旧运行态快照不再支持恢复。
  • 历史旧字段只允许存在于 imports/legacy/ 及其测试中。

15. 非目标

本方案当前不解决:

  • 新增具体第三个 flow 的业务实现
  • OpenAI 私有流程本身的业务优化
  • Kiro 私有流程本身的业务优化
  • 所有公共工具立即物理迁移到 core/ 目录
  • 旧配置的自动无感兼容启动
  • 旧运行态快照的兼容恢复

本方案只解决“以后再加 flow 时,不要再从根上出结构问题”。

16. 最终结论

这次重构必须被当成一次“彻底替换式升级”,不是普通功能开发。

如果继续在现有 openai + kiro 双轨基础上补第三个 flow,后续仍会再次进入:

  • core 继续膨胀
  • 命名继续污染
  • 兼容层继续叠加
  • 每次改动都更累

因此本次必须一次性完成:

  • 统一 contract
  • 统一命名
  • 统一目录边界
  • 删除长期双轨
  • 取消旧配置运行时兼容
  • 只保留单向导入转换器

完成后,后续 flow 才能真正变成“新增模块”,而不是“继续改核心”;旧世界也只能通过导入器进入新世界,而不能再反向定义新系统的结构。