Channel 系统概览
Channel 系统是 Elftia 的多平台消息接入层,负责将外部平台(Discord、Telegram、Slack 等)的消息接入到 Agent 处理管线中,并将回复路由回原始平台。
架构总览
graph TB
subgraph 外部平台
D[Discord]
T[Telegram]
S[Slack]
O[其他平台...]
end
subgraph Channel Plugin Layer
PL[ChannelPluginLoader<br/>插件发现与加载]
PR[ChannelPluginRegistry<br/>实例管理与事件分发]
end
subgraph Message Pipeline
MR[ChannelMessageRouter<br/>安全管线 + 触发匹配]
end
subgraph Security Pipeline
RL[RateLimiter]
IS[InputSanitizer]
PG[PromptGuardian]
UP[UserPermissionService]
CG[ChannelPermissionGate]
end
subgraph Agent Layer
MB[ChannelMagiBridge<br/>消息格式转换]
MS[MagiService<br/>Agent 处理]
end
D & T & S & O --> PR
PL --> PR
PR -->|message event| MR
MR --> RL --> IS --> PG --> UP --> CG
MR -->|routeToAgent event| MB
MB --> MS
MS -->|response| MB
MB -->|sendResponse| MR
MR -->|sendMessage| PR
PR --> D & T & S & O
关键文件索引
| 文件 | 路径 | 职责 |
|---|---|---|
| ChannelPluginLoader | desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.ts | 发现、验证、加载插件(双目录) |
| ChannelPluginRegistry | desktop/app/main/services/capabilities/integrations/channel/ChannelPluginRegistry.ts | 管理插件工厂和 Channel 实例的生命周期 |
| ChannelMessageRouter | desktop/app/main/services/capabilities/integrations/channel/ChannelMessageRouter.ts | 安全管线、触发匹配、消息缓冲、响应分片 |
| ChannelMagiBridge | desktop/app/main/services/agent-core/magi/ChannelMagiBridge.ts | Channel 消息 → MagiIncomingMessage 转换 |
| ChannelMarketplaceService | desktop/app/main/services/capabilities/integrations/channel/ChannelMarketplaceService.ts | CDN 清单获取、插件下载安装 |
| ChannelPluginRouter | desktop/app/main/services/routers/ChannelPluginRouter.ts | IPC 路由处理(前端 ↔ 后端) |
| channel-sdk | packages/channel-sdk/src/ | 插件开发 SDK(类型、接口) |
| channel-types | desktop/app/shared/contracts/channel-types.ts | 统一 Channel 类型定义 |
| channel-sdk (re-export) | desktop/app/shared/contracts/channel-sdk.ts | SDK 类型重导出 + 工具函数内联 |
| security-types | desktop/app/shared/contracts/security-types.ts | 用户角色和权限类型定义 |
| RateLimiter | desktop/app/main/services/platform/security/RateLimiter.ts | 滑动窗口速率限制 |
| InputSanitizer | desktop/app/main/services/platform/security/InputSanitizer.ts | 不可见字符清除 |
| PromptGuardian | desktop/app/main/services/platform/security/PromptGuardian.ts | AI 驱动的提示注入检测 |
| UserPermissionService | desktop/app/main/services/platform/security/UserPermissionService.ts | 基于角色的访问控制 |
| ChannelPermissionGate | desktop/app/main/services/platform/security/ChannelPermissionGate.ts | 敏感操作确认机制 |
插件生命周期
stateDiagram-v2
[*] --> Discovered: ChannelPluginLoader.discover()
Discovered --> Registered: ChannelPluginRegistry.registerPlugin()
Registered --> InstanceCreated: createInstance(id, config)
InstanceCreated --> Connecting: connectInstance(id)
Connecting --> Connected: plugin.connect() 成功
Connecting --> Error: plugin.connect() 失败
Connected --> Disconnected: disconnectInstance(id)
Error --> Connecting: 重试连接
Disconnected --> Connecting: 重新连接
InstanceCreated --> Removed: removeInstance(id)
Disconnected --> Removed: removeInstance(id)
Connected --> Removed: removeInstance(id)
Removed --> [*]
启动流程
ChannelPluginLoader扫描两个目录(bundled + marketplace),发现所有elftia-channel.json清单- 对于每个发现的插件,调用
loader.load()加载模块,获取 factory 函数 - 调用
registry.registerPlugin(manifest, factory, dir)注册到 Registry - 从数据库加载已保存的 Channel 实例配置
- 对每个实例调用
registry.createInstance(id, config) - 对
enabled && autoConnect的实例调用registry.connectAll() ChannelMagiBridge.start()开始监听routeToAgent事件
连接管理
connectInstance(id)— 调用plugin.connect(credentials, options),状态流转:disconnected → connecting → connected | errordisconnectInstance(id)— 调用plugin.disconnect(),状态流转:connected → disconnectedconnectAll()— 并发连接所有enabled实例,使用Promise.allSettled容错disconnectAll()— 并发断开所有已连接实例
IPC 通道
所有前端操作通过 ChannelPluginRouter 的 IPC 通道实现:
| IPC 通道 | 方向 | 说明 |
|---|---|---|
channelPlugin:listInstances | renderer → main | 获取所有 Channel 实例列表 |
channelPlugin:createInstance | renderer → main | 创建新实例(含凭证加密存储) |
channelPlugin:updateInstance | renderer → main | 更新实例配置 |
channelPlugin:deleteInstance | renderer → main | 删除实例及相关存储 |
channelPlugin:connect | renderer → main | 连接指定实例 |
channelPlugin:disconnect | renderer → main | 断开指定实例 |
channelPlugin:testConnection | renderer → main | 验证凭证有效性 |
channelPlugin:getMarketplace | renderer → main | 获取 Marketplace 插件列表 |
channelPlugin:downloadPlugin | renderer → main | 从 CDN 下载并安装插件 |
channelPlugin:removePlugin | renderer → main | 卸载已安装的插件 |
channelPlugin:updateTrigger | renderer → main | 更新触发规则 |
channelPlugin:statusChange | main → renderer | 实例状态变化通知 |
channelPlugin:downloadProgress | main → renderer | 插件下载进度通知 |
数据持久化
Channel 实例
实例配置存储在 magi_channels 表中,通过 ChannelPluginRouter 的 channelsUpsert / channelsUpdate / channelsDelete 操作。
插件 K-V 存储
每个插件实例拥有独立的键值存储(ChannelStorageDb 接口),用于保存平台特定的状态数据。底层为 SQLite 表,上层有内存缓存。
消息活动日志
入站和出站消息以 JSONL 格式记录到文件系统:
{channelDataDir}/{channelId}/conversations/{chatDir}/{YYYY-MM-DD}.jsonl
写入采用缓冲机制(每 2 秒刷新一次),减少磁盘 I/O。
下一步
- Channel 插件 SDK — 插件接口定义和清单格式
- 消息路由与安全管线 — 消息处理管线详解
- ChannelMagiBridge — Channel 到 Agent 的消息桥接
- 编写 Channel 插件 — 从零开始编写自定义插件