Skip to content

20. 先回头看一眼:你其实已经走到插件系统门口了

导读 本章是一次回溯与收拢。前面十九章里,插件系统的各类组件和运行链路已经逐一铺开。这一章不引入新概念,而是把走过的路重新梳理一遍,并把下一阶段要进入的插件系统公共入口层——plugin_system.baseplugin_system.apiplugin_system.types——轻轻掀开一角,为后续打好衔接基础。

这一段路其实已经走了很长。

如果你是跟着这份指南一路读下来的,那你现在看到的,已经不再是“怎么把一个插件勉强写出来”,而是插件系统里一整套比较完整的分层:

  • 插件是什么
  • 组件是什么
  • 配置怎么接
  • Tool、Agent、Action、EventHandler、Chatter、Router、Adapter 分别负责什么
  • 消息又是怎么在线路里流动的

很多时候,学习插件系统最难的地方不在某个单点 API,反而在于:

学着学着,脑子里东西越来越多,但一时说不清这些东西到底怎么拼在一起。

所以这一章不打算继续加新概念。

这一章更像一次回头看。

本章先把走过的路重新梳理一遍,再把下一阶段要进入的公共入口层轻轻掀开一角:

  • plugin_system.base
  • plugin_system.api
  • plugin_system.types

后面会专门讲它们。

这一章只做一件事:

让你知道,前面学到的那些分散概念,已经开始自然汇成“插件作者真正会使用的一套入口”。

20.1 最开始的时候,你学的是“插件能不能站起来”

如果回忆最前面的几章,你最先接触的不是复杂组件,也不是统一消息模型。

你最先学的其实是更基础的东西:

  • 一个插件最少需要什么
  • manifest.json 在做什么
  • 插件类怎么注册
  • 项目结构可以先多简单

这一阶段的目标很朴素:

先让插件被系统识别、被系统加载。

这一步看起来好像很初级,但它其实很重要。

因为如果这一步没有站稳,后面所有“更高级”的内容都会变成空中楼阁。

所以现在回头看,最开始那几章真正帮你建立的,不是技巧,而是插件作者的第一个视角:

“我写的不是随便一个 Python 文件,而是插件系统能识别的一种组件化扩展。”

20.2 往前走一点,你学的是“插件内部可以长出哪些能力”

再往后,视角就从“插件能不能加载”变成了:

插件加载之后,到底能以哪些方式参与系统。

这时候你接触到的是一组组件边界:

  • Command
  • Service
  • Tool
  • Agent
  • Action
  • EventHandler
  • Chatter
  • Router
  • Adapter

如果只看名字,这些东西一开始很容易像一串并列名词。

但你现在应该已经能慢慢分出来了:

  • 有些组件更像“能力点”
  • 有些组件更像“流程控制点”
  • 有些组件更像“系统入口”
  • 有些组件更像“平台桥接层”

这就是前面那一大段内容真正的价值。

它不是为了让你背组件列表,而是为了让你逐渐建立边界感。

而插件系统一旦有了边界感,很多问题就会突然变简单。

比如你会开始更自然地判断:

  • “这个需求更像 Tool,不像 Agent。”
  • “这个需求应该放 Router,不该放 Command。”
  • “这个问题是 Adapter 层的,不是 Chatter 层的。”

这其实就是一种很实在的进步。

20.3 再往后,你学到的是“组件不是孤立的,它们活在一条链路里”

只理解组件还不够。

因为真实系统不是“很多组件摆在架子上”,而是“很多组件在链路里相互衔接”。

前面几章里,你已经开始接触到这种链路意识了。

比如:

  • Prompt 和 LLM 不是凭空工作的,它们会和 Tool、Agent、Chatter 连在一起
  • Action 不是自己漂浮着执行,它通常接着发送链路或平台动作
  • Adapter 不是独立存在,它接着统一消息模型和平台协议
  • MessageEnvelope 不是某个单独模块的私有格式,而是跨层传递的线路格式

这意味着你现在对插件系统的理解,其实已经从“单个组件说明书”慢慢走向了:

一套分层协作的运行系统。

这一步很关键。

因为只有当你意识到它是系统,不是零件堆,你后面再学公共 API 层时,才会知道那些 API 为什么值得存在。

20.4 这一阶段最容易出现的感觉:会写了很多东西,但入口开始变散

走到这里,很多插件作者会开始出现一种很典型的感觉:

  • 好像已经知道很多概念了
  • 也知道不少组件该怎么写
  • 但真到自己开始写插件时,导入路径、公共类型、系统接口会慢慢变得有点散

比如你会开始遇到这些问题:

  • 我到底应该从哪里 import 这些公共基类?
  • 发送消息、读配置、查聊天流、调 LLM,到底该从哪一层拿?
  • 常用的消息类型、LLM 类型、组件类型,是不是每次都要下钻到 corekernel 里找?

如果你开始有这种感觉,不是因为你退步了。

恰恰相反,这通常说明你已经从“理解概念”开始走向“真的准备写插件了”。

而这,也正是后面要进入公共入口层的原因。

20.5 为什么接下来要开始讲 plugin_system 的公共入口

从代码组织上看,Neo-MoFox 当然有更底层的实现层:

  • src/core/...
  • src/kernel/...

这些层当然很重要。

但如果你是插件作者,其实并不希望自己每次写插件时都不停地下钻这些底层路径。

更理想的状态通常是:

插件作者有一层相对稳定、相对友好的公共入口,可以拿到最常用的基类、API 和类型。

而当前项目里,这层入口已经逐渐被整理成了:

  • plugin_system.base
  • plugin_system.api
  • plugin_system.types

再往上一层,还有一个聚合入口:

  • plugin_system

也就是说,前面你学到的那些东西,并不是永远散落在整个代码库里。

它们正在被收束成插件作者更好用的一层外观。

这就是后面几章要进入的重点。

20.6 baseapitypes,现在先只记角色,不记细节

这一章不打算提前展开用法。

但你可以先把这三层当成三个不同的入口角色。

plugin_system.base

这一层你其实已经很熟了。

因为前面很多章节里,你一直在用的公共基类,本质上就在这里:

  • BasePlugin
  • BaseTool
  • BaseAgent
  • BaseAction
  • BaseChatter
  • BaseRouter
  • BaseAdapter

也就是说,base 更像是:

插件作者用来定义组件骨架的入口。

plugin_system.api

这一层更像是“运行中的系统能力入口”。

比如从名字上你已经能看出来它收拢的是哪些方向:

  • 聊天
  • 发送
  • 配置
  • Prompt
  • LLM
  • 插件查询
  • 路由
  • 事件
  • 存储

也就是说,它回答的问题更接近:

插件写出来以后,运行时要怎样和系统能力交互。

plugin_system.types

这一层解决的则是另一类很实际的问题:

常用公共类型,到底从哪里拿。

它不是运行时 API,也不是组件基类。

它更像一层为插件作者准备的稳定类型出口,让你不用每次都下钻到更深层路径里去找:

  • Message
  • MessageType
  • PromptTemplate
  • LLMPayload
  • ToolCall
  • ToolResult
  • TaskType

这层看起来没那么“炫”,但写插件写多了以后,你会非常感谢它存在。

20.7 为什么这一步不是“补充知识”,而是“真正进入插件作者视角”

这一点值得单独说明。

后面要讲的 apitypes,不是那种“可学可不学的补充篇”。

它们更像是:

当你已经理解插件系统内部边界以后,终于开始从插件作者真正日常使用的入口来重新看整个系统。

前面你更像是在认识系统本体。

后面你会更像是在认识:

“作为插件作者,我真正应该从哪一层接这个系统。”

这两者其实不一样。

前者偏理解原理,后者偏形成稳定的编写习惯。

而一个插件作者一旦形成稳定习惯,后续写插件的速度和可维护性都会明显提高。

20.8 这也是为什么前面没有急着先讲 API 总表

你可能也会反过来问:

既然 plugin_system.apiplugin_system.types 这么重要,为什么不一开始就先讲?

答案其实很简单。

因为如果你在还没建立组件边界、消息模型、运行链路之前,就先看一堆 API 名字,体验往往会很差。

你会知道:

  • send_api
  • chat_api
  • prompt_api
  • adapter_api

但你不一定知道:

  • 这些 API 分别服务哪一层问题
  • 它们和前面那些组件边界怎么对应
  • 什么时候该用,什么时候不该用

所以更合理的顺序其实正是现在这样:

  1. 先理解插件系统里都有哪些角色和边界
  2. 再回头看插件作者的公共入口层

这样你看到的就不再是“功能菜单”,而是一组有上下文的位置。

20.9 如果把前面的学习过程压成一条线,大概是这样

你可以把前面一路走来的过程,粗略压成这样一条线:

  1. 先理解插件是什么,怎样最小落地
  2. 再理解插件里能长出哪些组件
  3. 再理解这些组件分别卡在哪些系统边界上
  4. 再理解消息、平台、发送、对话这些链路怎么串起来
  5. 最后回到插件作者真正会碰到的公共入口层

如果你现在正站在第 5 步门口,那其实说明前面的基础已经铺得差不多了。

后面要做的,不再是继续无止境地扩展概念,而是开始收拢使用入口。

20.10 这一章就先收在这里:下一阶段,开始从“组件世界”走向“入口世界”

如果把这一章压成最后几句话,我最希望你记住的是:

  1. 你前面学到的那些组件、链路和边界,并不是散的,它们已经开始自然汇合。
  2. 下一阶段不再只是继续认识组件,而是开始认识插件作者真正会使用的公共入口。
  3. plugin_system.baseplugin_system.apiplugin_system.types,就是这层入口的重要起点。

接下来我们会开始专门讲这些入口。

但在进入细节之前,你现在先只需要保留一个很简单的感觉:

前面那一整段路,不是白走的,它正在把你带到“真正会写插件的人会怎样接系统”这一层。

下一章,一个很自然的起点就是:

先从 plugin_system.api 开始,看插件作者怎样通过公共 API 和系统运行时打交道。

贡献者

The avatar of contributor named as minecraft1024a minecraft1024a
The avatar of contributor named as Windpicker-owo Windpicker-owo

页面历史

Released under the GPL-3.0 License.

新对话
MoFox 助手

下午好。

今天想做点什么?

聊天内容可能会被记录以用于改进服务及其质量,并会遵循我们的隐私政策进行处理。