插件系统架构
Moltbot 的插件化扩展机制
概述
插件系统是 Moltbot 的核心扩展机制,支持动态加载 Channel、Provider、Tool、Hook 等插件。采用发现-加载-注册-执行的流程,实现了模块化和可扩展性。
设计目标
- 模块化: 核心功能最小化,通过插件扩展
- 统一 API: 所有插件使用相同的 Plugin API
- 动态加载: 支持运行时发现和加载插件
- 热重载: 配置变更时可重新加载插件
- 类型安全: TypeScript 支持和 Schema 验证
插件接口定义
核心插件定义
文件: src/plugins/types.ts
export type MoltbotPluginDefinition = {
id?: string; // 插件唯一标识符
name?: string; // 插件显示名称
description?: string; // 插件描述
version?: string; // 插件版本
kind?: PluginKind; // 插件类型 (目前支持 "memory")
configSchema?: MoltbotPluginConfigSchema; // 配置 schema
register?: (api: MoltbotPluginApi) => void | Promise<void>; // 注册函数
activate?: (api: MoltbotPluginApi) => void | Promise<void>; // 激活函数
};
Plugin API 接口
export type MoltbotPluginApi = {
// 插件元信息
id: string;
name: string;
version?: string;
description?: string;
source: string;
// 配置访问
config: MoltbotConfig;
pluginConfig?: Record<string, unknown>;
// 运行时 API (暴露核心功能)
runtime: PluginRuntime;
logger: PluginLogger;
// 注册方法
registerTool: (tool, opts?) => void;
registerHook: (events, handler, opts?) => void;
registerHttpHandler: (handler) => void;
registerHttpRoute: (params) => void;
registerChannel: (registration) => void;
registerGatewayMethod: (method, handler) => void;
registerCli: (registrar, opts?) => void;
registerService: (service) => void;
registerProvider: (provider) => void;
registerCommand: (command) => void;
// 工具方法
resolvePath: (input: string) => string;
// 生命周期钩子
on: <K extends PluginHookName>(
hookName: K,
handler: PluginHookHandlerMap[K],
opts?: { priority?: number }
) => void;
};
插件清单文件
Manifest 定义
文件: src/plugins/manifest.ts
每个插件必须包含 moltbot.plugin.json 清单文件:
export type PluginManifest = {
id: string; // 必需:插件 ID
configSchema: Record<string, unknown>; // 必需:配置 JSON Schema
kind?: PluginKind; // 可选:插件类型
channels?: string[]; // 可选:提供的通道 IDs
providers?: string[]; // 可选:提供的 provider IDs
skills?: string[]; // 可选:提供的 skill IDs
name?: string; // 可选:插件名称
description?: string; // 可选:插件描述
version?: string; // 可选:插件版本
uiHints?: Record<string, PluginConfigUiHint>; // UI 提示
};
插件类型详解
Channel 插件
定义: src/channels/plugins/types.plugin.ts
Channel 插件实现了消息渠道的完整适配器接口。
export type ChannelPlugin<ResolvedAccount = any> = {
id: ChannelId;
meta: ChannelMeta;
capabilities: ChannelCapabilities;
// 核心适配器
config: ChannelConfigAdapter<ResolvedAccount>;
messaging?: ChannelMessagingAdapter;
outbound?: ChannelOutboundAdapter;
auth?: ChannelAuthAdapter;
security?: ChannelSecurityAdapter<ResolvedAccount>;
// 可选功能
setup?: ChannelSetupAdapter;
pairing?: ChannelPairingAdapter;
groups?: ChannelGroupAdapter;
mentions?: ChannelMentionAdapter;
commands?: ChannelCommandAdapter;
directory?: ChannelDirectoryAdapter;
status?: ChannelStatusAdapter<ResolvedAccount>;
gateway?: ChannelGatewayAdapter<ResolvedAccount>;
// Agent 工具和钩子
agentTools?: ChannelAgentToolFactory | ChannelAgentTool[];
agentPrompt?: ChannelAgentPromptAdapter;
};
Provider 插件
定义: src/plugins/types.ts
Provider 插件提供 AI 模型提供商和认证方法。
export type ProviderPlugin = {
id: string;
label: string;
docsPath?: string;
aliases?: string[];
envVars?: string[];
models?: ModelProviderConfig;
auth: ProviderAuthMethod[]; // 认证方法
formatApiKey?: (cred: AuthProfileCredential) => string;
refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
};
export type ProviderAuthMethod = {
id: string;
label: string;
hint?: string;
kind: ProviderAuthKind; // "oauth" | "api_key" | "token" | "device_code" | "custom"
run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
};
Tool 插件
插件可以注册 Agent 工具:
MoltbotPluginToolFactory = (
ctx: MoltbotPluginToolContext,
) => AnyAgentTool | AnyAgentTool[] | null | undefined;
// 注册方式
api.registerTool(tool, { name?: string, names?: string[], optional?: boolean });
插件加载流程
插件发现机制
文件: src/plugins/discovery.ts
export function discoverMoltbotPlugins(params: {
workspaceDir?: string;
extraPaths?: string[];
}): PluginDiscoveryResult
发现优先级
- Config 路径:
plugins.load.paths配置的路径 (origin: "config") - Workspace 路径:
{workspaceDir}/.clawdbot/extensions(origin: "workspace") - Global 路径:
~/.clawdbot/extensions(origin: "global") - Bundled 路径:
extensions/(仓库内) (origin: "bundled")
发现规则
- 文件扩展名:
.ts,.js,.mts,.cts,.mjs,.cjs - 目录必须包含
index.ts/js/mjs/cjs或在package.json中声明moltbot.extensions - 支持多扩展点(一个 npm 包提供多个插件)
插件加载流程图
插件配置管理
配置结构
文件: src/plugins/config-state.ts
export type NormalizedPluginsConfig = {
enabled: boolean; // 全局插件开关
allow: string[]; // 允许列表
deny: string[]; // 拒绝列表
loadPaths: string[]; // 额外加载路径
slots: {
memory?: string | null; // Memory slot 插件 ID
};
entries: Record<string, { // 插件特定配置
enabled?: boolean;
config?: unknown;
}>;
};
启用状态解析
export function resolveEnableState(
id: string,
origin: PluginRecord["origin"],
config: NormalizedPluginsConfig,
): { enabled: boolean; reason?: string }
优先级
- 如果
config.enabled === false→disabled: "plugins disabled" - 如果
config.deny.includes(id)→disabled: "blocked by denylist" - 如果
config.allow.length > 0且不在列表中 →disabled: "not in allowlist" - 如果
config.slots.memory === id→enabled: true - 如果
config.entries[id].enabled === true→enabled: true - 如果
config.entries[id].enabled === false→disabled: "disabled in config" - 如果是 bundled 且在
BUNDLED_ENABLED_BY_DEFAULT中 →enabled: true - 如果是 bundled →
disabled: "bundled (disabled by default)" - 否则 →
enabled: true(workspace/global 默认启用)
插件运行时 API
PluginRuntime 结构
文件: src/plugins/runtime/types.ts
export type PluginRuntime = {
version: string;
// 配置管理
config: {
loadConfig: LoadConfig;
writeConfigFile: WriteConfigFile;
};
// 系统工具
system: {
enqueueSystemEvent: EnqueueSystemEvent;
runCommandWithTimeout: RunCommandWithTimeout;
formatNativeDependencyHint: FormatNativeDependencyHint;
};
// 媒体处理
media: {
loadWebMedia: LoadWebMedia;
detectMime: DetectMime;
mediaKindFromMime: MediaKindFromMime;
isVoiceCompatibleAudio: IsVoiceCompatibleAudio;
getImageMetadata: GetImageMetadata;
resizeToJpeg: ResizeToJpeg;
};
// 文字转语音
tts: {
textToSpeechTelephony: TextToSpeechTelephony;
};
// 工具
tools: {
createMemoryGetTool: CreateMemoryGetTool;
createMemorySearchTool: CreateMemorySearchTool;
registerMemoryCli: RegisterMemoryCli;
};
// 通道功能
channel: {
text: { /* 文本处理 */ };
reply: { /* 回复处理 */ };
routing: { /* 路由 */ };
pairing: { /* 配对 */ };
media: { /* 媒体 */ };
activity: { /* 活动记录 */ };
session: { /* 会话 */ };
mentions: { /* 及 */ };
reactions: { /* 反应 */ };
groups: { /* 群组 */ };
debounce: { /* 防抖 */ };
commands: { /* 命令 */ };
// 特定通道
discord: { /* Discord 专用功能 */ };
slack: { /* Slack 专用功能 */ };
telegram: { /* Telegram 专用功能 */ };
signal: { /* Signal 专用功能 */ };
imessage: { /* iMessage 专用功能 */ };
whatsapp: { /* WhatsApp 专用功能 */ };
line: { /* LINE 专用功能 */ };
};
// 日志
logging: {
shouldLogVerbose: ShouldLogVerbose;
getChildLogger: (bindings?, opts?) => RuntimeLogger;
};
// 状态
state: {
resolveStateDir:: ResolveStateDir;
};
};
插件生命周期钩子
钩子类型
文件: src/plugins/types.ts
export type PluginHookName =
| "before_agent_start"
| "agent_end"
| "before_compaction"
| "after_compaction"
| "message_received"
| "message_sending"
| "message_sent"
| "before_tool_call"
| "after_tool_call"
| "tool_result_persist"
| "session_start"
| "session_end"
| "gateway_start"
| "gateway_stop";
钩子注册
// 监听 Agent 开始事件
api.on("before_agent_start", async (ctx) => {
console.log("Agent starting:", ctx.sessionKey);
});
// 监听工具调用
api.on("before_tool_call", async (ctx) => {
console.log("Tool called:", ctx.toolName);
});
代码路径引用
| 功能 | 文件路径 |
|---|---|
| 插件类型定义 | src/plugins/types.ts |
| 插件发现 | src/plugins/discovery.ts |
| 插件加载器 | src/plugins/loader.ts |
| 插件清单 | src/plugins/manifest.ts |
| 插件注册表 | src/plugins/registry.ts |
| 插件运行时 | src/plugins/runtime.ts |
| 插件配置 | src/plugins/config-state.ts |
| Channel Plugin | src/channels/plugins/types.plugin.ts |
| Provider Plugin | src/plugins/types.ts |