22 KiB
分阶段迁移计划
1. 概述
EBA 架构涉及 langbot-plugin-sdk、LangBot 后端、LangBot 前端、文档和示例插件等多个仓库的改动。为降低风险、保证系统稳定性,采用分阶段渐进式迁移策略。
1.1 阶段总览
| 阶段 | 名称 | 范围 | 依赖 |
|---|---|---|---|
| Phase 1 | SDK 实体层 | langbot-plugin-sdk | 无 |
| Phase 2 | 适配器重构 | LangBot 后端 | Phase 1 |
| Phase 3 | 核心系统 | LangBot 后端 | Phase 2 |
| Phase 4 | 插件 SDK 集成 | langbot-plugin-sdk + LangBot | Phase 3 |
| Phase 5 | WebUI 编排面板 | LangBot 前端 | Phase 3 |
| Phase 6 | 文档与示例 | langbot-wiki + langbot-plugin-demo | Phase 4, 5 |
1.2 核心原则
- 每个阶段结束后系统可运行:任何阶段完成后,现有功能不受影响
- 向后兼容贯穿全程:旧接口在整个迁移期间保持可用
- 先 SDK 后实现:先定义好接口和模型,再做具体实现
- 先核心适配器后边缘:优先迁移用户量大的适配器
2. Phase 1:SDK 实体层
目标:在 langbot-plugin-sdk 中定义新的事件体系、通用实体、API 接口和适配器基类。
仓库:langbot-plugin-sdk
2.1 任务清单
| # | 任务 | 文件/模块 | 说明 |
|---|---|---|---|
| 1.1 | 定义通用事件基类层次 | api/entities/builtin/platform/events.py |
新增 MessageReceivedEvent, MessageEditedEvent, GroupMemberJoinedEvent 等,保留现有 FriendMessage/GroupMessage |
| 1.2 | 定义平台特有事件基类 | api/entities/builtin/platform/events.py |
新增 PlatformSpecificEvent |
| 1.3 | 扩展通用实体 | api/entities/builtin/platform/entities.py |
新增 User(统一 Friend/GroupMember 的基础)、Channel 等,保留现有实体 |
| 1.4 | 清理消息组件 | api/entities/builtin/platform/message.py |
将 WeChatMiniPrograms 等 WeChat 特有组件标记为 platform-specific,不再作为通用组件 |
| 1.5 | 定义新适配器基类 | api/definition/abstract/platform/adapter.py |
新增 AbstractPlatformAdapter(继承现有 AbstractMessagePlatformAdapter 并扩展通用 API 方法),保留旧基类 |
| 1.6 | 定义 API 能力声明 | api/definition/abstract/platform/capabilities.py(新文件) |
AdapterCapabilities 数据类,声明适配器支持的事件和 API |
| 1.7 | 定义 NotSupportedError |
api/entities/builtin/platform/errors.py(新文件) |
可选 API 未实现时抛出的异常 |
2.2 关键设计约束
- 所有新增定义以新增文件或新增类的方式引入,不修改现有类的字段和方法签名
- 现有
AbstractMessagePlatformAdapter保留不动,新基类AbstractPlatformAdapter继承它 - 新事件类与旧事件类并存,通过
event_type字段(命名空间字符串)区分
2.3 验收标准
- 所有新增类可正常 import 且通过类型检查
- 现有
FriendMessage,GroupMessage,AbstractMessagePlatformAdapter等类行为不变 - 新增单元测试覆盖事件序列化/反序列化、实体构造
- SDK 版本号 minor bump(如
0.x.0→0.x+1.0)
3. Phase 2:适配器重构
目标:将现有单文件适配器迁移到独立目录结构,实现新事件监听和通用 API。
仓库:LangBot(后端)
3.1 适配器迁移优先级
根据用户量和代表性,建议按以下顺序迁移:
| 优先级 | 适配器 | 理由 |
|---|---|---|
| P0 | Telegram | 用户量大,API 最完善,适合作为参考实现 |
| P0 | Discord | 国际用户主要平台,事件类型丰富 |
| P1 | aiocqhttp(OneBot v11) | 国内 QQ 用户主要适配器 |
| P1 | Satori | 通用协议适配器,覆盖多个平台 |
| P2 | Lark / DingTalk / Slack | 企业平台,用户量中等 |
| P2 | qqofficial / WeChat 系列 | 国内用户 |
| P3 | Kook / LINE / WeCom 系列 | 用户量较小 |
| P3 | WebSocket | 内置适配器,相对简单 |
| P4 | legacy/* | 遗留适配器,按需决定是否迁移或废弃 |
3.2 单个适配器迁移步骤(以 Telegram 为例)
| # | 任务 | 说明 |
|---|---|---|
| 2.1 | 创建目录结构 | pkg/platform/adapters/telegram/ 下创建 __init__.py, adapter.py, event_converter.py, message_converter.py, api_impl.py, types.py, manifest.yaml |
| 2.2 | 迁移消息转换器 | 将 TelegramMessageConverter 从 sources/telegram.py 搬到 adapters/telegram/message_converter.py,逻辑不变 |
| 2.3 | 重写事件转换器 | 新的 TelegramEventConverter 支持将 Telegram Update 转换为所有通用事件类型(不只是消息),不支持的事件转为 PlatformSpecificEvent |
| 2.4 | 实现通用 API | 在 api_impl.py 中实现 edit_message, delete_message, get_group_info 等 Telegram 支持的通用 API |
| 2.5 | 实现透传 API | 在 adapter.py 中实现 call_platform_api,将 action 映射到 Telegram Bot API 调用 |
| 2.6 | 声明能力 | 在 manifest.yaml 或适配器类中声明支持的事件和 API 列表 |
| 2.7 | 新建 Adapter 主类 | TelegramAdapter 继承 AbstractPlatformAdapter(新基类),委托各模块实现 |
| 2.8 | 更新 manifest.yaml | 更新 execution.python.path 指向新位置 |
| 2.9 | 验证 | 确保新适配器通过现有消息收发流程的测试 |
3.3 基础设施任务
| # | 任务 | 说明 |
|---|---|---|
| 2.A | 创建 adapters/_base/ |
将 SDK 中新基类的运行时辅助代码放在此处(如事件分发辅助函数) |
| 2.B | 更新 ComponentDiscovery | 使 discover_blueprint 支持扫描 adapters/ 子目录中的 YAML |
| 2.C | 更新 templates/components.yaml |
将 fromDirs 从 pkg/platform/sources/ 改为 pkg/platform/adapters/(过渡期两个都扫描) |
| 2.D | 保留旧 sources/ | 过渡期不删除旧文件,通过 manifest 的 deprecated: true 标记 |
3.4 验收标准
- 已迁移的适配器在新目录结构下正常启动和收发消息
- 新事件(如
message.edited)在支持的平台上正确触发 - 通用 API(如
edit_message)在支持的平台上正确执行 - 未迁移的适配器(仍在
sources/)继续正常工作 - ComponentDiscovery 同时扫描新旧目录
4. Phase 3:核心系统
目标:实现 EventBus、EventRouter 和事件处理器框架,将事件从适配器分发到不同的处理器。
仓库:LangBot(后端)
4.1 任务清单
| # | 任务 | 文件/模块 | 说明 |
|---|---|---|---|
| 3.1 | 实现 EventBus | pkg/platform/event_bus.py(新文件) |
事件总线:接收适配器事件,进行日志记录,分发给 EventRouter |
| 3.2 | 实现 EventRouter | pkg/platform/event_router.py(新文件) |
事件路由引擎:读取 Bot 的 event_handlers 配置,匹配事件类型,分发到对应 Handler |
| 3.3 | 实现 PipelineHandler | pkg/platform/handlers/pipeline_handler.py |
将 message.received 事件转为现有 Query,进入 Pipeline 流水线 |
| 3.4 | 实现 AgentHandler | pkg/platform/handlers/agent_handler.py |
直接调用 RequestRunner 处理事件,不经过 Pipeline 多 Stage 流程 |
| 3.5 | 实现 WebhookHandler | pkg/platform/handlers/webhook_handler.py |
将事件 POST 到外部 URL,解析响应执行动作(重构现有 WebhookPusher) |
| 3.6 | 实现 PluginHandler | pkg/platform/handlers/plugin_handler.py |
将事件分发给插件 EventListener(复用现有 plugin_connector 机制) |
| 3.7 | Bot 实体扩展 | pkg/entity/persistence/bot.py |
新增 event_handlers JSON 字段 |
| 3.8 | 数据库迁移 | pkg/persistence/migrations/ |
新增迁移脚本:添加 event_handlers 列,将现有 use_pipeline_uuid 数据迁移为 event_handlers 格式 |
| 3.9 | 重构 RuntimeBot | pkg/platform/botmgr.py |
将 initialize() 中硬编码的 on_friend_message/on_group_message 回调替换为通过 EventBus 分发所有事件 |
| 3.10 | 重构 MessageAggregator | pkg/pipeline/aggregator.py |
从 RuntimeBot 解耦,作为 PipelineHandler 的内部机制(只对 message.received 事件生效) |
| 3.11 | Agent Handler 中 RequestRunner 解耦 | pkg/provider/runner.py + handlers |
RequestRunner 需要能独立于 Pipeline Stage 运行,为 Agent Handler 提供轻量调用路径 |
| 3.12 | HTTP API 扩展 | pkg/api/http/controller/ |
新增/更新 Bot API 端点以支持 event_handlers 的 CRUD |
4.2 数据迁移策略
现有 Bot 表有 use_pipeline_uuid 字段,需要自动迁移为 event_handlers:
# 迁移逻辑伪代码
for bot in all_bots:
if bot.use_pipeline_uuid:
bot.event_handlers = [
{
"event_type": "message.received",
"handler_type": "pipeline",
"handler_config": {
"pipeline_uuid": bot.use_pipeline_uuid
}
}
]
else:
bot.event_handlers = []
4.3 RuntimeBot 重构要点
当前 RuntimeBot.initialize() 硬编码注册两个回调:
# 现有代码 (botmgr.py)
self.adapter.register_listener(FriendMessage, on_friend_message)
self.adapter.register_listener(GroupMessage, on_group_message)
重构后改为注册通用事件回调:
# 新代码
async def on_event(event: Event, adapter: AbstractPlatformAdapter):
await self.event_bus.emit(
bot_uuid=self.bot_entity.uuid,
event=event,
adapter=adapter,
)
# 注册所有事件类型的统一回调
self.adapter.register_listener(Event, on_event)
EventBus 接收事件后,调用 EventRouter 按配置分发。
4.4 事件处理器执行流程
EventBus.emit(bot_uuid, event, adapter)
│
▼
EventRouter.route(bot_uuid, event)
│ 查询 bot.event_handlers 配置
│ 匹配 event_type(精确匹配 > 通配符 *)
▼
匹配到的 Handler(s)
│
├── PipelineHandler.handle(event, adapter)
│ │ 仅支持 message.received
│ │ 构造 Query → MessageAggregator → QueryPool → Pipeline
│ └── 沿用现有完整流水线机制
│
├── AgentHandler.handle(event, adapter)
│ │ 根据 handler_config 选择 RequestRunner
│ │ 直接调用 runner.run() 处理事件
│ └── 将结果通过 adapter API 回复
│
├── WebhookHandler.handle(event, adapter)
│ │ 序列化事件为 JSON
│ │ POST 到 handler_config.url
│ └── 解析响应,执行动作(回复消息、调用 API 等)
│
└── PluginHandler.handle(event, adapter)
│ 通过 plugin_connector 分发给插件
└── 插件 EventListener 处理
4.5 验收标准
message.received事件通过 PipelineHandler 正确进入现有 Pipeline(与旧行为一致)- 新增事件(如
group.member_joined)能通过 PluginHandler 分发给插件 - AgentHandler 能直接调用 RequestRunner(至少
local-agent)处理事件并回复 - WebhookHandler 能将事件 POST 到外部 URL
- 数据库迁移正确执行,
use_pipeline_uuid数据迁移到event_handlers - 现有 Bot 在不修改配置的情况下行为不变(自动迁移保证)
5. Phase 4:插件 SDK 集成
目标:将新事件和 API 通过插件 SDK 暴露给插件开发者,同时实现兼容层。
仓库:langbot-plugin-sdk + LangBot
5.1 任务清单
| # | 任务 | 说明 |
|---|---|---|
| 4.1 | 新增插件事件包装 | 在 api/entities/events.py 中为每个通用事件新增插件级事件类(如 MessageEditedReceived, MemberJoinedReceived) |
| 4.2 | 兼容层实现 | PersonMessageReceived / GroupMessageReceived 由新的 MessageReceivedEvent 自动生成,旧事件作为新事件的 alias |
| 4.3 | 新 API 暴露 | 在 LangBotAPIProxy 中新增方法:edit_message, delete_message, get_group_info, get_user_info, call_platform_api 等 |
| 4.4 | 通信协议扩展 | 在 entities/io/actions/enums.py 中新增 action 枚举(如 EDIT_MESSAGE, DELETE_MESSAGE, GET_GROUP_INFO, CALL_PLATFORM_API) |
| 4.5 | Runtime Handler 扩展 | 在 PluginConnectionHandler / ControlConnectionHandler 中添加新 action 的处理逻辑 |
| 4.6 | EventListener 扩展 | 确保 @handler() 装饰器支持注册新事件类型 |
| 4.7 | QueryBasedAPI 扩展 | 在 QueryBasedAPIProxy 中新增事件上下文相关的 API(如 get_event_source_adapter) |
5.2 兼容层详细设计
新事件系统 旧事件系统(兼容层)
───────────── ─────────────────
MessageReceivedEvent ┌→ PersonMessageReceived (chat_type == "private")
(chat_type: "private"|"group") ┤
└→ GroupMessageReceived (chat_type == "group")
实现方式:在 RuntimeEventDispatcher 中,当分发 MessageReceivedEvent 给插件时,同时生成对应的旧事件类实例。插件可以用新事件类或旧事件类注册 handler,都能收到。
5.3 验收标准
- 现有插件(使用旧事件和 API)无需修改即可运行
- 新插件可以使用新事件类型(如
MemberJoinedReceived)注册 handler - 新 API(如
edit_message)可通过self.edit_message()或event_context.edit_message()调用 - 透传 API
call_platform_api可正常调用适配器特有功能 - 所有新 action 的通信协议正确工作(stdio / WebSocket)
6. Phase 5:WebUI 编排面板
目标:在 WebUI 的 Bot 管理页面实现事件处理器的可视化编排。
仓库:LangBot(前端 web/)
6.1 任务清单
| # | 任务 | 说明 |
|---|---|---|
| 5.1 | Bot 编辑页面扩展 | 在 Bot 编辑页面新增「事件处理」面板 |
| 5.2 | 事件处理器列表组件 | 可视化展示当前 Bot 的 event_handlers 列表,支持增删改排序 |
| 5.3 | 事件类型选择器 | 下拉选择事件类型(命名空间分组展示),支持通配符 * |
| 5.4 | Handler 类型选择与配置 | 选择 handler 类型后展示对应的配置表单(Pipeline 选择器、Runner 选择器、Webhook URL 等) |
| 5.5 | Pipeline Handler 配置 | 复用现有的 Pipeline 选择 UI(从现有 use_pipeline_uuid 选择器迁移) |
| 5.6 | Agent Handler 配置 | Runner 选择器(local-agent / dify / n8n / coze 等)+ Runner 参数配置表单 |
| 5.7 | Webhook Handler 配置 | URL 输入、认证方式选择、Header 配置 |
| 5.8 | Plugin Handler 配置 | 通常无需额外配置,分发给所有匹配的插件 EventListener |
| 5.9 | HTTP API 对接 | 前端调用后端 API 保存/读取 event_handlers 配置 |
| 5.10 | 迁移提示 | 对于从旧版本升级的用户,如果检测到 use_pipeline_uuid 已自动迁移,展示提示说明 |
6.2 UI 交互设计概要
┌─ Bot 编辑页面 ─────────────────────────────────────┐
│ │
│ 基本信息 │ 适配器配置 │ ★ 事件处理 │ │
│ │
│ ┌─ 事件处理器列表 ────────────────────────────┐ │
│ │ │ │
│ │ ① message.received → Pipeline: "主流水线" │ │
│ │ [编辑] [删除] │ │
│ │ │ │
│ │ ② group.member_joined → Agent: local-agent │ │
│ │ [编辑] [删除] │ │
│ │ │ │
│ │ ③ * (默认) → Plugin │ │
│ │ [编辑] [删除] │ │
│ │ │ │
│ │ [+ 添加事件处理器] │ │
│ │ │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ [保存] [取消] │
└─────────────────────────────────────────────────────┘
6.3 验收标准
- 用户可以在 WebUI 上为 Bot 添加/编辑/删除事件处理器
- 四种 Handler 类型均有对应的配置表单
- 配置保存后正确写入数据库
event_handlers字段 - 旧版本升级后,自动迁移的配置在 UI 上正确展示
- Pipeline Handler 的行为与旧的
use_pipeline_uuid完全一致
7. Phase 6:文档与示例
目标:更新所有面向开发者的文档和示例。
仓库:langbot-wiki, langbot-plugin-demo
7.1 任务清单
| # | 任务 | 仓库 | 说明 |
|---|---|---|---|
| 6.1 | EBA 架构概览文档 | langbot-wiki | 面向用户的新架构说明 |
| 6.2 | 适配器开发指南更新 | langbot-wiki | 如何开发一个新的适配器(新目录结构、新基类、事件转换等) |
| 6.3 | 插件开发指南更新 | langbot-wiki | 新事件类型、新 API 的使用说明 |
| 6.4 | 插件迁移指南 | langbot-wiki | 现有插件如何迁移到新事件/API(如果需要使用新能力) |
| 6.5 | 事件处理器配置指南 | langbot-wiki | WebUI 上如何配置事件处理器 |
| 6.6 | 示例插件更新 | langbot-plugin-demo | HelloPlugin 增加新事件监听示例、新 API 调用示例 |
| 6.7 | 新示例插件 | langbot-plugin-demo | 新建一个示例展示非消息事件处理(如入群欢迎) |
8. 风险评估与缓解
8.1 技术风险
| 风险 | 影响 | 概率 | 缓解措施 |
|---|---|---|---|
| 适配器迁移中断现有功能 | 高 | 中 | 新旧目录并存,ComponentDiscovery 同时扫描两个目录,逐个适配器迁移验证 |
| 事件模型不兼容导致插件崩溃 | 高 | 低 | 兼容层保证旧事件类型继续工作,新增类不修改旧类 |
| 数据库迁移失败 | 高 | 低 | 迁移脚本做前置校验,use_pipeline_uuid 在过渡期保留不删除 |
| RequestRunner 解耦破坏 Pipeline | 高 | 中 | Agent Handler 调用 Runner 的路径独立于 Pipeline,不修改现有 Pipeline Stage 中的 Runner 调用逻辑 |
| 性能回退(EventBus 额外开销) | 中 | 低 | EventBus 在进程内同步分发,无额外序列化/网络开销 |
| 各平台事件差异大难以统一 | 中 | 中 | 通用事件只抽象最大公约数字段,差异部分保留在 source_platform_object;不支持的事件走 PlatformSpecificEvent |
8.2 兼容性风险
| 风险 | 缓解措施 |
|---|---|
| 现有插件使用旧事件类 | 兼容层自动将新事件转为旧事件分发,两种事件类都能注册 handler |
现有插件调用 reply() / send_message() |
这两个 API 保持不变,只是底层实现可能微调 |
第三方基于 AbstractMessagePlatformAdapter 开发的适配器 |
旧基类保留,新基类继承旧基类,第三方适配器无需立即迁移 |
| 用户自定义 Pipeline 配置 | Pipeline 机制完整保留,PipelineHandler 只是入口变了(从 RuntimeBot 硬编码变为 EventRouter 配置) |
8.3 回滚策略
每个 Phase 独立可回滚:
- Phase 1(SDK 新增类):删除新增文件,回退 SDK 版本号
- Phase 2(适配器目录):恢复
components.yaml的fromDirs指向旧目录,旧 sources/ 未删除 - Phase 3(核心系统):回退数据库迁移,恢复 RuntimeBot 旧的硬编码回调
- Phase 4(插件集成):回退 SDK 版本,插件使用旧版 SDK
- Phase 5(WebUI):前端回退,Bot 编辑页面隐藏事件处理面板
9. 里程碑与时间线建议
| 里程碑 | 阶段 | 预期产出 |
|---|---|---|
| M1 | Phase 1 完成 | SDK 新版本发布,包含新事件/实体/基类定义 |
| M2 | Phase 2 首批适配器(Telegram + Discord) | 两个参考实现,验证目录结构和事件/API 体系 |
| M3 | Phase 3 核心系统 | EventBus + EventRouter + 四种 Handler 可用 |
| M4 | Phase 2 剩余适配器 | 所有活跃适配器迁移完成 |
| M5 | Phase 4 插件集成 | 新 SDK 发布,插件可使用新事件和 API |
| M6 | Phase 5 WebUI | 事件处理器编排面板上线 |
| M7 | Phase 6 文档 | 开发者文档和示例更新完毕 |
建议 M1-M3 作为第一个大版本发布(如 v5.0),M4-M7 在后续小版本迭代中完成。
10. 开发指引
10.1 分支策略
建议在主仓库创建 feature/eba 长期特性分支,各 Phase 在子分支上开发后合入特性分支:
main
└── feature/eba
├── feature/eba-sdk-entities (Phase 1)
├── feature/eba-adapter-telegram (Phase 2)
├── feature/eba-adapter-discord (Phase 2)
├── feature/eba-core-system (Phase 3)
├── feature/eba-plugin-sdk (Phase 4)
└── feature/eba-webui (Phase 5)
10.2 测试策略
| 层次 | 测试内容 | 工具 |
|---|---|---|
| 单元测试 | 事件序列化/反序列化、实体构造、API 调用 mock | pytest |
| 集成测试 | EventBus → EventRouter → Handler 全链路 | pytest + asyncio |
| 适配器测试 | 各适配器的事件转换、消息转换、API 调用 | pytest + mock SDK |
| 端到端测试 | 从模拟平台事件到完整处理流程 | staging 环境 |
| 插件兼容性测试 | 旧插件在新系统下的行为 | langbot-plugin-demo |
10.3 代码审查关注点
- 新增代码是否影响现有行为
- 兼容层是否正确映射所有旧事件/API 场景
- 数据库迁移是否可逆
- 新 API 的错误处理(
NotSupportedError)是否一致 - 事件模型的序列化在 stdio/WebSocket 通信中是否正确