Skip to content

插件系统概览

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)

包类型

范式导入来源使用场景运行方式
Pluginplugin.sdk.plugin独立功能(搜索、提醒等)独立进程
Adapterplugin.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 通过 messageseventslifecycleconversationsmemory 读取宿主状态;只有前三者支持 watch()conversationsmemory 是只读快照。可重放 watcher 链使用 get() → 结构化 filter(field=value, ...)sort(by=...)limit()watch(),且只订阅 adddelchange 增量。它没有 publish/emit 接口。最近记忆记录使用 self.bus.memory.get(...),语义检索使用 await self.ctx.query_memory(...)
  • 动态入口 — 在运行时注册/注销入口点
  • Hosted UI — 在插件管理器中构建 TSX 交互面板和 Markdown 教程页
  • 静态 UI — 从插件目录提供旧版 Web UI 服务
  • 生命周期钩子startupshutdownreloadfreezeunfreezeconfig_change
  • 定时任务 — 使用 @timer_interval 实现周期性执行
  • 消息处理器 — 响应来自宿主系统的消息

插件目录结构

plugin/plugins/
└── my_plugin/
    ├── __init__.py      # 插件代码(入口点)
    ├── plugin.toml      # 插件配置
    ├── config.json      # 可选:自定义配置
    ├── data/            # 可选:运行时数据目录
    ├── ui/              # 可选:Hosted TSX 面板
    ├── docs/            # 可选:Markdown 或 TSX 教程页
    ├── i18n/            # 可选:插件本地翻译
    └── static/          # 可选:旧版 Web UI 文件

快速链接

基于 MIT 许可发布。