Code Reader
首页
帮助
设计文档
首页
帮助
设计文档
  • 插件系统架构

插件系统架构

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

发现优先级

  1. Config 路径: plugins.load.paths 配置的路径 (origin: "config")
  2. Workspace 路径: {workspaceDir}/.clawdbot/extensions (origin: "workspace")
  3. Global 路径: ~/.clawdbot/extensions (origin: "global")
  4. 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 }

优先级

  1. 如果 config.enabled === false → disabled: "plugins disabled"
  2. 如果 config.deny.includes(id) → disabled: "blocked by denylist"
  3. 如果 config.allow.length > 0 且不在列表中 → disabled: "not in allowlist"
  4. 如果 config.slots.memory === id → enabled: true
  5. 如果 config.entries[id].enabled === true → enabled: true
  6. 如果 config.entries[id].enabled === false → disabled: "disabled in config"
  7. 如果是 bundled 且在 BUNDLED_ENABLED_BY_DEFAULT 中 → enabled: true
  8. 如果是 bundled → disabled: "bundled (disabled by default)"
  9. 否则 → 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 Pluginsrc/channels/plugins/types.plugin.ts
Provider Pluginsrc/plugins/types.ts