OpenClaw 的插件体系由“插件 SDK”、“插件运行时”、“通道适配器(Channel)”与“ACP 运行时”等模块组成。插件通过统一的 OpenClawPluginApi 注册工具、钩子、HTTP 路由、CLI 命令、服务与通道插件;运行时提供媒体、TTS/STT、事件、日志、状态等能力;通道插件封装各渠道(如 Discord、Telegram、Feishu 等)的能力;ACP 运行时为外部会话控制提供统一接口。
graph TB
subgraph "插件 SDK"
A["OpenClawPluginApi<br/>注册与上下文"]
B["OpenClawPluginConfigSchema<br/>配置校验与 UI 提示"]
C["OpenClawPluginRuntime<br/>运行时能力"]
end
subgraph "通道插件"
D["ChannelPlugin 接口<br/>适配各渠道能力"]
E["ChannelRuntime<br/>文本/回复/路由/分组/命令等"]
end
subgraph "ACP 运行时"
F["AcpRuntime 接口<br/>会话控制与事件流"]
end
A --> C
A --> D
C --> E
D --> E
A --> F
核心组件
本节概述插件 API 的关键类型与职责边界,便于开发者建立整体认知。
-
插件 API(OpenClawPluginApi)
- 职责:注册工具、钩子、HTTP 路由、CLI、服务、通道插件、网关方法、上下文解析与生命周期钩子。
- 关键方法:registerTool、registerHook、registerHttpRoute、registerCli、registerService、registerChannel、registerGatewayMethod、registerCommand、registerContextEngine、resolvePath、on。
- 参考路径:types.ts
-
插件运行时(PluginRuntime)
- 职责:提供子代理运行、等待、会话读取、删除;通道专用能力集合。
- 子代理接口:subagent.run、waitForRun、getSessionMessages、getSession、deleteSession。
- 通道接口:text、reply、routing、pairing、media、activity、session、mentions、reactions、groups、debounce、commands、以及各渠道专用方法。
- 参考路径:runtime/types.ts,runtime/types-core.ts,runtime/types-channel.ts
-
通道插件(ChannelPlugin)
- 职责:声明渠道标识、元数据、能力集与适配器集合(认证、配置、出站、状态、心跳、提要、消息、代理提示、目录、解析器、动作、线程等)。
- 参考路径:types.plugin.ts,types.ts
-
ACP 运行时(AcpRuntime)
- 职责:会话确保、回合执行、能力查询、状态获取、模式与配置项设置、诊断、取消与关闭。
- 参考路径:types.ts
架构总览
下图展示插件在系统中的位置与交互关系:插件通过 OpenClawPluginApi 注册能力;运行时提供媒体、TTS/STT、事件与日志;通道插件桥接不同渠道;ACP 运行时提供外部会话控制。
sequenceDiagram
participant Dev as "插件开发者"
participant API as "OpenClawPluginApi"
participant RT as "PluginRuntime"
participant CH as "ChannelPlugin"
participant ACP as "AcpRuntime"
Dev->>API : 注册工具/钩子/HTTP/CLI/服务/通道/网关方法
API->>RT : 访问运行时能力媒体/TTS/STT/事件/日志/状态
API->>CH : 注册通道插件并绑定运行时
API->>ACP : 注册/调用 ACP 会话控制
RT-->>Dev : 返回运行时结果子代理/会话/通道操作
详细组件分析
插件运行时 API(PluginRuntime)
-
子代理运行
- run(params): 启动一次子代理运行,返回 runId。
- waitForRun(params): 等待指定 runId 完成,返回状态与可选错误。
- getSessionMessages(params): 获取会话消息列表。
- getSession(params)/deleteSession(params): 读取/删除会话(兼容/删除操作)。
- 参数与返回类型参考:runtime/types.ts
-
通道运行时能力(PluginRuntime.channel)
- 文本:分块、控制命令检测、Markdown 表格处理等。
- 回复:基于配置派发、打字态、入站上下文收尾、信封格式化等。
- 路由:会话键构建、路由解析。
- 配对:配对消息构建、允许来源读写、账户级配对请求。
- 媒体:远程媒体抓取、本地保存。
- 活动:通道活动记录与查询。
- 会话:会话存储路径、更新时间、入站会话记录、最后路由更新。
- 提及:提及正则构建与匹配。
- 反应:是否确认反应、回复后移除确认反应。
- 分组:组策略解析、是否需要提及。
- 去抖:入站去抖构造与阈值解析。
- 命令:授权计算、控制命令识别、是否处理文本命令。
- 渠道专用:Discord、Slack、Telegram、Signal、iMessage、WhatsApp、LINE 等。
- 参考路径:runtime/types-channel.ts
-
运行时核心能力(PluginRuntimeCore)
- 版本、配置加载/写入、系统事件、心跳唤醒、命令执行、媒体工具、TTS/STT、内存工具、事件订阅、日志、状态目录解析。
- 参考路径:runtime/types-core.ts
classDiagram
class PluginRuntime {
+subagent.run(params) SubagentRunResult
+subagent.waitForRun(params) SubagentWaitResult
+subagent.getSessionMessages(params) SubagentGetSessionMessagesResult
+subagent.getSession(params) SubagentGetSessionResult
+subagent.deleteSession(params) void
+channel.text.*
+channel.reply.*
+channel.routing.*
+channel.pairing.*
+channel.media.*
+channel.activity.*
+channel.session.*
+channel.mentions.*
+channel.reactions.*
+channel.groups.*
+channel.debounce.*
+channel.commands.*
+channel.discord.*
+channel.slack.*
+channel.telegram.*
+channel.signal.*
+channel.imessage.*
+channel.whatsapp.*
+channel.line.*
}
class PluginRuntimeCore {
+version string
+config.loadConfig()
+config.writeConfigFile()
+system.enqueueSystemEvent()
+system.requestHeartbeatNow()
+system.runCommandWithTimeout()
+system.formatNativeDependencyHint()
+media.loadWebMedia()
+media.detectMime()
+media.mediaKindFromMime()
+media.isVoiceCompatibleAudio()
+media.getImageMetadata()
+media.resizeToJpeg()
+tts.textToSpeechTelephony()
+stt.transcribeAudioFile()
+tools.createMemoryGetTool()
+tools.createMemorySearchTool()
+tools.registerMemoryCli()
+events.onAgentEvent()
+events.onSessionTranscriptUpdate()
+logging.shouldLogVerbose()
+logging.getChildLogger(bindings, opts) RuntimeLogger
+state.resolveStateDir()
}
PluginRuntime --> PluginRuntimeCore : "组合"
配置 API(OpenClawPluginConfigSchema)
- 功能:提供配置安全解析(safeParse)、直接解析(parse)、验证(validate)、UI 提示(uiHints)、JSON Schema(jsonSchema)。
- 典型用途:插件配置校验、向 UI 展示标签、帮助信息、敏感字段标记。
- 参考路径:types.ts
工具 API(OpenClawPluginToolContext 与工厂)
- 上下文字段:配置、工作空间、代理目录、代理 ID、会话键、会话 ID、消息通道、代理账户 ID、请求者发送方 ID、是否所有者、沙箱状态等。
- 工厂签名:(ctx: OpenClawPluginToolContext) => AnyAgentTool | AnyAgentTool[] | null | undefined
- 参考路径:types.ts
消息处理 API(通道插件)
- 通道插件接口(ChannelPlugin):声明渠道能力与适配器集合,包括认证、配置、出站、状态、心跳、消息、代理提示、目录、解析器、动作、线程等。
- 通道运行时(PluginRuntime.channel.*):提供各渠道专用能力(如 Discord、Telegram、Slack、Signal、iMessage、WhatsApp、LINE)。
- 参考路径:types.plugin.ts,types.ts,runtime/types-channel.ts
classDiagram
class ChannelPlugin {
+id ChannelId
+meta ChannelMeta
+capabilities ChannelCapabilities
+config ConfigAdapter
+setup SetupAdapter
+pairing PairingAdapter
+security SecurityAdapter
+groups GroupAdapter
+mentions MentionAdapter
+outbound OutboundAdapter
+status StatusAdapter
+gateway GatewayAdapter
+auth AuthAdapter
+elevated ElevatedAdapter
+commands CommandAdapter
+streaming StreamingAdapter
+threading ThreadingAdapter
+messaging MessagingAdapter
+agentPrompt AgentPromptAdapter
+directory DirectoryAdapter
+resolver ResolverAdapter
+actions MessageActionAdapter
+heartbeat HeartbeatAdapter
+agentTools ChannelAgentToolFactory
}
class PluginRuntimeChannel {
+text.*
+reply.*
+routing.*
+pairing.*
+media.*
+activity.*
+session.*
+mentions.*
+reactions.*
+groups.*
+debounce.*
+commands.*
+discord.*
+slack.*
+telegram.*
+signal.*
+imessage.*
+whatsapp.*
+line.*
}
ChannelPlugin --> PluginRuntimeChannel : "绑定运行时"
ACP 运行时 API(AcpRuntime)
- 方法:ensureSession、runTurn、getCapabilities、getStatus、setMode、setConfigOption、doctor、cancel、close。
- 事件与句柄:AcpRuntimeHandle、AcpRuntimeEvent、AcpRuntimeStatus、AcpRuntimeDoctorReport。
- 参考路径:types.ts
sequenceDiagram
participant P as "插件"
participant R as "AcpRuntime"
participant H as "AcpRuntimeHandle"
P->>R : ensureSession(input) -> H
P->>R : runTurn({handle, text, mode, requestId})
R-->>P : AsyncIterable<AcpRuntimeEvent>
P->>R : getStatus({handle})
R-->>P : AcpRuntimeStatus
P->>R : setMode({handle, mode})
P->>R : setConfigOption({handle, key, value})
P->>R : cancel({handle})
P->>R : close({handle})
使用示例(路径指引)
- 注册 Discord 通道插件:discord/index.ts
- 注册 Telegram 通道插件:telegram/index.ts
- 注册 Feishu 通道插件与多类工具:feishu/index.ts
依赖关系分析
- 插件 SDK 对运行时与通道插件的依赖:通过 OpenClawPluginApi 统一入口,运行时提供核心能力,通道插件提供渠道能力。
- 运行时对系统与媒体子系统的依赖:配置、进程、网络、媒体、TTS/STT、事件与日志等。
- 通道运行时对各渠道子系统的依赖:Discord、Slack、Telegram、Signal、iMessage、WhatsApp、LINE 的具体实现。
graph LR
SDK["OpenClawPluginApi"] --> RT["PluginRuntime"]
SDK --> CP["ChannelPlugin"]
RT --> CORE["PluginRuntimeCore"]
RT --> CH["PluginRuntimeChannel"]
CP --> CH
CH --> DISC["Discord"]
CH --> SLK["Slack"]
CH --> TGL["Telegram"]
CH --> SIG["Signal"]
CH --> IM["iMessage"]
CH --> WAPP["WhatsApp"]
CH --> LINE["LINE"]
性能考量
- 子代理运行与等待:合理设置超时与幂等键,避免重复运行与资源浪费。
- 会话消息读取:限制读取数量与范围,避免一次性加载过多历史消息。
- 媒体与语音:优先使用流式处理与缓存策略,减少重复下载与转码开销。
- 命令与去抖:根据渠道特性调整去抖阈值,平衡响应速度与资源消耗。
- 日志与事件:按需开启详细日志,避免高频写入影响性能。
插件类型与接口
OpenClaw 将插件相关类型与实现分布在多个模块中:
- 核心插件类型与 API 定义位于 plugins 子系统
- 通道插件类型位于 channels/plugins 子系统
- 插件 SDK 汇总导出位于 plugin-sdk 子系统
- 配置 Schema、运行时类型、网关方法类型等分别位于对应目录
graph TB
subgraph "插件核心"
A["plugins/types.ts<br/>定义 OpenClawPluginApi/ConfigSchema/工具/命令/HTTP路由/服务等"]
B["plugins/runtime/types.ts<br/>定义 PluginRuntime 接口"]
C["plugins/config-schema.ts<br/>emptyPluginConfigSchema 空配置模式"]
end
subgraph "通道插件"
D["channels/plugins/types.plugin.ts<br/>ChannelPlugin 抽象"]
E["channels/plugins/types.ts<br/>通道适配器/上下文/消息动作等"]
F["channels/plugins/config-schema.ts<br/>通道配置 Schema 构建"]
end
subgraph "插件SDK汇总"
G["plugin-sdk/index.ts<br/>统一导出常用类型与工具"]
H["plugin-sdk/channel-plugin-common.ts<br/>ChannelPlugin/PluginRuntime/OpenClawPluginApi 导出"]
end
A --> B
A --> C
D --> E
D --> F
G --> A
G --> D
H --> A
H --> D
核心组件
本节对关键类型进行分层说明,并给出使用场景与注意事项。
-
OpenClawPluginApi
- 职责:插件在运行时可调用的 API 边界,包括注册工具、钩子、HTTP 路由、通道、网关方法、CLI、服务、提供商与命令等
- 关键方法与属性:id/name/version/description/source/config/pluginConfig/runtime/logger/registerTool/registerHook/registerHttpRoute/registerChannel/registerGatewayMethod/registerCli/registerService/registerProvider/registerCommand/registerContextEngine/resolvePath/on
- 使用要点:通过 register* 方法将插件能力注入系统;on 提供生命周期钩子订阅;registerContextEngine 为独占槽位,仅允许一个上下文引擎生效
-
OpenClawPluginConfigSchema
- 职责:描述插件配置的校验方式与 UI 提示
- 支持能力:safeParse/parse/validate/uiHints/jsonSchema
- 使用要点:validate 返回 PluginConfigValidation 结果,ok 为 false 时包含错误数组;uiHints 用于在 UI 中展示标签、帮助信息、敏感字段等
-
ChannelPlugin
- 职责:通道插件的统一抽象,承载通道适配器、上下文、能力与生命周期
- 关联类型:ChannelId/ChannelMeta/ChannelOutboundAdapter/ChannelMessagingAdapter/ChannelResolverAdapter/ChannelSetupAdapter/ChannelStatusAdapter/ChannelSecurityAdapter 等
- 使用要点:通过 OpenClawPluginApi.registerChannel 注册;配合 ChannelDock 进行通道停靠与管理
-
插件钩子(Plugin Hook)
- 职责:在代理执行流程中的关键节点注入自定义逻辑
- 钩子名称集合:before_model_resolve/before_prompt_build/before_agent_start/llm_input/llm_output/agent_end/before_compaction/after_compaction/before_reset/message_received/message_sending/message_sent/before_tool_call/after_tool_call/tool_result_persist/before_message_write/session_start/session_end/subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended/gateway_start/gateway_stop
- 事件与结果类型:每个钩子均有对应的 Event 与 Result 类型,支持修改提示词、阻断工具调用、控制消息写入、会话与子代理生命周期等
- 类型守卫:isPluginHookName/isPromptInjectionHookName 等用于运行时校验钩子名称合法性
-
插件命令(Plugin Command)
- 职责:绕过 LLM 的简单命令处理,优先于内置命令与代理调用
- 定义:OpenClawPluginCommandDefinition 包含 name/nativeNames/description/acceptsArgs/requireAuth/handler
- 上下文:PluginCommandContext 提供发送者标识、通道、授权状态、参数、账户与线程等
-
HTTP 路由与网关方法
- 路由:OpenClawPluginHttpRouteParams 定义路径、处理器、认证方式(gateway/plugin)、匹配策略与替换行为
- 网关方法:GatewayRequestHandler 与 OpenClawPluginGatewayMethod 绑定到网关请求处理器
-
工具与服务
- 工具工厂:OpenClawPluginToolFactory 在工具上下文中生成 AnyAgentTool 或数组
- 服务:OpenClawPluginService 定义 id/start/stop 生命周期
-
提供商插件(ProviderPlugin)
- 职责:封装第三方提供商的认证与模型配置
- 认证:ProviderAuthMethod 定义 id/label/kind/run;ProviderAuthContext 提供运行环境、提示器、远程标记与 OAuth 处理器
架构总览
下图展示了插件系统的核心交互:插件通过 OpenClawPluginApi 注册能力,系统在代理执行流程中按钩子触发相应事件,通道插件负责消息收发与状态管理,HTTP 路由与网关方法提供外部访问入口。
sequenceDiagram
participant Dev as "插件开发者"
participant API as "OpenClawPluginApi"
participant Runtime as "PluginRuntime"
participant Agent as "代理执行流程"
participant Channel as "通道插件"
participant GW as "网关/Gateway"
Dev->>API : "registerTool/registerHook/registerCommand/..."
API->>Runtime : "存储注册项"
Agent->>Runtime : "触发钩子事件"
Runtime-->>Agent : "返回事件结果/修改"
Channel->>Runtime : "注册通道适配器"
API->>GW : "registerGatewayMethod/registerHttpRoute"
GW-->>API : "回调请求处理器"
详细组件分析
OpenClawPluginApi 类型与方法
-
能力边界
- 注册工具:registerTool(tool | factory, opts?)
- 注册钩子:registerHook(events, handler, opts?)
- 注册 HTTP 路由:registerHttpRoute(params)
- 注册通道:registerChannel(registration | ChannelPlugin)
- 注册网关方法:registerGatewayMethod(method, handler)
- 注册 CLI:registerCli(registrar, opts?)
- 注册服务:registerService(service)
- 注册提供商:registerProvider(provider)
- 注册命令:registerCommand(command)
- 注册上下文引擎:registerContextEngine(id, factory)
- 路径解析:resolvePath(input)
- 生命周期钩子:on(hookName, handler, opts?)
-
使用示例(路径引用)
- 工具注册:参见 src/plugins/types.ts
- 命令注册:参见 src/plugins/types.ts
- HTTP 路由注册:参见 src/plugins/types.ts
- 网关方法注册:参见 src/plugins/types.ts
- 通道注册:参见 src/plugins/types.ts
OpenClawPluginConfigSchema 与配置验证
- 结构
- safeParse/parse/validate:三种校验方式
- uiHints:键到 PluginConfigUiHint 的映射,用于 UI 展示
- jsonSchema:JSON Schema 元数据
- 验证结果
- PluginConfigValidation:ok 为 true/false,false 时携带错误数组
- 使用示例(路径引用)
- 配置校验:参见 src/plugins/types.ts
- 空配置模式:参见 src/plugins/config-schema.ts
ChannelPlugin 与通道适配器
- ChannelPlugin 抽象
- 通过 OpenClawPluginApi.registerChannel 注册
- 可选 Dock:ChannelDock 用于通道停靠
- 关键适配器与上下文
- ChannelOutboundAdapter/ChannelMessagingAdapter/ChannelResolverAdapter/ChannelSetupAdapter/ChannelStatusAdapter/ChannelSecurityAdapter 等
- 上下文类型:ChannelOutboundContext/ChannelGroupContext/ChannelThreadingContext/ChannelSecurityContext 等
- 使用示例(路径引用)
- 通道注册:参见 src/plugins/types.ts
- 通道适配器类型:参见 src/channels/plugins/types.ts
插件钩子体系
- 钩子名称与集合
- 预定义集合:before_model_resolve/before_prompt_build/before_agent_start/llm_input/llm_output/agent_end/before_compaction/after_compaction/before_reset/message_received/message_sending/message_sent/before_tool_call/after_tool_call/tool_result_persist/before_message_write/session_start/session_end/subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended/gateway_start/gateway_stop
- 类型守卫:isPluginHookName/isPromptInjectionHookName
- 事件与结果类型
- 代理阶段:before_model_resolve/before_prompt_build/before_agent_start/llm_input/llm_output/agent_end
- 内存与会话:before_compaction/after_compaction/before_reset/session_start/session_end
- 消息:message_received/message_sending/message_sent
- 工具:before_tool_call/after_tool_call/tool_result_persist/before_message_write
- 子代理:subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended
- 网关:gateway_start/gateway_stop
- 使用示例(路径引用)
- 钩子名称集合与守卫:参见 src/plugins/types.ts
- 代理钩子事件与结果:参见 src/plugins/types.ts
- 工具钩子事件与结果:参见 src/plugins/types.ts
- 会话与子代理钩子事件:参见 src/plugins/types.ts
插件命令与上下文
- 命令定义
- OpenClawPluginCommandDefinition:name/nativeNames/description/acceptsArgs/requireAuth/handler
- 执行上下文
- PluginCommandContext:senderId/channel/channelId/isAuthorizedSender/args/commandBody/config/from/to/accountId/messageThreadId
- 使用示例(路径引用)
- 命令定义与上下文:参见 src/plugins/types.ts
- 命令上下文:参见 src/plugins/types.ts
HTTP 路由与网关方法
- 路由参数
- OpenClawPluginHttpRouteParams:path/handler/auth(match/replaceExisting)
- 网关方法
- OpenClawPluginGatewayMethod:method/handler
- 使用示例(路径引用)
- 路由参数与处理器:参见 src/plugins/types.ts
- 网关方法类型:参见 src/plugins/types.ts
- 网关类型定义:参见 src/gateway/server-methods/types.ts
工具与服务
- 工具工厂
- OpenClawPluginToolFactory:在工具上下文中生成 AnyAgentTool 或数组
- 工具上下文:OpenClawPluginToolContext
- 服务
- OpenClawPluginService:id/start/stop
- 使用示例(路径引用)
- 工具工厂与上下文:参见 src/plugins/types.ts
- 工具上下文:参见 src/plugins/types.ts
- 服务定义:参见 src/plugins/types.ts
提供商插件(ProviderPlugin)
- 认证方法
- ProviderAuthMethod:id/label/kind/run
- ProviderAuthContext:config/agentDir/workspaceDir/prompter/runtime/isRemote/openUrl/oauth
- ProviderAuthResult:profiles/configPatch/defaultModel/notes
- 提供商插件
- ProviderPlugin:id/label/docsPath/aliases/envVars/models/auth/formatApiKey/refreshOAuth
- 使用示例(路径引用)
- 认证方法与上下文:参见 src/plugins/types.ts
- 提供商插件:参见 src/plugins/types.ts
配置 Schema 与通道配置
- 插件配置 Schema
- OpenClawPluginConfigSchema:见上文
- emptyPluginConfigSchema:空配置模式
- 通道配置 Schema
- buildChannelConfigSchema:构建通道配置 Schema
- AllowFromEntrySchema/SecretInputSchema 等:通道允许列表与密钥输入的 Schema
- 使用示例(路径引用)
- 空配置模式:参见 src/plugins/config-schema.ts
- 通道配置 Schema:参见 src/channels/plugins/config-schema.ts
- 允许列表与密钥 Schema:参见 src/config/zod-schema.core.ts
类型安全与最佳实践
- 类型守卫
- isPluginHookName:校验钩子名称是否在预定义集合内
- isPromptInjectionHookName:判断是否为提示注入类钩子
- 泛型约束
- registerTool 支持工厂模式,通过泛型约束 AnyAgentTool
- registerCommand 的 handler 返回 ReplyPayload,确保输出一致性
- 最佳实践
- 使用 OpenClawPluginConfigSchema.validate 进行配置校验并收集错误
- 在 before_prompt_build/before_agent_start 中使用静态上下文避免每轮消耗
- 使用 registerCommand 实现无需 LLM 的简单命令,提升响应速度
- 对 HTTP 路由与网关方法进行权限控制(auth: gateway/plugin)
依赖关系分析
- 插件核心依赖
- plugins/types.ts 依赖 runtime/types.ts、gateway/server-methods/types.ts、hooks/types.ts、config/config.ts 等
- 通道插件依赖
- channels/plugins/types.plugin.ts 与 types.ts 依赖 channels/* 下的适配器与上下文
- SDK 汇总
- plugin-sdk/index.ts 汇总导出常用类型与工具,减少使用者导入成本
graph LR
PT["plugins/types.ts"] --> RT["plugins/runtime/types.ts"]
PT --> GT["gateway/server-methods/types.ts"]
PT --> HT["hooks/types.ts"]
PT --> CT["config/config.ts"]
CPT["channels/plugins/types.plugin.ts"] --> CTS["channels/plugins/types.ts"]
SDK["plugin-sdk/index.ts"] --> PT
SDK --> CPT
性能考量
- 钩子结果字段最小化:在提示注入钩子中仅返回必要字段,避免重复 token 消耗
- 并行处理:利用会话文件路径在压缩前进行异步读取与处理
- 路由与网关:合理设置 auth 与 match 策略,减少不必要的鉴权开销
- 工具调用阻断:在 before_tool_call 中及时阻断不必要或高风险操作
插件运行时 API
围绕插件运行时的核心模块如下:
- 运行时入口与聚合:创建运行时对象,组合各子域功能
- 类型定义:统一声明运行时 API 的结构与参数
- 子域实现:系统、工具、通道、事件、配置、日志、状态目录等
- 子代理运行时:在网关请求上下文内可用的子代理能力
- 测试与契约:类型契约校验与行为测试
graph TB
A["运行时入口<br/>createPluginRuntime"] --> B["核心类型<br/>PluginRuntimeCore"]
A --> C["子域实现<br/>runtime-system.ts"]
A --> D["工具域<br/>runtime-tools.ts"]
A --> E["通道域<br/>runtime-channel.ts"]
A --> F["事件域<br/>runtime-events.ts"]
A --> G["配置域<br/>runtime-config.ts"]
A --> H["子代理运行时<br/>types.ts + index.ts"]
H --> I["子代理通道域<br/>runtime-whatsapp.ts"]
核心组件
- PluginRuntime 聚合对象:由入口函数创建,包含版本号、配置、系统、媒体、TTS/STT、工具、通道、事件、日志、状态目录等能力
- PluginRuntimeCore:运行时核心能力集合,定义了所有可访问的子域与方法签名
- 子代理运行时:在非网关请求上下文中默认不可用,仅在网关请求期间激活
关键点
- 版本解析:通过包信息获取版本字符串,失败时回退为“unknown”
- 子代理不可用时的行为:在非请求上下文中调用子代理方法将抛出错误
- 通道域:按渠道细分(如 Discord、Slack、Telegram、Signal、iMessage、WhatsApp、Line),并提供消息发送、动作处理、探测、权限审计、目录查询等能力
架构总览
下图展示运行时对象的组成与依赖关系:
classDiagram
class PluginRuntime {
+string version
+config
+system
+media
+tts
+stt
+tools
+channel
+events
+logging
+state
+subagent
}
class PluginRuntimeCore {
+version : string
+config
+system
+media
+tts
+stt
+tools
+events
+logging
+state
}
class SubagentRuntime {
+run(params) Promise~SubagentRunResult~
+waitForRun(params) Promise~SubagentWaitResult~
+getSessionMessages(params) Promise~SubagentGetSessionMessagesResult~
+getSession(params) Promise~SubagentGetSessionResult~
+deleteSession(params) Promise~void~
}
PluginRuntime --> PluginRuntimeCore : "聚合"
PluginRuntime --> SubagentRuntime : "可选启用"
详细组件分析
PluginRuntime 类与方法清单
- 版本:只读字符串,用于标识运行时版本
- 配置:加载与写入配置文件
- 系统:事件入队、心跳触发、带超时的命令执行、原生依赖提示格式化
- 媒体:加载 Web 媒体、检测 MIME、根据 MIME 推断媒体类型、音频兼容性判断、图像元数据、图片压缩
- TTS/STT:电话级 TTS、音频文件转写
- 工具:内存检索工具、内存搜索工具、注册内存 CLI
- 通道:文本分块、回复派发、路由、配对、媒体存取、活动记录、会话元数据、提及、反应、群组策略、去抖动、命令授权、各渠道消息发送与监控
- 事件:代理事件监听、会话转录更新监听
- 日志:是否输出详细日志、子日志器创建
- 状态:状态目录解析
- 子代理:运行、等待、查询会话消息、会话删除(在网关请求上下文中可用)
子代理运行时 API
- run(params)
- 参数:会话键、消息、可选扩展系统提示、通道、投递开关、幂等键
- 返回:运行 ID
- waitForRun(params)
- 参数:运行 ID、可选超时毫秒
- 返回:状态(成功/错误/超时)、错误信息(如有)
- getSessionMessages(params)
- 参数:会话键、可选限制条数
- 返回:消息数组
- getSession(params)(已弃用)
- 行为:等同 getSessionMessages
- deleteSession(params)
- 参数:会话键、可选删除转录
- 返回:无
使用约束
- 在非网关请求上下文中,子代理方法将抛出错误;需在请求处理期间使用
通道域 API(以常见渠道为例)
- 文本:分块、控制命令识别、表格模式转换
- 回复:缓冲式派发、打字模拟、配置解析、上下文收尾、信封格式化
- 路由:构建会话键、解析路由
- 配对:构建配对回复、读取允许列表、插入配对请求
- 媒体:远程媒体抓取、本地保存
- 活动:记录与查询渠道活动
- 会话:存储路径解析、会话更新时间读取、入站会话记录、最后路由更新
- 提及:正则构建、匹配模式
- 反应:是否应添加反应、反应移除
- 群组:策略解析、是否必须提及
- 去抖动:入站去抖动器与延迟解析
- 命令:授权解析、控制命令判定、处理开关
- 渠道能力:Discord、Slack、Telegram、Signal、iMessage、WhatsApp、Line 的消息发送、动作处理、探测、权限审计、目录查询等
工具域 API
- 内存检索工具:从内存中获取数据
- 内存搜索工具:基于条件搜索内存
- 注册内存 CLI:向 CLI 注册内存相关命令
系统域 API
- enqueueSystemEvent:入队系统事件
- requestHeartbeatNow:立即请求心跳
- runCommandWithTimeout:带超时的命令执行
- formatNativeDependencyHint:格式化原生依赖提示
事件域 API
- onAgentEvent:注册代理事件监听
- onSessionTranscriptUpdate:注册会话转录更新监听
配置域 API
- loadConfig:加载配置
- writeConfigFile:写入配置文件
日志与状态
- 日志:shouldLogVerbose、getChildLogger
- 状态:resolveStateDir
子代理运行时实现要点
- 子代理运行注册与生命周期:注册运行、等待超时计算、清理策略、期望完成消息、工作区目录继承等
- 子代理启动流程:主会话别名解析、请求者显示键生成、超时配置应用、线程绑定准备等
- 子代理命令动作:发送消息、等待结束、拉取历史、提取助手文本、停止回复等
通道域 WhatsApp 子域
- 延迟加载:消息发送、投票发送、Web 登录、QR 登录、登录等待、Web 监控、动作处理等均采用动态导入
- Web 会话:活跃监听器、认证年龄、登出、自 ID 读取与记录、认证存在性检查
- 登录工具:创建 WhatsApp 登录工具
典型使用场景与流程
会话获取与消息发送(以 Slack 为例)
sequenceDiagram
participant P as "插件"
participant R as "PluginRuntime.channel.slack"
participant S as "Slack 发送器"
P->>R : "resolveChannelAllowlist(...) / resolveUserAllowlist(...)"
R-->>P : "返回允许列表"
P->>R : "sendMessageSlack(...)"
R->>S : "转发发送请求"
S-->>R : "发送结果"
R-->>P : "返回发送结果"
子代理运行与等待
sequenceDiagram
participant P as "插件"
participant SR as "PluginRuntime.subagent"
participant GW as "网关"
P->>SR : "run({sessionKey, message, ...})"
SR-->>P : "返回 runId"
P->>SR : "waitForRun({runId, timeoutMs})"
alt 成功
SR-->>P : "{status : 'ok'}"
else 超时
SR-->>P : "{status : 'timeout'}"
else 错误
SR-->>P : "{status : 'error', error}"
end
P->>GW : "可选:查询会话消息或删除会话"
会话消息查询与历史处理
flowchart TD
Start(["开始"]) --> Call["调用 getSessionMessages(sessionKey, limit?)"]
Call --> Resp{"返回消息数组"}
Resp --> |有消息| Strip["过滤工具消息"]
Resp --> |无消息| End(["结束"])
Strip --> Last["取最后一条消息"]
Last --> Reply["生成回复文本"]
Reply --> End
依赖关系分析
- 运行时入口依赖各子域工厂函数,组合为统一对象
- 子域实现依赖具体业务模块(如通道发送、媒体处理、系统事件、心跳唤醒、进程执行、配置读写等)
- 子代理运行时在非请求上下文中被占位实现,避免误用
- 通道域针对不同渠道进行细粒度导出,便于按需使用
graph LR
IDX["index.ts"] --> SYS["runtime-system.ts"]
IDX --> TOOLS["runtime-tools.ts"]
IDX --> CH["runtime-channel.ts"]
IDX --> EVT["runtime-events.ts"]
IDX --> CFG["runtime-config.ts"]
IDX --> TYPES["types.ts"]
CH --> WHATS["runtime-whatsapp.ts"]
性能考虑
- 动态导入与懒加载:通道域(如 WhatsApp)采用动态导入,减少初始加载开销
- 去抖动与人类延迟:通道域提供入站去抖动与人类延迟配置,有助于降低重复处理与提升交互体验
- 命令分块与表格模式:文本分块与表格模式转换可减少单次消息长度,提高下游处理效率
- 原生依赖提示:通过格式化提示帮助用户快速定位缺失依赖,减少运行时失败重试成本
- 子代理超时与等待:合理设置等待超时与清理策略,避免长时间占用资源
工具函数与助手 API
- 插件 SDK 入口导出位于 src/plugin-sdk/index.ts,统一对外暴露各类工具与类型。
- 关键子模块:
- 文件锁:src/plugin-sdk/file-lock.ts
- 异步队列:src/plugin-sdk/keyed-async-queue.ts
- 运行时存储:src/plugin-sdk/runtime-store.ts
- OAuth 工具:src/plugin-sdk/oauth-utils.ts、src/plugin-sdk/provider-auth-result.ts
- Webhook:src/plugin-sdk/webhook-targets.ts、src/plugin-sdk/webhook-request-guards.ts、src/plugin-sdk/webhook-memory-guards.ts
- JSON 存储:src/plugin-sdk/json-store.ts
- 命令执行与临时路径:src/plugin-sdk/run-command.ts、src/plugin-sdk/temp-path.ts
- 文本分片:src/plugin-sdk/text-chunking.ts
- 参数解析:src/plugin-sdk/boolean-param.ts
- 请求 URL 解析:src/plugin-sdk/request-url.ts
- 配置辅助:src/plugin-sdk/channel-config-helpers.ts
- 状态构建:src/plugin-sdk/status-helpers.ts
- 入站信封与派发:src/plugin-sdk/inbound-envelope.ts、src/plugin-sdk/inbound-reply-dispatch.ts
- 出站媒体与负载:src/plugin-sdk/outbound-media.ts、src/plugin-sdk/reply-payload.ts
- 工具发送提取:src/plugin-sdk/tool-send.ts
- 认证与 SSRF 策略:src/plugin-sdk/fetch-auth.ts、src/plugin-sdk/ssrf-policy.ts
- 持久化去重:src/plugin-sdk/persistent-dedupe.ts
- 通用工具与队列辅助:src/utils.ts、src/utils/queue-helpers.ts
- 认证配置存储与刷新:src/agents/auth-profiles/store.ts、src/agents/auth-profiles/oauth.ts
- 扩展 OAuth 示例:extensions/google-gemini-cli-auth/oauth.ts、extensions/minimax-portal-auth/oauth.ts
graph TB
subgraph "插件SDK"
A["file-lock.ts"]
B["keyed-async-queue.ts"]
C["runtime-store.ts"]
D["oauth-utils.ts"]
E["provider-auth-result.ts"]
F["webhook-targets.ts"]
G["webhook-request-guards.ts"]
H["webhook-memory-guards.ts"]
I["json-store.ts"]
J["run-command.ts"]
K["temp-path.ts"]
L["text-chunking.ts"]
M["boolean-param.ts"]
N["request-url.ts"]
O["channel-config-helpers.ts"]
P["status-helpers.ts"]
Q["inbound-envelope.ts"]
R["inbound-reply-dispatch.ts"]
S["outbound-media.ts"]
T["reply-payload.ts"]
U["tool-send.ts"]
V["fetch-auth.ts"]
W["ssrf-policy.ts"]
X["persistent-dedupe.ts"]
Y["index.ts"]
end
subgraph "通用工具"
Z["utils.ts"]
AA["queue-helpers.ts"]
end
subgraph "认证存储"
BB["auth-profiles/store.ts"]
CC["auth-profiles/oauth.ts"]
end
subgraph "扩展OAuth示例"
DD["google-gemini-cli-auth/oauth.ts"]
EE["minimax-portal-auth/oauth.ts"]
end
Y --> A
Y --> B
Y --> C
Y --> D
Y --> E
Y --> F
Y --> G
Y --> H
Y --> I
Y --> J
Y --> K
Y --> L
Y --> M
Y --> N
Y --> O
Y --> P
Y --> Q
Y --> R
Y --> S
Y --> T
Y --> U
Y --> V
Y --> W
Y --> X
Y --> Z
Y --> AA
Y --> BB
Y --> CC
Y --> DD
Y --> EE
核心组件
- 文件锁管理:提供可重试、可过期的文件级互斥锁,支持持有计数与清理。
- 异步队列:按键串行化任务,保证同键并发安全与顺序执行。
- 运行时存储:为插件运行时提供轻量级键值存储封装。
- OAuth 工具:生成 PKCE 验证器、构建 OAuth 认证结果。
- Webhook 安全与限流:注册目标、鉴权、请求体读取、速率限制与异常追踪。
- JSON 存储:原子写入与回退读取,保障数据一致性。
- 命令执行与临时路径:带超时的命令执行与安全的临时文件路径生成。
- 文本分片:按字符边界安全切分长文本,避免 UTF-16 代理对截断。
- 参数解析与 URL 处理:布尔参数读取、规范化请求 URL。
- 配置与状态辅助:通道配置基座、运行时状态快照构建。
- 入站信封与派发:构建入站消息信封、派发回复。
- 出站媒体与负载:出站媒体加载、负载组装与分块发送。
- 工具发送提取:从消息中提取工具调用载荷。
- 认证与 SSRF 策略:作用域令牌获取与主机白名单策略。
- 持久化去重:基于持久化缓存的重复消息检测。
- 通用工具与队列辅助:路径、字符串、时间格式化、队列容量与丢弃策略等。
- 认证配置存储与刷新:认证存储的读写锁、合并与迁移、OAuth 刷新。
架构总览
下图展示插件 SDK 中“文件锁”“异步队列”“运行时存储”“OAuth 工具”“Webhook 安全”“JSON 存储”“命令执行与临时路径”“文本分片”“参数解析”“配置辅助”“状态构建”“入站信封与派发”“出站媒体与负载”“工具发送提取”“认证与 SSRF 策略”“持久化去重”以及“通用工具与队列辅助”的交互关系。
graph TB
FL["文件锁<br/>file-lock.ts"]
KA["异步队列<br/>keyed-async-queue.ts"]
RS["运行时存储<br/>runtime-store.ts"]
OU["OAuth 工具<br/>oauth-utils.ts"]
PAR["认证结果构建<br/>provider-auth-result.ts"]
WT["Webhook 目标<br/>webhook-targets.ts"]
WRG["Webhook 请求守卫<br/>webhook-request-guards.ts"]
WMG["Webhook 内存守卫<br/>webhook-memory-guards.ts"]
JS["JSON 存储<br/>json-store.ts"]
RC["命令执行<br/>run-command.ts"]
TP["临时路径<br/>temp-path.ts"]
TC["文本分片<br/>text-chunking.ts"]
BP["布尔参数<br/>boolean-param.ts"]
RU["请求URL<br/>request-url.ts"]
CCH["配置辅助<br/>channel-config-helpers.ts"]
SH["状态构建<br/>status-helpers.ts"]
IE["入站信封<br/>inbound-envelope.ts"]
IRD["入站派发<br/>inbound-reply-dispatch.ts"]
OM["出站媒体<br/>outbound-media.ts"]
RP["出站负载<br/>reply-payload.ts"]
TS["工具发送提取<br/>tool-send.ts"]
FA["认证作用域<br/>fetch-auth.ts"]
SP["SSRF 策略<br/>ssrf-policy.ts"]
PD["持久化去重<br/>persistent-dedupe.ts"]
UT["通用工具<br/>utils.ts"]
QH["队列辅助<br/>queue-helpers.ts"]
FL --> RS
KA --> RS
OU --> PAR
WT --> WRG
WRG --> WMG
JS --> RS
RC --> TP
TC --> RP
BP --> UT
RU --> UT
CCH --> SH
IE --> IRD
OM --> RP
TS --> UT
FA --> UT
SP --> UT
PD --> UT
UT --> QH
详细组件分析
文件锁管理(file-lock)
- 功能概述
- 提供可重试、指数退避与抖动的文件锁获取机制。
- 支持“陈旧锁”检测(进程不存在或超过存活时间)并自动清理。
- 持有计数与句柄复用,避免重复打开。
- 关键类型
- FileLockOptions:重试次数、倍率、最小/最大超时、是否随机抖动;陈旧时间阈值。
- FileLockHandle:包含锁路径与释放函数。
- 关键函数
- acquireFileLock(filePath, options):获取锁,内部处理重试与陈旧锁清理。
- withFileLock(filePath, options, fn):在锁保护下执行回调,确保 finally 释放。
- 使用场景
- 多进程/多实例对同一资源(如配置文件、会话文件)的互斥访问。
- 错误处理
- 超时抛出错误;陈旧锁自动清理后重试;最终失败抛出明确错误信息。
- 性能与内存
- 采用指数退避+抖动降低竞争冲突;持有计数减少频繁 IO;异常路径通过 finally 保证释放。
flowchart TD
Start(["进入 acquireFileLock"]) --> Normalize["标准化文件路径并创建 .lock"]
Normalize --> TryOpen{"尝试以独占方式打开 .lock"}
TryOpen --> |成功| WritePayload["写入 PID 与创建时间"]
WritePayload --> Hold["记录持有状态并返回句柄"]
TryOpen --> |失败且非 EEXIST| ThrowErr["抛出错误"]
TryOpen --> |EEXIST| Stale{"判断是否陈旧锁"}
Stale --> |是| RemoveLock["删除 .lock 并重试"]
Stale --> |否| RetryDelay["计算延迟并等待"]
RetryDelay --> Attempts{"剩余重试次数 > 0 ?"}
RemoveLock --> Attempts
Attempts --> |是| TryOpen
Attempts --> |否| Timeout["抛出超时错误"]
Hold --> End(["返回 FileLockHandle"])
异步队列(keyed-async-queue)
- 功能概述
- 按键维护“尾部 Promise”,确保同键任务串行执行,避免竞态。
- 支持钩子:入队与 settle 回调,便于统计与可观测性。
- 关键类型
- KeyedAsyncQueueHooks:onEnqueue、onSettle。
- KeyedAsyncQueue:封装 Map<string, Promise>。
- 关键函数
- enqueueKeyedTask:入队并返回当前任务 Promise。
- KeyedAsyncQueue.enqueue:面向对象封装。
- 使用场景
- 同一会话/账户的连续操作(如消息发送、状态更新)需要严格顺序。
- 错误处理
- 任一任务失败不影响后续任务入队;tail 清理在 finally 中完成。
- 性能与内存
- Map 存储 tail,避免堆积;任务完成后清理对应键,防止内存泄漏。
sequenceDiagram
participant Dev as "插件代码"
participant Q as "KeyedAsyncQueue"
participant Tail as "Map 尾Promise"
Dev->>Q : enqueue(key, task)
Q->>Tail : 获取或初始化尾Promise
Tail-->>Q : previous
Q->>Q : previous.catch().then(task).finally(onSettle)
Q->>Tail : 设置 tail = 当前任务Promise
Q-->>Dev : 返回当前任务Promise
Note over Tail,Q : 任务完成后清理键,避免内存泄漏
运行时存储(runtime-store)
- 功能概述
- 为插件运行时提供键值存储封装,便于跨模块共享状态。
- 使用场景
- 缓存插件上下文、会话元数据、中间结果等。
- 注意事项
- 仅适合进程内短期存储;持久化请使用 JSON 存储或文件锁保护的文件。
OAuth 工具(oauth-utils 与 provider-auth-result)
- 功能概述
- oauth-utils:生成 PKCE 验证器与表单编码。
- provider-auth-result:根据 provider 与凭据构建 ProviderAuthResult,含默认模型与配置补丁。
- 使用场景
- 插件完成 OAuth 授权后,将凭据注入到认证存储与配置中。
- 错误处理
- 认证结果需校验 providerId、access、refresh、expires 等字段完整性。
- 最佳实践
- 优先使用 provider-auth-result 统一构建认证结果,减少重复逻辑。
Webhook 安全与限流(webhook-targets、webhook-request-guards、webhook-memory-guards)
- 功能概述
- webhook-targets:注册目标、解析鉴权、同步/异步解析单个目标。
- webhook-request-guards:请求体读取、内容类型检查、并发/速率限制配置。
- webhook-memory-guards:限流器、异常追踪计数器、固定窗口计数器。
- 使用场景
- 插件接收外部 Webhook,需要鉴权、限流与异常监控。
- 错误处理
- 非 POST 请求直接拒绝;非法 Content-Type 抛错;请求体过大或读取失败抛出特定错误类型。
- 性能与内存
- 限流与异常计数器驻留内存,注意合理设置窗口与阈值,避免内存膨胀。
JSON 存储(json-store)
- 功能概述
- 原子写入与回退读取,避免部分写入导致的数据损坏。
- 使用场景
- 配置文件、认证存储、会话元数据等需要强一致性的 JSON 数据。
- 错误处理
- 写入失败回滚;读取失败返回默认值或 null。
命令执行与临时路径(run-command、temp-path)
- 功能概述
- run-command:带超时的命令执行,返回结果与退出码。
- temp-path:生成随机临时文件路径,支持 withTempDownloadPath 自动清理。
- 使用场景
- 下载远程资源、执行外部工具、生成临时输出。
- 错误处理
- 超时、非零退出码、IO 错误均需捕获并上报。
文本分片(text-chunking)
- 功能概述
- 按 UTF-16 边界安全切分文本,避免代理对被截断。
- 使用场景
- 出站消息长度受限时的分段发送。
- 性能与内存
- 切片过程中避免复制大块文本;合理设置分片大小。
参数解析与 URL 处理(boolean-param、request-url)
- 功能概述
- boolean-param:读取布尔参数,支持多种输入形式。
- request-url:规范化请求 URL,便于路由与鉴权。
- 使用场景
- Webhook 或 HTTP 路由参数解析、URL 规范化。
配置与状态辅助(channel-config-helpers、status-helpers)
- 功能概述
- channel-config-helpers:通道配置基座、允许列表映射、格式化等。
- status-helpers:构建运行时账户/通道状态快照与汇总。
- 使用场景
- 插件在启动或运行时收集与展示状态信息。
入站信封与派发(inbound-envelope、inbound-reply-dispatch)
- 功能概述
- inbound-envelope:构建入站消息信封,抽取必要上下文。
- inbound-reply-dispatch:根据配置派发回复,记录会话。
- 使用场景
- 插件接收外部消息后的统一处理入口。
出站媒体与负载(outbound-media、reply-payload)
- 功能概述
- outbound-media:从 URL 加载出站媒体。
- reply-payload:组装出站负载,支持分块文本与媒体、前置标题等。
- 使用场景
- 发送富媒体消息、带附件的回复。
工具发送提取(tool-send)
- 功能概述
- 从消息中提取工具调用载荷,便于插件侧处理工具链。
- 使用场景
- 基于用户指令触发工具调用。
认证与 SSRF 策略(fetch-auth、ssrf-policy)
- 功能概述
- fetch-auth:作用域令牌提供者与降级回退。
- ssrf-policy:主机名后缀白名单策略,判定 HTTPS URL 是否允许。
- 使用场景
- HTTP 请求时注入认证头与限制私网访问。
持久化去重(persistent-dedupe)
- 功能概述
- 基于持久化缓存的重复消息检测,避免重复处理。
- 使用场景
- Webhook 或消息流中的幂等处理。
通用工具与队列辅助(utils、queue-helpers)
- 功能概述
- utils:路径、字符串、时间格式化、睡眠、正则转义、JSON 安全解析等。
- queue-helpers:队列容量控制、丢弃策略、防抖、摘要提示、跨通道检测等。
- 使用场景
- 日志、路径显示、字符串处理、队列节流与溢出摘要。
认证配置存储与刷新(auth-profiles/store、auth-profiles/oauth)
- 功能概述
- store:认证存储的加载、保存、合并、迁移与只读运行时视图。
- oauth:OAuth 凭据刷新与健康度评估。
- 使用场景
- 插件在运行时读取/更新认证配置,或在首次调用时自动刷新。
- 错误处理
- 陈旧锁与文件 IO 异常需捕获;认证条目不合法时记录警告并跳过。
扩展 OAuth 示例(google-gemini-cli-auth、minimax-portal-auth)
- 功能概述
- google-gemini-cli-auth:本地回调等待授权码,构造 OAuth 流程。
- minimax-portal-auth:轮询授权状态,动态调整轮询间隔,超时处理。
- 使用场景
- 插件实现自定义 OAuth 登录流程。
依赖关系分析
- 入口导出
- src/plugin-sdk/index.ts 将各工具模块统一导出,形成插件 SDK 的“门面”,便于按需引入。
- 模块耦合
- 文件锁与运行时存储:文件锁用于保护运行时存储的并发写入。
- 异步队列与 Webhook:队列保证同键 Webhook 处理顺序;守卫与限流保障稳定性。
- JSON 存储与认证存储:认证存储在写入时使用 JSON 存储与文件锁。
- 工具函数与业务模块:utils 与 queue-helpers 被广泛用于路径、字符串、队列处理等。
- 循环依赖
- 未发现直接循环依赖;各模块通过入口导出与类型约束保持清晰边界。
graph LR
IDX["index.ts 导出"] --> FL["file-lock.ts"]
IDX --> KA["keyed-async-queue.ts"]
IDX --> RS["runtime-store.ts"]
IDX --> OU["oauth-utils.ts"]
IDX --> PAR["provider-auth-result.ts"]
IDX --> WT["webhook-targets.ts"]
IDX --> WRG["webhook-request-guards.ts"]
IDX --> WMG["webhook-memory-guards.ts"]
IDX --> JS["json-store.ts"]
IDX --> RC["run-command.ts"]
IDX --> TP["temp-path.ts"]
IDX --> TC["text-chunking.ts"]
IDX --> BP["boolean-param.ts"]
IDX --> RU["request-url.ts"]
IDX --> CCH["channel-config-helpers.ts"]
IDX --> SH["status-helpers.ts"]
IDX --> IE["inbound-envelope.ts"]
IDX --> IRD["inbound-reply-dispatch.ts"]
IDX --> OM["outbound-media.ts"]
IDX --> RP["reply-payload.ts"]
IDX --> TS["tool-send.ts"]
IDX --> FA["fetch-auth.ts"]
IDX --> SP["ssrf-policy.ts"]
IDX --> PD["persistent-dedupe.ts"]
IDX --> UT["utils.ts"]
IDX --> QH["queue-helpers.ts"]
IDX --> BB["auth-profiles/store.ts"]
IDX --> CC["auth-profiles/oauth.ts"]
IDX --> DD["google-gemini-cli-auth/oauth.ts"]
IDX --> EE["minimax-portal-auth/oauth.ts"]
性能考量
- 文件锁
- 指数退避+抖动降低热点竞争;持有计数减少 IO;建议合理设置陈旧阈值与重试上限。
- 异步队列
- 同键串行化避免竞态;tail 清理防止内存泄漏;建议为高频键设置合理的超时与重试策略。
- Webhook
- 固定窗口限流与异常计数器需结合业务流量设定;请求体大小与读取超时应与上游协商。
- JSON 存储
- 原子写入减少碎片;大文件建议分块或外部存储;定期清理无效键。
- 文本分片
- 避免在代理对边界处截断;分片大小与编码方式需匹配下游限制。
- 认证存储
- 写入使用文件锁;合并与迁移尽量在空闲时段执行;只读运行时视图减少写放大。
配置模式 API
配置模式 API 在项目中的组织结构如下:
graph TB
subgraph "配置模式核心"
A[src/config/schema.ts] --> B[配置模式构建器]
A --> C[配置模式验证器]
A --> D[配置模式合并器]
end
subgraph "插件 SDK"
E[src/plugin-sdk/index.ts] --> F[emptyPluginConfigSchema]
E --> G[buildChannelConfigSchema]
E --> H[配置模式导出]
end
subgraph "插件实现"
I[extensions/discord/src/channel.ts] --> J[Discord配置]
K[extensions/feishu/src/config-schema.ts] --> L[飞书配置]
M[extensions/bluebubbles/src/config-schema.ts] --> N[iMessage配置]
end
subgraph "协议定义"
O[src/gateway/protocol/schema/config.ts] --> P[配置协议]
Q[src/channels/plugins/config-schema.test.ts] --> R[测试用例]
end
A --> E
E --> I
E --> K
E --> M
核心组件
配置模式响应对象
配置模式 API 的核心输出是一个结构化的响应对象,包含以下关键属性:
classDiagram
class ConfigSchemaResponse {
+schema : ConfigSchema
+uiHints : ConfigUiHints
+version : string
+generatedAt : string
}
class ConfigSchema {
+type : string
+properties : Record
+required : string[]
+additionalProperties : boolean
}
class ConfigUiHints {
+[key : string] : ConfigUiHint
}
class ConfigUiHint {
+label : string
+help : string
+tags : string[]
+advanced : boolean
+sensitive : boolean
+placeholder : string
}
ConfigSchemaResponse --> ConfigSchema
ConfigSchemaResponse --> ConfigUiHints
ConfigUiHints --> ConfigUiHint
配置模式构建函数
配置模式 API 提供了多个核心构建函数:
- emptyPluginConfigSchema: 创建空的插件配置模式
- buildChannelConfigSchema: 构建通道配置模式
- buildConfigSchema: 主要的配置模式构建入口
架构概览
配置模式 API 采用分层架构设计,确保了模块间的松耦合和高内聚:
sequenceDiagram
participant Plugin as 插件开发者
participant SDK as 插件SDK
participant Builder as 配置构建器
participant Validator as 验证器
participant UI as UI系统
Plugin->>SDK : 定义配置模式
SDK->>Builder : 调用构建函数
Builder->>Builder : 合并基础配置
Builder->>Validator : 应用验证规则
Validator->>UI : 生成UI提示
UI->>Plugin : 返回完整配置模式
Note over Plugin,UI : 支持动态更新和版本兼容
详细组件分析
emptyPluginConfigSchema 组件
emptyPluginConfigSchema 是一个专门用于创建空插件配置模式的构建函数。它为插件开发者提供了一个基础的配置框架,允许插件在需要时扩展配置选项。
实现特点
- 基础配置结构: 提供标准的插件配置基础结构
- 可扩展性: 允许插件在基础上添加自定义配置项
- 类型安全: 通过 TypeScript 类型系统确保配置的正确性
使用场景
flowchart TD
A[插件初始化] --> B[调用 emptyPluginConfigSchema]
B --> C[获得基础配置模式]
C --> D[插件添加自定义配置]
D --> E[返回完整配置模式]
F[配置验证] --> G[类型检查]
G --> H[默认值应用]
H --> I[返回验证结果]
buildChannelConfigSchema 组件
buildChannelConfigSchema 是构建通道配置模式的核心函数,专门为不同通信渠道(如 Discord、飞书等)提供配置支持。
核心功能
- Zod Schema 支持: 原生支持 Zod 配置模式
- 向后兼容: 兼容旧版本的 Zod 模式(v3)
- Draft-07 兼容: 自动应用 Draft-07 规范
- 错误处理: 提供完善的错误处理机制
配置模式示例
以 Discord 通道为例,展示配置模式的构建过程:
classDiagram
class DiscordConfigSchema {
+enabled : boolean
+token : SecretInput
+defaultAccount : string
+accounts : Record~string, AccountConfig~
}
class AccountConfig {
+enabled : boolean
+name : string
+dmPolicy : DmPolicy
+groupPolicy : GroupPolicy
+allowFrom : string[]
}
class ChannelConfig {
+discord : DiscordConfigSchema
}
DiscordConfigSchema --> AccountConfig
ChannelConfig --> DiscordConfigSchema
配置模式合并器
配置模式合并器负责将多个配置模式合并为一个统一的配置结构:
flowchart LR
A[基础配置] --> C[合并器]
B[插件配置] --> C
C --> D[通道配置]
D --> E[最终配置模式]
F[UI提示] --> G[敏感信息标记]
G --> H[派生标签应用]
H --> I[最终响应]
配置模式验证器
配置模式验证器确保所有配置都符合预定义的规则和约束:
flowchart TD
A[输入配置] --> B[类型验证]
B --> C{验证通过?}
C --> |是| D[应用默认值]
C --> |否| E[返回错误]
D --> F[应用敏感信息标记]
F --> G[生成UI提示]
G --> H[返回验证结果]
I[缓存检查] --> J[缓存命中?]
J --> |是| H
J --> |否| A
依赖关系分析
配置模式 API 的依赖关系体现了清晰的分层架构:
graph TB
subgraph "外部依赖"
A[Zod Schema]
B[TypeBox]
C[JSON Schema]
end
subgraph "核心模块"
D[配置模式构建器]
E[配置验证器]
F[配置合并器]
G[UI提示处理器]
end
subgraph "插件接口"
H[emptyPluginConfigSchema]
I[buildChannelConfigSchema]
J[配置模式导出]
end
subgraph "插件实现"
K[Discord插件]
L[飞书插件]
M[iMessage插件]
end
A --> D
B --> E
C --> F
D --> G
E --> H
F --> I
G --> J
H --> K
I --> L
J --> M
性能考虑
配置模式 API 在设计时充分考虑了性能优化:
缓存策略
- 基础配置缓存: 缓存基础配置模式以避免重复计算
- 合并结果缓存: 使用哈希键缓存合并后的配置结果
- 缓存大小限制: 最大缓存数量限制为 64 个条目
内存优化
- 结构化克隆: 使用
structuredClone进行深拷贝 - 增量哈希计算: 避免创建巨大的 JSON 字符串进行哈希
- 按需加载: 只在需要时构建和验证配置模式
并发处理
- 异步操作: 支持异步配置模式构建
- 并发安全: 缓存操作具有线程安全保证
- 资源清理: 自动清理最旧的缓存条目
渠道适配器 API
OpenClaw 将渠道适配器能力抽象为一组核心类型与加载机制:
- 类型与接口:在 channels/plugins/types.* 中集中导出,包含适配器接口、核心数据模型与上下文类型。
- 加载与缓存:通过 registry-loader 提供按 ChannelId 的适配器解析与缓存,避免重复加载。
- 出站专用加载:针对“仅需发送能力”的场景,提供轻量级 outbound 适配器加载入口。
- 扩展与示例:各渠道扩展(如 bluebubbles)提供配置类型与工具函数,作为实现参考。
graph TB
subgraph "渠道插件层"
T["types.ts<br/>导出适配器与核心类型"]
RA["registry-loader.ts<br/>按 ChannelId 解析适配器"]
OL["outbound/load.ts<br/>轻量级出站适配器加载"]
end
subgraph "运行时"
RT["运行时注册表<br/>getActivePluginRegistry()"]
CACHE["适配器缓存<br/>Map<ChannelId, 实例>"]
end
subgraph "扩展示例"
BB["bluebubbles/types.ts<br/>配置与工具函数"]
end
T --> RA
RA --> RT
RA --> CACHE
OL --> RA
BB --> T
核心组件
本节对关键适配器与核心类型进行分层说明,帮助开发者快速定位职责边界与使用方式。
-
适配器接口族
- ChannelMessagingAdapter:负责消息的接收与处理(拉取、解析、路由、回执等)。
- ChannelOutboundAdapter:负责消息的发送(分片、附件、目标选择、流式支持等)。
- ChannelResolverAdapter:负责将“用户/群组标识”解析为可路由的目标对象。
- 其他常用适配器:ChannelAuthAdapter、ChannelConfigAdapter、ChannelSetupAdapter、ChannelStatusAdapter、ChannelHeartbeatAdapter、ChannelPairingAdapter、ChannelSecurityAdapter、ChannelElevatedAdapter、ChannelGatewayAdapter、ChannelGroupAdapter、ChannelThreadingAdapter、ChannelStreamingAdapter、ChannelAgentPromptAdapter、ChannelMessageActionAdapter、ChannelMentionAdapter 等。
-
核心数据模型
- ChannelId:渠道唯一标识。
- ChannelMeta:渠道元信息。
- ChannelOutboundContext/ChannelPollContext:发送与轮询上下文。
- ChannelResolveKind/ChannelResolveResult:解析结果与类型。
- ChannelAccountSnapshot/ChannelAccountState:账户快照与状态。
- ChannelCapabilities:渠道能力标签集合。
- ChannelOutboundTargetMode:发送目标模式(如单聊、群聊、多目标)。
- ChannelPollResult:轮询结果(消息列表、状态、下一次轮询时间等)。
- ChannelMessageActionName/ChannelMessageActionContext:消息动作名称与上下文。
- ChannelToolSend:工具调用发送封装。
- ChannelDirectoryEntry/ChannelDirectoryEntryKind:目录条目与类型。
- ChannelSecurityContext/ChannelSecurityDmPolicy:安全上下文与私信策略。
- ChannelLoginWithQrStartResult/ChannelLoginWithQrWaitResult:二维码登录流程结果。
- ChannelLogoutContext/ChannelLogoutResult:登出上下文与结果。
- ChannelSetupInput:安装/初始化输入。
- ChannelStatusIssue:状态问题描述。
- ChannelThreadingContext/ChannelThreadingToolContext:线程上下文与工具上下文。
- ChannelAgentTool/ChannelAgentToolFactory:代理工具与工厂。
- ChannelLogSink:日志输出目标。
- BaseProbeResult/BaseTokenResolution:探测与令牌解析基础结构。
-
关键加载与缓存
- createChannelRegistryLoader:通用适配器解析器,支持缓存与运行时注册表切换。
- loadChannelOutboundAdapter:轻量级出站适配器加载入口,避免导入链路冗余。
架构总览
下图展示渠道适配器在运行时的加载与调用关系,以及与扩展的关系。
sequenceDiagram
participant Dev as "渠道开发者"
participant Types as "types.ts"
participant Loader as "registry-loader.ts"
participant Runtime as "运行时注册表"
participant Cache as "适配器缓存"
participant Ext as "扩展(如 bluebubbles)"
Dev->>Types : 引入适配器接口与核心类型
Dev->>Loader : 调用 createChannelRegistryLoader(...)
Loader->>Runtime : 获取活动注册表
Loader->>Cache : 命中缓存?
alt 命中
Cache-->>Loader : 返回适配器实例
else 未命中
Loader->>Runtime : 查找匹配的插件注册项
Loader->>Ext : 读取插件导出的适配器
Loader->>Cache : 写入缓存
Ext-->>Loader : 返回适配器实例
end
Loader-->>Dev : 返回适配器实例
详细组件分析
ChannelMessagingAdapter(消息收发)
- 职责
- 拉取新消息并转换为统一的消息模型。
- 处理消息动作(回复、编辑、删除、反应等)。
- 维护会话上下文与历史限制。
- 可选:支持流式响应与合并块回复。
- 方法与参数要点(示意)
- 轮询/拉取:传入 ChannelPollContext,返回 ChannelPollResult;包含消息数组、下次轮询时间、状态标记。
- 动作处理:传入 ChannelMessageActionContext,包含动作名与上下文数据,返回处理结果或错误。
- 回执/已读:根据渠道能力决定是否发送已读回执。
- 返回格式
- ChannelPollResult:包含消息列表、状态码、下一次轮询时间等。
- 动作处理返回:布尔或带错误信息的对象。
- 错误处理
- 对网络超时、鉴权失败、渠道限流等进行分类处理与重试策略。
- 对不可恢复错误(如无效凭据)应返回明确错误并触发登出流程。
- 性能优化
- 合理设置轮询间隔与批量大小。
- 使用增量拉取与本地去重,减少重复消息处理。
- 流式响应合并(blockStreamingCoalesce)降低往返次数。
ChannelOutboundAdapter(出站发送)
- 职责
- 将统一消息模型转换为渠道特定格式。
- 支持文本分片(按长度或换行)、附件上传、目标选择与多目标广播。
- 支持流式发送与合并块回复。
- 方法与参数要点(示意)
- 发送:传入 ChannelOutboundContext,包含目标、内容、附件、流式标志等;返回发送结果或错误。
- 分片策略:按字符数或换行符切分;控制媒体最大尺寸与本地路径根目录白名单。
- 目标模式:单聊、群聊、多目标;支持 handle/chat_id/chat_guid/chat_identifier 等多种解析目标。
- 返回格式
- 发送结果:包含消息 ID、发送状态、失败原因等。
- 错误:标准化错误对象,包含错误码与可读提示。
- 错误处理
- 对网络异常、配额不足、媒体不合规等情况进行降级与重试。
- 对目标不存在或无权限等错误,返回明确错误并记录上下文。
- 性能优化
- 并发发送队列与背压控制。
- 本地路径校验与媒体压缩策略。
- 合并小块流式回复以减少 API 调用。
flowchart TD
Start(["开始发送"]) --> BuildCtx["构建 ChannelOutboundContext"]
BuildCtx --> Shard["按策略分片文本"]
Shard --> Attach["处理附件与媒体校验"]
Attach --> Target["解析目标模式"]
Target --> Send["调用渠道发送接口"]
Send --> Result{"发送成功?"}
Result --> |是| Done["返回发送结果"]
Result --> |否| Retry["重试/降级/记录错误"]
Retry --> Done
ChannelResolverAdapter(解析器)
- 职责
- 将用户/群组标识解析为渠道内部可识别的实体。
- 支持多种解析类型(handle、chat_id、chat_guid、chat_identifier 等)。
- 方法与参数要点(示意)
- 解析:传入 ChannelResolveKind 与标识,返回 ChannelResolveResult。
- 结果:包含解析到的实体信息、是否成功、可选的错误信息。
- 返回格式
- 成功:包含目标实体的必要字段(如 id、guid、identifier)。
- 失败:标准化错误对象,包含原因与建议。
- 错误处理
- 对未知标识、权限不足、渠道不支持等情况进行区分处理。
- 性能优化
- 缓存解析结果,避免重复查询。
- 批量解析以减少往返。
classDiagram
class ChannelResolverAdapter {
+resolve(kind, identifier) ChannelResolveResult
}
class ChannelResolveKind {
+CHAT_ID
+CHAT_GUID
+CHAT_IDENTIFIER
+HANDLE
}
class ChannelResolveResult {
+success : boolean
+entity : any
+error? : string
}
ChannelResolverAdapter --> ChannelResolveKind : "使用"
ChannelResolverAdapter --> ChannelResolveResult : "返回"
ChannelAuthAdapter(鉴权)
- 职责
- 管理渠道登录态、刷新令牌、二维码登录、登出等。
- 方法与参数要点(示意)
- 登录:支持账号密码、二维码登录、令牌登录等。
- 刷新:自动刷新过期令牌。
- 登出:清理会话与本地存储。
- 返回格式
- 登录结果:包含会话信息、二维码等待结果等。
- 登出结果:包含清理状态与错误信息。
ChannelConfigAdapter(配置)
- 职责
- 管理渠道配置读写、默认值、能力标签、策略开关等。
- 方法与参数要点(示意)
- 读取:获取当前配置与能力标签。
- 写入:允许/禁止配置写入(受策略控制)。
- 返回格式
- 配置对象:包含能力、策略、分片参数、媒体限制等。
- 写入结果:布尔或错误对象。
ChannelSetupAdapter(安装/初始化)
- 职责
- 完成渠道首次安装与初始化,收集必要参数(如服务器地址、Webhook 路径等)。
- 方法与参数要点(示意)
- 输入:ChannelSetupInput(包含服务器地址、认证信息、策略等)。
- 输出:初始化结果与后续步骤指引。
- 返回格式
- 初始化结果:包含状态、下一步操作、错误信息。
ChannelStatusAdapter(状态)
- 职责
- 上报渠道健康状态、诊断问题、生成状态报告。
- 方法与参数要点(示意)
- 轮询:定期检查连接、鉴权、配额等。
- 报告:返回 ChannelStatusIssue 列表与修复建议。
- 返回格式
- 状态:包含健康度、最近问题、修复建议。
ChannelHeartbeatAdapter(心跳)
- 职责
- 维持长连接或定时心跳,检测连接存活。
- 方法与参数要点(示意)
- 心跳:周期性发送心跳包。
- 失败:触发重连或上报状态。
ChannelPairingAdapter(配对)
- 职责
- 管理设备/账号配对流程,支持二维码配对与配对状态监控。
- 方法与参数要点(示意)
- 开始配对:返回二维码起始结果。
- 等待配对:轮询配对状态直至完成。
- 返回格式
- 二维码起始结果:包含二维码数据与等待参数。
- 等待结果:包含配对成功/失败与错误信息。
ChannelSecurityAdapter(安全)
- 职责
- 管理私信策略、白名单、访问控制、敏感操作审计等。
- 方法与参数要点(示意)
- 策略:私信策略(如仅配对用户、允许列表)。
- 白名单:允许来源与目标的过滤。
- 返回格式
- 策略评估结果:允许/拒绝与原因。
ChannelElevatedAdapter(提升权限)
- 职责
- 在受限环境(沙箱)中申请提升权限,执行高权限操作。
- 方法与参数要点(示意)
- 权限申请:提交权限清单与用途说明。
- 结果:返回授权状态与错误信息。
ChannelGatewayAdapter(网关)
- 职责
- 与网关通信,注册回调、转发事件、同步状态。
- 方法与参数要点(示意)
- 注册:注册回调与事件类型。
- 转发:将渠道事件转发至网关。
- 返回格式
- 注册结果:成功/失败与错误信息。
ChannelGroupAdapter(群组)
- 职责
- 管理群组成员、邀请、踢人、改名等群组操作。
- 方法与参数要点(示意)
- 成员管理:添加/移除成员。
- 属性修改:修改群组名称与描述。
- 返回格式
- 操作结果:成功/失败与错误信息。
ChannelThreadingAdapter(线程)
- 职责
- 管理消息线程、子话题、上下文继承等。
- 方法与参数要点(示意)
- 创建线程:基于消息创建子线程。
- 上下文:继承父消息的上下文与历史。
- 返回格式
- 线程上下文:包含线程 ID、上下文数据。
ChannelStreamingAdapter(流式)
- 职责
- 支持流式响应与块合并,提升交互体验。
- 方法与参数要点(示意)
- 流式发送:分块发送响应并合并。
- 合并策略:按渠道能力与性能调整。
- 返回格式
- 流式结果:包含块序列与最终合并结果。
ChannelAgentPromptAdapter(代理提示)
- 职责
- 提供渠道特定的代理提示词模板与上下文注入。
- 方法与参数要点(示意)
- 模板:返回提示词模板与变量映射。
- 注入:将上下文注入模板并生成最终提示。
- 返回格式
- 提示结果:字符串或结构化提示对象。
ChannelMessageActionAdapter(消息动作)
- 职责
- 处理消息动作(回复、编辑、删除、反应等)。
- 方法与参数要点(示意)
- 动作:根据动作名与上下文执行相应操作。
- 上下文:包含消息 ID、动作参数、目标等。
- 返回格式
- 动作结果:成功/失败与错误信息。
ChannelMentionAdapter(提及)
- 职责
- 处理消息中的提及(@某人),生成提及标记与解析。
- 方法与参数要点(示意)
- 生成:将用户名映射为渠道特定的提及标记。
- 解析:从消息中提取提及并解析为用户标识。
- 返回格式
- 提及结果:包含标记与用户列表。
依赖关系分析
- 适配器接口与核心类型由 types.ts 统一导出,便于跨模块引用。
- registry-loader.ts 通过运行时注册表解析插件导出的适配器,并维护缓存。
- outbound/load.ts 专门用于加载出站适配器,避免导入链路冗余。
- 扩展示例(如 bluebubbles)提供配置类型与工具函数,作为实现参考。
graph LR
Types["types.ts"] --> Adapters["适配器接口定义"]
Types --> Core["核心类型定义"]
Registry["registry-loader.ts"] --> Runtime["运行时注册表"]
Registry --> Cache["适配器缓存"]
Outbound["outbound/load.ts"] --> Registry
Blue["bluebubbles/types.ts"] --> Types
性能考虑
- 缓存与复用
- 使用 registry-loader 的缓存机制,避免重复解析与实例化。
- 对解析器、状态检查、配置读取等高频操作进行缓存。
- 并发与背压
- 出站发送采用并发队列与背压控制,防止渠道限流与资源耗尽。
- 合理设置分片大小与批量发送数量。
- 网络与超时
- 为网络请求设置合理超时与重试策略,区分瞬时错误与永久错误。
- 对长连接或心跳进行指数退避与自动重连。
- 资源与安全
- 严格校验本地媒体路径与大小,避免越权访问与资源滥用。
- 对敏感操作(如删除、踢人)增加二次确认与审计日志。
Webhook HTTP API
Webhook HTTP API 的实现分布在多个模块中:
graph TB
subgraph "核心SDK层"
A[webhook-targets.ts<br/>目标注册与解析]
B[webhook-request-guards.ts<br/>请求守卫与限流]
C[webhook-path.ts<br/>路径规范化]
D[webhook-memory-guards.ts<br/>内存级防护]
end
subgraph "插件集成层"
E[http-registry.ts<br/>HTTP路由注册]
F[monitor.webhook.ts<br/>Zalo集成]
G[webhook.ts<br/>语音通话集成]
H[webhook-security.ts<br/>安全验证]
end
subgraph "扩展实现层"
I[webhook-handler.ts<br/>Synology Chat]
J[monitor.ts<br/>Nextcloud Talk]
K[webhooks-cli.ts<br/>命令行工具]
end
A --> E
B --> A
C --> A
D --> B
E --> F
E --> G
H --> G
I --> A
J --> A
核心组件
Webhook 目标管理系统
Webhook 目标管理系统负责管理所有已注册的 webhook 目标,提供统一的注册、注销和查找功能。
classDiagram
class RegisteredWebhookTarget {
+target : T
+unregister() : void
}
class RegisterWebhookTargetOptions {
+onFirstPathTarget? : Function
+onLastPathTargetRemoved? : Function
}
class WebhookTargetMatchResult {
<<enumeration>>
+none
+single
+ambiguous
}
class WebhookInFlightLimiter {
+tryAcquire(key) : boolean
+release(key) : void
+size() : number
+clear() : void
}
RegisteredWebhookTarget --> WebhookTargetMatchResult
WebhookInFlightLimiter --> RegisteredWebhookTarget
请求处理管道
请求处理管道提供了完整的 webhook 请求生命周期管理,包括验证、限流、认证和处理流程。
sequenceDiagram
participant Client as 客户端
participant Pipeline as 处理管道
participant Guards as 守卫检查
participant Limiter as 限流器
participant Handler as 业务处理器
Client->>Pipeline : POST 请求
Pipeline->>Guards : 基础验证
Guards->>Guards : 方法检查
Guards->>Guards : 内容类型检查
Guards->>Guards : 速率限制检查
Guards-->>Pipeline : 验证结果
alt 验证通过
Pipeline->>Limiter : 获取并发许可
Limiter-->>Pipeline : 许可结果
alt 许可获取成功
Pipeline->>Handler : 处理业务逻辑
Handler-->>Pipeline : 处理完成
Pipeline->>Limiter : 释放许可
else 许可获取失败
Pipeline-->>Client : 429 Too Many Requests
end
else 验证失败
Pipeline-->>Client : 错误响应
end
架构概览
Webhook HTTP API 采用分层架构设计,确保了系统的可扩展性和安全性:
graph TB
subgraph "外部接口层"
A[HTTP客户端]
B[Webhook提供商]
end
subgraph "路由管理层"
C[HTTP路由注册器]
D[路径规范化器]
E[目标匹配器]
end
subgraph "安全防护层"
F[速率限制器]
G[并发限制器]
H[内容类型验证]
I[认证验证器]
end
subgraph "业务处理层"
J[请求解析器]
K[业务处理器]
L[响应生成器]
end
subgraph "监控告警层"
M[异常追踪器]
N[状态计数器]
O[日志记录器]
end
A --> C
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
H --> I
I --> J
J --> K
K --> L
L --> M
M --> N
N --> O
详细组件分析
注册系统
registerWebhookTarget
注册 webhook 目标的核心函数,负责将目标添加到路径映射表中,并处理首次和最后目标的清理工作。
flowchart TD
A[调用 registerWebhookTarget] --> B[规范化路径]
B --> C{是否为首个目标?}
C --> |是| D[执行首次目标回调]
C --> |否| E[直接添加到映射表]
D --> F[更新映射表]
E --> F
F --> G[返回 RegisteredWebhookTarget]
G --> H[提供注销功能]
registerWebhookTargetWithPluginRoute
结合插件路由注册的高级注册函数,自动管理 HTTP 路由的创建和销毁。
请求处理流程
withResolvedWebhookRequestPipeline
完整的请求处理管道,封装了从请求接收到底层业务处理的所有步骤。
sequenceDiagram
participant Req as 请求对象
participant Resolver as 解析器
participant Pipeline as 管道
participant Handler as 处理器
Req->>Resolver : 解析目标路径
Resolver->>Pipeline : 创建处理上下文
Pipeline->>Pipeline : 应用基础守卫
Pipeline->>Pipeline : 检查并发限制
Pipeline->>Handler : 调用业务处理
Handler-->>Pipeline : 返回处理结果
Pipeline->>Pipeline : 释放资源
认证与安全
认证机制实现
不同的 webhook 提供商采用了相应的认证策略:
| 提供商 | 认证方式 | 安全特性 |
|---|---|---|
| Zalo | 令牌对比 | 时间安全比较、重放攻击防护 |
| Twilio | HMAC-SHA1签名 | 时间戳验证、重放缓存 |
| Nextcloud Talk | 签名头验证 | 双重签名验证、后端白名单 |
| Synology Chat | Bearer令牌 | 多源令牌解析 |
限流与防护
速率限制器
classDiagram
class FixedWindowRateLimiter {
+windowMs : number
+maxRequests : number
+maxTrackedKeys : number
+isRateLimited(key, nowMs) : boolean
+size() : number
+clear() : void
}
class WebhookInFlightLimiter {
+maxInFlightPerKey : number
+maxTrackedKeys : number
+tryAcquire(key) : boolean
+release(key) : void
+size() : number
+clear() : void
}
class BoundedCounter {
+maxTrackedKeys : number
+ttlMs : number
+increment(key, nowMs) : number
+size() : number
+clear() : void
}
FixedWindowRateLimiter --> BoundedCounter
WebhookInFlightLimiter --> BoundedCounter
路径规范化
路径规范化确保了 webhook URL 的一致性和正确性:
flowchart TD
A[原始路径输入] --> B[去除首尾空白]
B --> C{是否为空?}
C --> |是| D[/ 默认根路径]
C --> |否| E{是否以/开头?}
E --> |否| F[添加前缀/]
E --> |是| G{是否以/结尾且非根路径?}
F --> G
G --> |是| H[移除末尾/]
G --> |否| I[保持原样]
H --> J[规范化完成]
I --> J
D --> J
依赖关系分析
Webhook HTTP API 的依赖关系体现了清晰的分层架构:
graph TB
subgraph "外部依赖"
A[node:http 模块]
B[crypto 模块]
C[URL 解析]
end
subgraph "内部核心"
D[webhook-targets]
E[webhook-request-guards]
F[webhook-path]
G[webhook-memory-guards]
end
subgraph "插件系统"
H[http-registry]
I[plugin-runtime]
J[plugin-registry]
end
subgraph "扩展实现"
K[zalo-monitor]
L[voice-call-server]
M[synology-chat-handler]
N[nextcloud-talk-monitor]
end
A --> D
B --> E
C --> F
D --> H
E --> G
H --> I
I --> J
H --> K
H --> L
H --> M
H --> N