15 KiB
AstrBot SDK v4 当前架构文档
本文描述仓库 当前实现,是 src-new/astrbot_sdk / src-new/astrbot / tests_v4 的唯一主文档。
refactor.md 仅保留历史设计意图和演进说明,不再描述现状。
1. 目标与边界
AstrBot SDK v4 当前同时承担两件事:
- 提供一套原生 v4 插件模型:
Star、Context、MessageEvent、capability clients、v4 protocol。 - 维持旧插件兼容:
astrbot_sdk.api.*、astrbot_sdk.compat、astrbot.api.*以及选定的astrbot.core.*facade 继续可用。
因此,compat 现在不是可忽略的旁路,而是一个受控的过渡子系统。当前架构目标是:
- v4 原生 API 仍保持清晰、窄导出、协议优先。
- legacy 兼容逻辑尽量收口到私有边界,而不是扩散到 runtime 主干。
- 兼容导入路径继续可用,但不把旧应用整棵树重新复制进来。
- 文档明确区分“等价兼容”“降级兼容”“仅导入兼容”。
2. 当前分层模型
插件作者
├─ 原生 v4: astrbot_sdk.{Star, Context, MessageEvent, decorators}
└─ legacy compat: astrbot_sdk.api.* / astrbot_sdk.compat / astrbot.api.*
高层 API
├─ 原生 clients: llm / memory / db / platform
└─ legacy facade: LegacyContext / LegacyStar / message components / filter namespace
执行边界
├─ runtime 主干: loader / bootstrap / handler_dispatcher / capability_router / peer
├─ compat 私有实现: _legacy_api.py / _legacy_runtime.py / _legacy_loader.py
└─ 运行时交互辅助: _session_waiter.py / _shared_preferences.py
协议与传输
├─ protocol.messages / protocol.descriptors
├─ Peer
└─ StdioTransport / WebSocket transports
当前最重要的架构判断
astrbot_sdk.__init__只导出推荐的 v4 入口。astrbot_sdk.runtime.__init__只导出高级运行时原语,不把 loader/bootstrap 等编排细节提升为根级稳定 API。astrbot_sdk.protocol.__init__只导出 v4 原生协议模型;legacy JSON-RPC 适配器留在protocol.legacy_adapter子模块。- compat 私有实现保留在既有顶层 private 模块中,避免再维护一套并行目录。
astrbot_sdk.api.*与astrbot.*仅作为迁移期 facade 保留,不再扩张为长期稳定主入口。- runtime 主干通过
_legacy_runtime.py/_legacy_loader.py等私有边界执行 compat filters / hooks / 生命周期桥接,不直接展开更多 legacy 细节。
3. 目录结构
src-new/
├── astrbot_sdk/
│ ├── __init__.py # v4 推荐顶层入口
│ ├── context.py # Context / CancelToken
│ ├── decorators.py # on_command / on_message / provide_capability ...
│ ├── events.py # MessageEvent / PlainTextResult
│ ├── errors.py # AstrBotError / ErrorCodes
│ ├── star.py # Star 基类与 handler 收集
│ ├── cli.py # astr / astrbot-sdk CLI 入口
│ ├── testing.py # 本地开发与测试 harness
│ ├── compat.py # 旧顶层兼容重导出
│ ├── _legacy_api.py # LegacyContext / LegacyStar / CommandComponent
│ ├── _legacy_llm.py # legacy LLM/tool 兼容辅助
│ ├── _legacy_loader.py # legacy 插件发现与 main.py 包装
│ ├── _legacy_runtime.py # compat 执行边界
│ ├── _session_waiter.py # legacy session_waiter 兼容执行
│ ├── _shared_preferences.py # 共享偏好兼容辅助
│ │
│ ├── clients/
│ │ ├── _proxy.py # CapabilityProxy
│ │ ├── llm.py
│ │ ├── memory.py
│ │ ├── db.py # 包含 get_many / set_many / watch
│ │ └── platform.py
│ │
│ ├── protocol/
│ │ ├── __init__.py # 仅导出原生 v4 协议模型
│ │ ├── descriptors.py # handlers / capabilities / builtin schema registry
│ │ ├── messages.py # initialize / invoke / result / event / cancel
│ │ └── legacy_adapter.py # v3 JSON-RPC ↔ v4 适配
│ │
│ ├── runtime/
│ │ ├── __init__.py # Peer / Transport / CapabilityRouter / HandlerDispatcher
│ │ ├── peer.py
│ │ ├── transport.py
│ │ ├── capability_router.py
│ │ ├── handler_dispatcher.py
│ │ ├── loader.py
│ │ ├── environment_groups.py # 共享环境规划与分组环境管理
│ │ └── bootstrap.py
│ │
│ └── api/ # astrbot_sdk.api.* 兼容层
│ ├── basic/
│ ├── components/
│ ├── event/
│ ├── message/
│ ├── platform/
│ ├── provider/
│ └── star/
│
└── astrbot/ # 旧包名 facade,受控兼容面
├── api/
└── core/
4. 核心执行链
4.1 插件发现与 worker 启动
runtime.loader.discover_plugins()扫描插件目录,兼容plugin.yaml和 legacymain.py插件。PluginEnvironmentManager.plan()基于runtime.python和requirements.txt规划共享环境分组。GroupEnvironmentManager负责准备分组环境;worker 仍然保持“一插件一进程”,只是可共享同一个 Python 环境。load_plugin()加载组件,v4Star直接实例化,legacy 组件复用同一LegacyContext。- legacy component 注册通过
_legacy_runtime.py把 compat hooks / LLM tools / context functions 绑定到共享LegacyContext。 PluginWorkerRuntime创建Peer、HandlerDispatcher、CapabilityDispatcher,初始化后向 supervisor 发送initialize。- worker 启动/停止时的 compat lifecycle hooks 统一由
_legacy_runtime.py执行。
4.2 handler.invoke 调用链
- 上游通过 capability
"handler.invoke"调 worker。 HandlerDispatcher构造本地Context和MessageEvent,先尝试把消息路由给_session_waiter.py。- 若命中 legacy compat handler,则由
_legacy_runtime.py应用 custom filters、结果装饰、发送后 hook、错误 hook。 - handler 返回值支持:
MessageEventResultMessageChainPlainTextResultstr{"text": ...}
- 发送链路优先使用
ctx.platform.send_chain()或event.reply()。
4.3 capability 调用链
- 插件代码通过
ctx.llm.*、ctx.db.*、ctx.memory.*、ctx.platform.*访问上游能力。 - clients 通过
CapabilityProxy转成Peer.invoke()/Peer.invoke_stream()。 - supervisor 侧
CapabilityRouter处理内建能力;worker 也可以通过@provide_capability()暴露插件自定义 capability。 - 插件自定义 capability 由
CapabilityDispatcher在 worker 内分发执行。
4.4 session_waiter
_session_waiter.py 提供 legacy @session_waiter 的最小可运行兼容实现。
它不是单纯导入桩,而是按 session 维度把后续消息重新路由给等待中的 compat 回调。
5. 协议契约
5.1 五条硬规则
- 所有协议消息统一使用
id关联请求与响应。 EventMessage只用于stream=true的调用。- 插件 handler 回调统一走 capability
"handler.invoke"。 CancelMessage表示“请求停止”,调用方仍需等待终止态。initialize失败后连接进入不可用状态。
5.2 版本语义
当前实现里必须区分两个概念:
protocol_version:线协议版本。当前 wire contract 使用"1.0"。PeerInfo.version:软件/实现版本标识。当前 runtime 常用"v4"作为软件版本字符串。
二者不是同一个字段,也不应混写成同一含义。
5.3 主要消息
InitializeMessageInvokeMessageResultMessageEventMessageCancelMessage
InitializeMessage 由 Peer.initialize() 发起,成功响应是
ResultMessage(kind="initialize_result", success=True, output=InitializeOutput(...))。
6. 当前内建 capabilities
当前协议注册表和 CapabilityRouter 内建 capability 一致,共 18 个:
| 命名空间 | Capability | 流式 |
|---|---|---|
llm |
llm.chat |
否 |
llm |
llm.chat_raw |
否 |
llm |
llm.stream_chat |
是 |
memory |
memory.search |
否 |
memory |
memory.save |
否 |
memory |
memory.get |
否 |
memory |
memory.delete |
否 |
db |
db.get |
否 |
db |
db.set |
否 |
db |
db.delete |
否 |
db |
db.list |
否 |
db |
db.get_many |
否 |
db |
db.set_many |
否 |
db |
db.watch |
是 |
platform |
platform.send |
否 |
platform |
platform.send_image |
否 |
platform |
platform.send_chain |
否 |
platform |
platform.get_members |
否 |
说明:
SessionRef是结构化发送目标 schema,不是 capability。internal.*与handler.*命名空间保留给框架内部使用,不属于公开内建 capability 列表。
7. 兼容层现状(已弃用)
⚠️ 重要:兼容层已弃用,将在下个大版本移除
- 旧插件请使用 AstrBot 主程序 运行(主程序有完整的
StarManager支持)- 新插件请迁移到
astrbot_sdk顶层入口- 导入兼容层会触发
DeprecationWarning
7.0 迁移指南
旧插件开发者有两个选择:
- 继续使用旧 API:由 AstrBot 主程序运行,无需修改代码
- 迁移到 v4 SDK:
# 旧版(由主程序运行)
from astrbot.api.event import filter, AstrMessageEvent
from astrbot.api.star import Context, Star
class MyPlugin(Star):
def __init__(self, context: Context):
self.context = context
@filter.command("hello")
async def hello(self, event: AstrMessageEvent):
yield event.plain_result("Hello!")
# 新版(v4 SDK)
from astrbot_sdk import Star, on_command, MessageEvent
class MyPlugin(Star):
@on_command("hello")
async def hello(self, event: MessageEvent):
return event.reply("Hello!")
7.1 等价或接近等价的兼容面
以下兼容面当前是实际可运行的,不只是 import stub:
astrbot_sdk.api.*常用导入路径astrbot_sdk.compatastrbot.api.*以及选定的astrbot.core.*facadeLegacyContext/LegacyStar/CommandComponentfilter.command/regex/permissionevent_message_type/platform_adapter_type- 常用 compat hooks:
after_message_senton_astrbot_loadedon_platform_loadedon_decorating_resulton_llm_requeston_llm_responseon_waiting_llm_requeston_using_llm_toolon_llm_tool_respondon_plugin_erroron_plugin_loadedon_plugin_unloaded
- message components 兼容导出、别名构造和常用工厂
session_waiter- 旧插件共享单一
LegacyContext
7.2 降级兼容
这些能力可以运行,但不保证与历史实现完全等价:
command_group:当前会展平成普通命令名,不复刻旧的树状命令帮助与多层执行链。- legacy JSON-RPC handshake 转 v4 handler 描述时,只能近似恢复旧触发信息,原始 payload 会保留在 metadata 里。
astrbot.core.*的深层 facade 只覆盖受支持的导入路径,不等于整个旧应用树。tool_loop_agent()当前是 compat local tool loop,并非完整复刻旧应用内部 agent 体系。
7.3 仅导入兼容或明确不支持
以下路径或能力要么只有导入兼容,要么明确不实现旧语义:
astrbot.api.agent():显式NotImplementedErrorastrbot.core.provider.provider中的 provider 基类与 embeddings/rerank 方法:导入可用,但方法是 stub- 没有可映射执行链路的旧
filter.*helper:显式NotImplementedError
兼容原则是“尽量保留可运行的旧插件路径”,不是“重新实现整个旧 AstrBot 应用”。
8. 对插件作者的导入建议
推荐的新代码(v4)
from astrbot_sdk import Star, Context, MessageEvent
from astrbot_sdk.decorators import on_command, on_message, provide_capability
仍受支持的旧代码(已弃用)
⚠️ 以下导入路径已弃用,将在下个大版本移除。旧插件请使用 AstrBot 主程序运行。
# 已弃用 - 请迁移到 v4 或使用主程序
from astrbot_sdk.api.event import AstrMessageEvent
from astrbot_sdk.api.star.context import Context
from astrbot_sdk.api.event.filter import filter
旧包名 facade(已弃用)
⚠️ 以下导入路径已弃用,将在下个大版本移除。
# 已弃用 - 请迁移到 v4 或使用主程序
from astrbot.api.star import Star
from astrbot.core.utils.session_waiter import session_waiter
9. 本地开发与测试
当前仓库已经提供一条受控的本地开发路径:
- CLI:
astr dev --local/astrbot-sdk dev --localastrbot-sdk initastrbot-sdk validateastrbot-sdk build
- 稳定测试入口:
astrbot_sdk.testing
astrbot_sdk.testing 当前公开的稳定面包括:
PluginHarnessLocalRuntimeConfigMockContextMockMessageEventMockLLMClientMockPlatformClientMockPeerMockCapabilityRouterInMemoryDBInMemoryMemoryStdoutPlatformSinkRecordedSend
设计约束:
- 本地 harness 复用真实的
load_plugin()、HandlerDispatcher、CapabilityDispatcher、_legacy_runtime.py与_session_waiter.py dev --local使用进程内 mock core,而不是重新发明一套并行 runtime- 同一次
interactive会话会复用同一个 dispatcher / waiter manager / in-memory db / in-memory memory astrbot_sdk.testing是插件测试依赖的公开 API,minor 版本内保持兼容稳定
10. 测试与维护约定
- 当前主测试目录是
tests_v4/,覆盖 protocol、runtime、clients、compat facade、legacy plugin integration、top-level imports 与 integration flows。 - 文档维护规则:
- capability 集合变化时,同时更新本文档与对应测试。
- compat 支持级别变化时,同时更新本文档、
CLAUDE.md/AGENTS.md备注以及相关契约测试。 refactor.md不再承载现状;出现冲突时,一律以本文档和代码/测试为准。
11. 后续演进方向
- 当前版本:兼容层已标记为 deprecated,触发
DeprecationWarning - 下个大版本:完全移除兼容层,SDK 只支持 v4 新插件
- 旧插件将由 AstrBot 主程序独立支持,不依赖 SDK 兼容层