mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 01:40:15 +08:00
325 lines
13 KiB
Markdown
325 lines
13 KiB
Markdown
# AstrBot SDK v4 当前架构文档
|
||
|
||
本文描述仓库 **当前实现**,是 `src-new/astrbot_sdk` / `src-new/astrbot` / `tests_v4` 的唯一主文档。
|
||
`refactor.md` 仅保留历史设计意图和演进说明,不再描述现状。
|
||
|
||
## 1. 目标与边界
|
||
|
||
AstrBot SDK v4 当前同时承担两件事:
|
||
|
||
1. 提供一套原生 v4 插件模型:`Star`、`Context`、`MessageEvent`、capability clients、v4 protocol。
|
||
2. 维持旧插件兼容:`astrbot_sdk.api.*`、`astrbot_sdk.compat`、`astrbot.api.*` 以及选定的 `astrbot.core.*` facade 继续可用。
|
||
|
||
因此,compat 现在不是可忽略的旁路,而是一个受控的长期子系统。当前架构目标是:
|
||
|
||
- v4 原生 API 仍保持清晰、窄导出、协议优先。
|
||
- legacy 兼容逻辑尽量收口到私有边界,而不是扩散到 runtime 主干。
|
||
- 兼容导入路径继续可用,但不把旧应用整棵树重新复制进来。
|
||
- 文档明确区分“等价兼容”“降级兼容”“仅导入兼容”。
|
||
|
||
## 2. 当前分层模型
|
||
|
||
```text
|
||
插件作者
|
||
├─ 原生 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_runtime.py
|
||
├─ legacy 行为承接: _legacy_api.py
|
||
└─ 会话等待器: _session_waiter.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` 子模块。
|
||
- runtime 主干通过 `_legacy_runtime.py` 执行 compat filters / hooks / 生命周期桥接,不直接展开更多 legacy 细节。
|
||
|
||
## 3. 目录结构
|
||
|
||
```text
|
||
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_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 启动
|
||
|
||
1. `runtime.loader.discover_plugins()` 扫描插件目录,兼容 `plugin.yaml` 和 legacy `main.py` 插件。
|
||
2. `PluginEnvironmentManager.plan()` 基于 `runtime.python` 和 `requirements.txt` 规划共享环境分组。
|
||
3. `GroupEnvironmentManager` 负责准备分组环境;worker 仍然保持“一插件一进程”,只是可共享同一个 Python 环境。
|
||
4. `load_plugin()` 加载组件,v4 `Star` 直接实例化,legacy 组件复用同一 `LegacyContext`。
|
||
5. legacy component 注册通过 `_legacy_runtime` 把 compat hooks / LLM tools / context functions 绑定到共享 `LegacyContext`。
|
||
6. `PluginWorkerRuntime` 创建 `Peer`、`HandlerDispatcher`、`CapabilityDispatcher`,初始化后向 supervisor 发送 `initialize`。
|
||
7. worker 启动/停止时的 compat lifecycle hooks 统一由 `_legacy_runtime` 执行。
|
||
|
||
### 4.2 handler.invoke 调用链
|
||
|
||
1. 上游通过 capability `"handler.invoke"` 调 worker。
|
||
2. `HandlerDispatcher` 构造本地 `Context` 和 `MessageEvent`,先尝试把消息路由给 `_session_waiter`。
|
||
3. 若命中 legacy compat handler,则由 `_legacy_runtime` 应用 custom filters、结果装饰、发送后 hook、错误 hook。
|
||
4. handler 返回值支持:
|
||
- `MessageEventResult`
|
||
- `MessageChain`
|
||
- `PlainTextResult`
|
||
- `str`
|
||
- `{"text": ...}`
|
||
5. 发送链路优先使用 `ctx.platform.send_chain()` 或 `event.reply()`。
|
||
|
||
### 4.3 capability 调用链
|
||
|
||
1. 插件代码通过 `ctx.llm.*`、`ctx.db.*`、`ctx.memory.*`、`ctx.platform.*` 访问上游能力。
|
||
2. clients 通过 `CapabilityProxy` 转成 `Peer.invoke()` / `Peer.invoke_stream()`。
|
||
3. supervisor 侧 `CapabilityRouter` 处理内建能力;worker 也可以通过 `@provide_capability()` 暴露插件自定义 capability。
|
||
4. 插件自定义 capability 由 `CapabilityDispatcher` 在 worker 内分发执行。
|
||
|
||
### 4.4 session_waiter
|
||
|
||
`_session_waiter.py` 提供 legacy `@session_waiter` 的最小可运行兼容实现。
|
||
它不是单纯导入桩,而是按 session 维度把后续消息重新路由给等待中的 compat 回调。
|
||
|
||
## 5. 协议契约
|
||
|
||
### 5.1 五条硬规则
|
||
|
||
1. 所有协议消息统一使用 `id` 关联请求与响应。
|
||
2. `EventMessage` 只用于 `stream=true` 的调用。
|
||
3. 插件 handler 回调统一走 capability `"handler.invoke"`。
|
||
4. `CancelMessage` 表示“请求停止”,调用方仍需等待终止态。
|
||
5. `initialize` 失败后连接进入不可用状态。
|
||
|
||
### 5.2 版本语义
|
||
|
||
当前实现里必须区分两个概念:
|
||
|
||
- `protocol_version`:**线协议版本**。当前 wire contract 使用 `"1.0"`。
|
||
- `PeerInfo.version`:**软件/实现版本标识**。当前 runtime 常用 `"v4"` 作为软件版本字符串。
|
||
|
||
二者不是同一个字段,也不应混写成同一含义。
|
||
|
||
### 5.3 主要消息
|
||
|
||
- `InitializeMessage`
|
||
- `InvokeMessage`
|
||
- `ResultMessage`
|
||
- `EventMessage`
|
||
- `CancelMessage`
|
||
|
||
`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. 兼容层现状
|
||
|
||
### 7.1 等价或接近等价的兼容面
|
||
|
||
以下兼容面当前是实际可运行的,不只是 import stub:
|
||
|
||
- `astrbot_sdk.api.*` 常用导入路径
|
||
- `astrbot_sdk.compat`
|
||
- `astrbot.api.*` 以及选定的 `astrbot.core.*` facade
|
||
- `LegacyContext` / `LegacyStar` / `CommandComponent`
|
||
- `filter.command` / `regex` / `permission`
|
||
- `event_message_type` / `platform_adapter_type`
|
||
- 常用 compat hooks:
|
||
- `after_message_sent`
|
||
- `on_astrbot_loaded`
|
||
- `on_platform_loaded`
|
||
- `on_decorating_result`
|
||
- `on_llm_request`
|
||
- `on_llm_response`
|
||
- `on_waiting_llm_request`
|
||
- `on_using_llm_tool`
|
||
- `on_llm_tool_respond`
|
||
- `on_plugin_error`
|
||
- `on_plugin_loaded`
|
||
- `on_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()`:显式 `NotImplementedError`
|
||
- `astrbot.core.provider.provider` 中的 provider 基类与 embeddings/rerank 方法:导入可用,但方法是 stub
|
||
- 没有可映射执行链路的旧 `filter.*` helper:显式 `NotImplementedError`
|
||
|
||
兼容原则是“尽量保留可运行的旧插件路径”,不是“重新实现整个旧 AstrBot 应用”。
|
||
|
||
## 8. 对插件作者的导入建议
|
||
|
||
### 推荐的新代码
|
||
|
||
```python
|
||
from astrbot_sdk import Star, Context, MessageEvent
|
||
from astrbot_sdk.decorators import on_command, on_message, provide_capability
|
||
```
|
||
|
||
### 仍受支持的旧代码
|
||
|
||
```python
|
||
from astrbot_sdk.api.event import AstrMessageEvent
|
||
from astrbot_sdk.api.star.context import Context
|
||
from astrbot_sdk.api.event.filter import filter
|
||
```
|
||
|
||
### 旧包名 facade
|
||
|
||
```python
|
||
from astrbot.api.star import Star
|
||
from astrbot.core.utils.session_waiter import session_waiter
|
||
```
|
||
|
||
只有在需要兼容现有旧插件时才应继续使用这些路径;新插件应直接使用 v4 顶层入口。
|
||
|
||
## 9. 本地开发与测试
|
||
|
||
当前仓库已经提供一条受控的本地开发路径:
|
||
|
||
- CLI:
|
||
- `astr dev --local` / `astrbot-sdk dev --local`
|
||
- `astrbot-sdk init`
|
||
- `astrbot-sdk validate`
|
||
- `astrbot-sdk build`
|
||
- 稳定测试入口:`astrbot_sdk.testing`
|
||
|
||
`astrbot_sdk.testing` 当前公开的稳定面包括:
|
||
|
||
- `PluginHarness`
|
||
- `LocalRuntimeConfig`
|
||
- `MockContext`
|
||
- `MockMessageEvent`
|
||
- `MockLLMClient`
|
||
- `MockPlatformClient`
|
||
- `MockPeer`
|
||
- `MockCapabilityRouter`
|
||
- `InMemoryDB`
|
||
- `InMemoryMemory`
|
||
- `StdoutPlatformSink`
|
||
- `RecordedSend`
|
||
|
||
设计约束:
|
||
|
||
- 本地 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. 当前建议的后续演进方向
|
||
|
||
1. 继续把 runtime 对 compat 的认知收口到 `_legacy_runtime.py`。
|
||
2. 继续拆薄 `_legacy_api.py`,让 `LegacyContext` 更偏向 facade 和 orchestration。
|
||
3. 保持 `src-new/astrbot` 为受控 facade,不要把旧应用整棵树重新复制进来。
|
||
4. 用契约测试保护 capability 注册表、compat hook 执行和 facade 导入矩阵,避免文档再次漂移。
|