插件系统
插件系统允许第三方扩展 CocoCat 的功能——注册新工具、挂接到工具调用生命周期、无需修改核心代码。
架构
plugins/{name}/
├── plugin.json # 清单(必选)
├── *.py # 处理器代码
└── ... # 其他资源所有插件存放在项目根目录 plugins/ 下,每个子目录一个插件。
发现机制
plugin_manager.py 提供两级发现:
| 方式 | 说明 |
|---|---|
| 目录扫描 | 扫描 plugins/*/plugin.json,按 manifest 加载 |
| entry_points | (预留)支持通过 Python entry_points 注册 |
调用 discover_plugins() 返回 {name: manifest} 字典。
Manifest 格式 (plugin.json)
json
{
"name": "my-plugin",
"version": "1.0.0",
"description": "示例插件",
"tools": [
{
"name": "my_tool",
"description": "工具描述",
"inputSchema": {
"type": "object",
"properties": {
"param1": {"type": "string"}
},
"required": ["param1"]
},
"handler": "handler.py:my_func"
}
],
"hooks": {
"pre_tool_call": ["hooks.py:pre_tool"],
"post_tool_call": ["hooks.py:post_tool"]
}
}工具注册
tool_registry.py 定义 PluginTool 基类,继承自 Tool:
python
class PluginTool(Tool):
def execute(self, **kwargs) -> str:
result = self._handler(**kwargs)
return str(result) if result is not None else ""load_plugin_tools(manifest) 根据 manifest 中的 tools 数组动态创建 PluginTool 实例,handler 引用格式为 file.py:function_name。
钩子系统
plugin_hooks.py 提供 HookRegistry 类:
| 事件 | 触发时机 | 可做操作 |
|---|---|---|
pre_tool_call | 工具执行前 | 拦截/修改参数、拒绝执行 |
post_tool_call | 工具执行后 | 修改/记录结果 |
pre_tool_call
python
def pre_tool(tool_name: str, args: dict, ctx: dict) -> dict:
if tool_name == "exec_command" and "rm" in args.get("command", ""):
return {"action": "deny", "reason": "rm blocked by plugin"}
return {"action": "continue", "args": args}返回值说明:
action: "continue"— 放行,可选args修改参数action: "deny"— 拒绝,附带reason
post_tool_call
python
def post_tool(tool_name: str, args: dict, result: str, ctx: dict) -> dict:
return {"result": result + "\n[audited by plugin]"}安装
install_plugin(source, name="") 支持两种来源:
| source 格式 | 行为 |
|---|---|
./path/to/plugin | 本地路径复制到 plugins/{name} |
https://github.com/... | git clone --depth 1 到 plugins/{name} |
安装后自动验证 plugin.json 是否存在。
卸载
uninstall_plugin(name) 删除 plugins/{name} 目录。
完整示例
plugins/example-plugin/
├── plugin.json
├── tools.py # 工具处理器
└── hooks.py # 钩子处理器json
{
"name": "example-plugin",
"version": "1.0.0",
"description": "示例:添加 echo 工具并在执行前记录",
"tools": [
{
"name": "echo",
"description": "回显输入",
"inputSchema": {
"type": "object",
"properties": {
"text": {"type": "string"}
},
"required": ["text"]
},
"handler": "tools.py:echo_handler"
}
],
"hooks": {
"pre_tool_call": ["hooks.py:audit_pre"]
}
}