feat: 重构处理器分发和插件加载模块,增强兼容性和错误处理,更新文档

This commit is contained in:
whatevertogo
2026-03-13 04:37:13 +08:00
parent 7d0802fb9e
commit cc5dc9266c
3 changed files with 205 additions and 4 deletions

View File

@@ -1,4 +1,63 @@
"""插件侧 handler 调度器
"""处理器分发模块
定义 HandlerDispatcher 类,负责将能力调用分发到具体的处理器函数。
支持参数注入、流式执行、错误处理和生命周期回调。
核心职责:
- 根据处理器 ID 查找处理器
- 构建处理器参数(支持类型注解注入)
- 执行处理器并处理结果
- 处理异步生成器流式结果
- 统一的错误处理
参数注入优先级:
1. 按类型注解注入(支持 Optional[Type]
2. 按参数名注入(兼容无类型注解)
3. 从 legacy_args 注入(命令参数等)
支持的注入类型:
- MessageEvent: 消息事件
- Context: 运行时上下文
与旧版对比:
旧版 HandlerExecutor:
- 从 star_handlers_registry 获取处理器
- 直接调用 handler(event, **args)
- 无参数注入支持
- 通过 JSON-RPC notification 发送流式结果
- 错误通过 JSON-RPC error 响应
新版 HandlerDispatcher:
- 从 LoadedHandler 映射获取处理器
- 支持类型注解注入 (MessageEvent, Context)
- 支持参数名注入 (event, ctx, context)
- 支持 legacy_args 注入
- 支持 Optional[Type] 类型
- 支持默认值
- 统一的错误处理和 on_error 回调
处理器签名兼容:
# 旧版签名
def handler(event: AstrMessageEvent) -> str:
return "result"
# 新版签名(类型注入)
async def handler(event: MessageEvent, ctx: Context) -> None:
await event.reply("result")
# 新版签名(名字注入)
async def handler(event, ctx) -> None:
await ctx.platform.send(event.session_id, "result")
# 流式处理器
async def streaming_handler(event: MessageEvent):
yield "chunk 1"
yield "chunk 2"
结果处理:
- PlainTextResult: 调用 event.reply()
- str: 调用 event.reply()
- dict with "text": 调用 event.reply(str(item["text"]))
`HandlerDispatcher` 把运行时收到的 `handler.invoke` 请求转成真实 Python 调用。
它的职责只包括参数注入、legacy 返回值兼容和错误回调;不负责 handler 发现或

View File

@@ -1,4 +1,77 @@
"""插件发现、环境准备和组件加载。
"""插件加载模块
定义插件发现、环境管理和加载的核心逻辑。
支持新旧两种 Star 组件的兼容加载。
核心概念:
PluginSpec: 插件规范,描述插件的基本信息
PluginDiscoveryResult: 插件发现结果,包含成功和跳过的插件
PluginEnvironmentManager: 插件虚拟环境管理器
LoadedHandler: 加载后的处理器,包含描述符和可调用对象
LoadedPlugin: 加载后的插件,包含处理器和实例
插件发现流程:
1. 扫描 plugins_dir 下的子目录
2. 检查 plugin.yaml 和 requirements.txt
3. 解析 manifest_data 获取插件信息
4. 验证必要字段name, components, runtime.python
5. 返回 PluginDiscoveryResult
环境管理流程:
1. 检查 .venv 目录是否存在
2. 检查 Python 版本是否匹配
3. 检查指纹是否变化requirements 内容)
4. 必要时重建虚拟环境
5. 使用 uv 安装依赖
插件加载流程:
1. 将插件目录添加到 sys.path
2. 遍历 components 列表
3. 动态导入组件类
4. 判断是否为新版 Star
5. 创建实例(新版直接实例化,旧版传入 legacy_context
6. 扫描处理器方法
7. 构建 HandlerDescriptor
新旧 Star 组件兼容:
新版 Star:
- 继承自 Star 基类
- __astrbot_is_new_star__ 返回 True
- 无参构造函数
- 通过 @handler 装饰器注册处理器
旧版 Star:
- 不继承或 __astrbot_is_new_star__ 返回 False
- 需要 legacy_context 参数
- 通过 @xxx_handler 装饰器注册处理器
- 使用 extras_configs 传递配置
与旧版对比:
旧版 StarManager:
- 通过 plugin.yaml 发现插件
- 动态导入组件类并实例化
- 注册到 star_handlers_registry
- 使用 functools.partial 绑定实例
- 无环境管理
- 无指纹缓存
新版 loader.py:
- PluginSpec 描述插件规范
- PluginEnvironmentManager 管理虚拟环境
- load_plugin() 加载并解析组件
- LoadedHandler 封装处理器和描述符
- 支持新旧 Star 组件兼容
- 支持环境指纹缓存
plugin.yaml 格式:
name: my_plugin
author: author_name
desc: Plugin description
version: 1.0.0
runtime:
python: "3.11"
components:
- class: my_plugin.main:MyComponent
`loader` 是 runtime 与插件代码之间的边界层,负责三件事:

View File

@@ -1,4 +1,73 @@
"""运行时协议对等端。
"""协议对等端模块
定义 Peer 类,封装双向传输通道上的消息收发、初始化握手、能力调用、
流式事件转发与取消处理。这里的 peer 指"通信对端/本端"这一网络协议概念,
而不是业务上的用户、群聊或会话对象。
核心职责:
- 消息序列化/反序列化
- 初始化握手协议
- 能力调用(同步/流式)
- 取消处理
- 连接生命周期管理
消息处理:
入站:
ResultMessage -> 唤醒等待的 Future
EventMessage -> 投递到流式队列
InitializeMessage -> 调用 initialize_handler
InvokeMessage -> 创建任务调用 invoke_handler
CancelMessage -> 取消对应的任务
出站:
initialize() -> InitializeMessage
invoke() -> InvokeMessage(stream=False)
invoke_stream() -> InvokeMessage(stream=True)
cancel() -> CancelMessage
与旧版对比:
旧版 JSON-RPC:
- 分离的 JSONRPCClient 和 JSONRPCServer
- 通过 method 字段区分操作类型
- 使用 JSONRPCRequest/Response 消息类型
- 流式通过独立的 notification 实现
- 无统一的取消机制
新版 Peer:
- 统一的 Peer 抽象,既是客户端也是服务端
- 通过 type 字段区分消息类型
- 使用 InitializeMessage/InvokeMessage/EventMessage 等
- 流式通过 EventMessage(phase=delta) 实现
- 统一的 CancelMessage 取消机制
使用示例:
# 作为客户端发起调用
peer = Peer(transport=transport, peer_info=PeerInfo(...))
await peer.start()
output = await peer.initialize(handlers)
result = await peer.invoke("llm.chat", {"prompt": "hello"})
# 作为服务端处理调用
peer.set_invoke_handler(my_handler)
await peer.start()
消息处理流程:
入站消息:
ResultMessage -> 唤醒等待的 Future
EventMessage -> 投递到流式队列
InitializeMessage -> 调用 _initialize_handler
InvokeMessage -> 创建任务调用 _invoke_handler
CancelMessage -> 取消对应的任务
出站消息:
initialize() -> InitializeMessage
invoke() -> InvokeMessage(stream=False)
invoke_stream() -> InvokeMessage(stream=True)
cancel() -> CancelMessage
取消机制:
- CancelToken 用于检查取消状态
- 入站任务在收到 CancelMessage 时被取消
- 早到取消:在任务执行前检查 cancel_token避免竞态条件
`Peer` 把 `Transport` 和 v4 协议消息模型接起来,负责:
@@ -344,7 +413,7 @@ class Peer:
if isinstance(exc, AstrBotError):
error = exc
else:
error = AstrBotError.protocol_error(f"协议消息处理失败: {exc}")
error = AstrBotError.protocol_error(f"无法解析协议消息: {exc}")
await self._fail_connection(error)
raise error from exc