插件系统概览
N.E.K.O. 插件系统是一个基于 Python 的插件框架,建立在进程隔离和异步 IPC 之上。平台只有两种包类型:产品功能使用 Plugin(插件),外部协议桥接使用 Adapter(适配器)。原 Extension(扩展) 包类型已经移除;PluginRouter 仍可在普通 Plugin 内部使用。
架构
┌────────────────────────────────────────────────────┐
│ Main Process (Host) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Plugin Host (core/) │ │
│ │ - Plugin lifecycle management │ │
│ │ - Bus system (memory, events, messages) │ │
│ │ - ZMQ IPC transport │ │
│ └──────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Plugin Server (server/) │ │
│ │ - HTTP API endpoints (FastAPI) │ │
│ │ - Plugin registry │ │
│ │ - Message queue │ │
│ └──────────────────────────────────────────────┘ │
└────────────────────┬───────────────────────────────┘
│ ZMQ IPC
┌──────────────┼──────────────┐
▼ ▼ ▼
Plugin A Plugin B Adapter D
(process) (process) (process)包类型
| 范式 | 导入来源 | 使用场景 | 运行方式 |
|---|---|---|---|
| Plugin | plugin.sdk.plugin | 独立功能(搜索、提醒等) | 独立进程 |
| Adapter | plugin.sdk.adapter | 将外部协议(MCP、NoneBot)桥接到内部插件调用 | 独立进程,带网关管线 |
何时使用哪种范式?
- "我想添加一个新的独立功能" → 使用 Plugin
- “我想在现有功能周围增加命令” → 使用普通 Plugin;若你维护原宿主且代码很大,可在宿主内使用
PluginRouter - "我想接受 MCP/NoneBot/外部协议调用并将其路由到插件" → 使用 Adapter
从 Plugin 开始。迁移原 Extension 时,把 Router 合并进所属 Plugin,或改造成独立 Plugin。
主要特性
- 进程隔离 — Plugin 与 Adapter 均在独立进程中运行
- 异步支持 — 同时支持同步和异步入口点
- Result 类型 — 使用
Ok/Err进行类型安全的错误处理(正常流程中无异常) - 钩子系统 —
@before_entry、@after_entry、@around_entry、@replace_entry实现 AOP - 跨插件调用 —
self.plugins.call_entry("other_plugin:entry_id")实现插件间通信 - 系统信息 —
self.system_info查询宿主系统元数据 - 插件存储 —
PluginStore提供持久化键值存储 - 总线系统 —
self.bus通过messages、events、lifecycle、conversations、memory读取宿主状态;只有前三者支持watch(),conversations与memory是只读快照。可重放 watcher 链使用get()→ 结构化filter(field=value, ...)→sort(by=...)→limit()→watch(),且只订阅add、del、change增量。它没有 publish/emit 接口。最近记忆记录使用self.bus.memory.get(...),语义检索使用await self.ctx.query_memory(...)。 - 动态入口 — 在运行时注册/注销入口点
- Hosted UI — 在插件管理器中构建 TSX 交互面板和 Markdown 教程页
- 静态 UI — 从插件目录提供旧版 Web UI 服务
- 生命周期钩子 —
startup、shutdown、reload、freeze、unfreeze、config_change - 定时任务 — 使用
@timer_interval实现周期性执行 - 消息处理器 — 响应来自宿主系统的消息
插件目录结构
plugin/plugins/
└── my_plugin/
├── __init__.py # 插件代码(入口点)
├── plugin.toml # 插件配置
├── config.json # 可选:自定义配置
├── data/ # 可选:运行时数据目录
├── ui/ # 可选:Hosted TSX 面板
├── docs/ # 可选:Markdown 或 TSX 教程页
├── i18n/ # 可选:插件本地翻译
└── static/ # 可选:旧版 Web UI 文件