一个基于 Go 的插件化执行系统。
系统通过“主程序编排 + 插件处理业务”的方式,将可变业务能力从主流程中解耦出来,适合持续演进、可扩展、需容错治理的工程场景。
- 1. 项目简介
- 2. 核心能力
- 3. 目录结构
- 4. 架构与执行原理
- 5. 快速开始
- 6. 命令行使用说明
- 7. 插件规范与配置
- 8. 内置插件详细说明
- 9. 输出结果解读
- 10. 常见问题与排查
- 11. 测试与质量保障
- 12. 扩展开发指南
- 13. 未来演进方向
在传统系统中,主程序常常承载大量业务逻辑,导致修改成本高、回归风险大。
本项目通过插件化机制,将业务能力下沉到插件层,主程序只负责:
- 插件发现与装载
- 依赖与版本校验
- 执行编排(串行/并行)
- 超时、重试、熔断治理
- 输出结构化结果与可读化报告
这个模式特别适合:
- 业务规则频繁变化
- 希望多人并行开发不同能力模块
- 需要高可用与故障隔离
- 希望在不改主流程代码的前提下扩展能力
- 自动扫描
plugins/目录 - 插件启用/禁用状态持久化
- 支持运行时热加载检测(
watch)
- 串行模式:后一个插件消费前一个插件输出
- 并行模式:每个插件基于同一输入独立运行,最终合并
- 单插件超时控制
- 失败重试
- 熔断与冷却机制
- 插件异常隔离(子进程执行,主程序不崩)
- 插件依赖关系声明与校验
- 拓扑排序执行
- 语义化版本约束匹配
- 默认结构化 JSON 报告
--pretty分段可读输出(清晰显示每个插件改了什么)
.
├── cmd/
│ └── plugin-host/
│ ├── main.go
│ ├── pretty.go
│ └── pretty_test.go
├── internal/
│ ├── executor/
│ │ └── process.go
│ ├── loader/
│ │ ├── loader.go
│ │ └── loader_test.go
│ ├── manager/
│ │ ├── manager.go
│ │ └── manager_test.go
│ ├── state/
│ │ ├── store.go
│ │ └── store_test.go
│ └── version/
│ ├── semver.go
│ └── semver_test.go
├── plugins/
│ ├── uppercase/
│ │ ├── main.go
│ │ └── plugin.json
│ ├── enrich/
│ │ ├── main.go
│ │ └── plugin.json
│ └── companion_affect/
│ ├── main.go
│ └── plugin.json
├── go.mod
└── README.md
-
cmd/plugin-host
命令入口,负责参数解析与输出格式控制(JSON/pretty)。 -
internal/loader
插件清单加载、字段校验、目录快照生成(热加载依据)。 -
internal/manager
核心编排模块:依赖检查、执行计划、重试/熔断、结果汇总。 -
internal/executor
插件子进程调用器,负责 stdin/stdout JSON 协议通信。 -
internal/state
持久化插件状态(启停 + 熔断信息)。 -
internal/version
语义化版本解析与约束比较。
- 串行:
input -> pluginA -> pluginB -> pluginC -> final - 并行:
input -> {pluginA, pluginB, pluginC} -> merged
加载 -> 校验 -> 依赖拓扑 -> 执行 -> 重试/熔断 -> 报告
- Go 1.20 及以上(建议与你本机保持一致)
- Windows / Linux / macOS(当前示例已在 Windows 环境验证)
cd "项目目录"go run ./cmd/plugin-host list创建 input.json:
{
"text": "jeck今天有点累,但也很想继续努力"
}go run ./cmd/plugin-host run --data-file input.json --pretty查看插件基本信息与状态。
go run ./cmd/plugin-host list启用或禁用插件。
go run ./cmd/plugin-host disable enrich
go run ./cmd/plugin-host enable enrich执行插件链。
go run ./cmd/plugin-host run --data-file input.json常用参数:
--parallel:并行执行模式--pretty:可读分段输出--timeout-ms:默认超时--retries:默认重试次数--failure-threshold:熔断阈值--cooldown-ms:熔断冷却时长
完整示例:
go run ./cmd/plugin-host run --data-file input.json --pretty --timeout-ms 3000 --retries 1 --failure-threshold 2 --cooldown-ms 5000监听插件目录变更,自动重载。
go run ./cmd/plugin-host watch --interval-ms 1500输入(Host -> Plugin):
{
"data": {
"text": "hello"
}
}输出(Plugin -> Host)成功:
{
"data": {
"text": "HELLO"
}
}输出失败:
{
"error": "something failed"
}{
"id": "enrich",
"name": "Enrich",
"version": "1.0.0",
"description": "追加处理元信息",
"command": ["go", "run", "./plugins/enrich"],
"timeout_ms": 2000,
"max_retries": 1,
"failure_threshold": 2,
"cooldown_ms": 5000,
"min_host_version": "1.0.0",
"dependencies": [
{ "id": "uppercase", "version": ">=1.0.0,<2.0.0" }
]
}id:插件唯一标识name:插件名称version:插件版本description:描述command:插件启动命令timeout_ms:超时(毫秒)max_retries:最大重试次数failure_threshold:连续失败熔断阈值cooldown_ms:冷却时长(毫秒)min_host_version:主程序最低版本要求dependencies:插件依赖和版本约束
支持示例:
1.2.3(精确)>=1.0.0,<2.0.0(区间)^1.2.0(同大版本兼容)
文件:
plugins/uppercase/plugin.jsonplugins/uppercase/main.go
功能:
- 从
data.text读取文本 - 去除首尾空格
- 转换为大写(英文会变化,中文通常保持原样)
输入示例:
{"data":{"text":" jeck今天有点累 "}}输出示例:
{"data":{"text":"JECK今天有点累"}}价值:
- 作为标准化前置处理,降低后续插件输入噪声。
局限:
- 当前只处理顶层
text字段。
文件:
plugins/enrich/plugin.jsonplugins/enrich/main.go
功能:
- 在结果中追加元信息:
processed_athandled_by
依赖:
- 依赖
uppercase,版本>=1.0.0,<2.0.0
输入示例:
{"data":{"text":"JECK今天有点累"}}输出示例:
{
"data": {
"text": "JECK今天有点累",
"processed_at": "2026-04-21T17:46:20+08:00",
"handled_by": "enrich@1.0.0"
}
}价值:
- 增强链路可追踪性,便于日志审计与回放分析。
局限:
- 元信息字段固定,暂未参数化。
文件:
plugins/companion_affect/plugin.jsonplugins/companion_affect/main.go
功能:
- 分析输入文本情绪倾向
- 输出数字人可直接消费的结构化交互提示:
emotion_labelemotion_scoregesture_hintfacial_hinttone_hintreply_style_hint
- 追加
companion_runtime记录插件处理信息
输入示例:
{"data":{"text":"我今天真的好累,有点难过"}}输出示例(节选):
{
"data": {
"text": "我今天真的好累,有点难过",
"affect": {
"emotion_label": "sad_or_stressed",
"emotion_score": 80,
"gesture_hint": "慢速点头,身体前倾",
"facial_hint": "眉头轻皱,眼神专注",
"tone_hint": "低语速、低音量、安抚感",
"reply_style_hint": "先共情,再给陪伴式引导,避免说教"
}
}
}价值:
- 对话层:给回复风格提示
- 动作层:给姿态/动作提示
- 表情层:给表情倾向提示
- 语音层:给语速语调提示
局限:
- 当前为规则示例,不是学习型情感模型。
run 默认返回:
started_at/ended_atparallelinputfinalresults(每个插件的状态、耗时、输出)
分为三段:
- Run Summary(总览)
- Final Output(最终结果)
- Plugin Segments(逐插件分段)
每个插件分段展示:
- 插件身份(id/name/version)
- 状态、耗时、重试次数
- 字段变化摘要(新增/修改)
- 错误信息(如有)
这可以清楚回答:“谁改了什么,在哪一步改的”。
因为系统输出的是执行报告,不只是最终结果。
如果你只想快速看每一步变化,使用 --pretty。
- 串行:后续插件消费前一插件输出
- 并行:每个插件都消费原始输入,最后合并
报错示例:invalid character 'ï' looking for beginning of value
原因:文件带 UTF-8 BOM。
建议:使用无 BOM UTF-8 保存 input.json。
这通常是外部服务鉴权或访问策略问题(登录态、Token、网络策略等),不是本项目插件执行引擎本身的逻辑错误。
运行测试:
go test ./...当前覆盖:
- 状态持久化与熔断生命周期
- 依赖拓扑排序与环检测
- 版本约束匹配
- 热加载快照变化检测
- pretty 渲染(串行/并行/错误/无变更)
建议补充:
- 超时 + 重试 + 熔断联动场景
- 并行模式大规模插件稳定性
- 大对象输出下的 pretty 性能与截断策略
- 创建目录:
plugins/<plugin_id>/ - 编写
plugin.json - 编写
main.go(遵守输入输出协议) - 运行
go run ./cmd/plugin-host list确认加载成功 - 运行
go run ./cmd/plugin-host run --data-file input.json --pretty验证行为
- 插件内部只做业务,不做系统治理
- 输出尽量稳定,避免频繁变更字段结构
- 失败时返回明确错误字符串,方便诊断
- 对耗时逻辑建议增加超时保护
- 熔断 half-open 探测机制
- 插件资源配额(CPU/内存)
- 深层字段 diff(可选)
- 统一指标采集与监控
- 支持 HTTP / gRPC / WASM 协议插件
- 插件签名校验与安全策略