Перейти к основному содержимому

Обзор системы Channel

Система Channel — это многоплатформенный уровень приёма сообщений Elftia, отвечающий за маршрутизацию сообщений из внешних платформ (Discord, Telegram, Slack и др.) в конвейер обработки Agent и обратную маршрутизацию ответов на исходную платформу.

Обзор архитектуры

graph TB
subgraph External Platforms
D[Discord]
T[Telegram]
S[Slack]
O[Other Platforms...]
end

subgraph Channel Plugin Layer
PL[ChannelPluginLoader<br/>Plugin Discovery & Loading]
PR[ChannelPluginRegistry<br/>Instance Management & Event Dispatch]
end

subgraph Message Pipeline
MR[ChannelMessageRouter<br/>Security Pipeline + Trigger Matching]
end

subgraph Security Pipeline
RL[RateLimiter]
IS[InputSanitizer]
PG[PromptGuardian]
UP[UserPermissionService]
CG[ChannelPermissionGate]
end

subgraph Agent Layer
MB[ChannelMagiBridge<br/>Message Format Conversion]
MS[MagiService<br/>Agent Processing]
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

Индекс ключевых файлов

ФайлПутьОтветственность
ChannelPluginLoaderdesktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tsОбнаружение, валидация, загрузка плагинов (два каталога)
ChannelPluginRegistrydesktop/app/main/services/capabilities/integrations/channel/ChannelPluginRegistry.tsУправление фабрикой плагинов и жизненным циклом экземпляров Channel
ChannelMessageRouterdesktop/app/main/services/capabilities/integrations/channel/ChannelMessageRouter.tsКонвейер безопасности, сопоставление триггеров, буферизация сообщений, разбивка ответов
ChannelMagiBridgedesktop/app/main/services/agent-core/magi/ChannelMagiBridge.tsПреобразование сообщений Channel → MagiIncomingMessage
ChannelMarketplaceServicedesktop/app/main/services/capabilities/integrations/channel/ChannelMarketplaceService.tsПолучение CDN-манифеста, загрузка и установка плагинов
ChannelPluginRouterdesktop/app/main/services/routers/ChannelPluginRouter.tsIPC-маршрутизация (фронтенд ↔ бэкенд)
channel-sdkpackages/channel-sdk/src/SDK для разработки плагинов (типы, интерфейсы)
channel-typesdesktop/app/shared/contracts/channel-types.tsУнифицированные определения типов Channel
channel-sdk (re-export)desktop/app/shared/contracts/channel-sdk.tsРеэкспорт типов SDK + встроенные вспомогательные функции
security-typesdesktop/app/shared/contracts/security-types.tsОпределения типов ролей и разрешений пользователей
RateLimiterdesktop/app/main/services/platform/security/RateLimiter.tsОграничение частоты запросов скользящим окном
InputSanitizerdesktop/app/main/services/platform/security/InputSanitizer.tsУдаление невидимых символов
PromptGuardiandesktop/app/main/services/platform/security/PromptGuardian.tsОбнаружение инъекций промптов на основе AI
UserPermissionServicedesktop/app/main/services/platform/security/UserPermissionService.tsУправление доступом на основе ролей
ChannelPermissionGatedesktop/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() success
Connecting --> Error: plugin.connect() failure
Connected --> Disconnected: disconnectInstance(id)
Error --> Connecting: Retry connection
Disconnected --> Connecting: Reconnect
InstanceCreated --> Removed: removeInstance(id)
Disconnected --> Removed: removeInstance(id)
Connected --> Removed: removeInstance(id)
Removed --> [*]

Последовательность запуска

  1. ChannelPluginLoader сканирует два каталога (bundled + marketplace) и обнаруживает все манифесты elftia-channel.json
  2. Для каждого обнаруженного плагина вызывает loader.load() для загрузки модуля и получения фабричной функции
  3. Вызывает registry.registerPlugin(manifest, factory, dir) для регистрации в Registry
  4. Загружает сохранённые конфигурации экземпляров Channel из базы данных
  5. Вызывает registry.createInstance(id, config) для каждого экземпляра
  6. Вызывает registry.connectAll() для экземпляров с enabled && autoConnect
  7. ChannelMagiBridge.start() начинает прослушивание событий routeToAgent

Управление подключениями

  • connectInstance(id) — вызов plugin.connect(credentials, options), переход состояний: disconnected → connecting → connected | error
  • disconnectInstance(id) — вызов plugin.disconnect(), переход состояний: connected → disconnected
  • connectAll() — конкурентное подключение всех enabled-экземпляров с использованием Promise.allSettled для отказоустойчивости
  • disconnectAll() — конкурентное отключение всех подключённых экземпляров

IPC-каналы

Все фронтенд-операции реализованы через IPC-каналы ChannelPluginRouter:

IPC-каналНаправлениеОписание
channelPlugin:listInstancesrenderer → mainПолучить список всех экземпляров Channel
channelPlugin:createInstancerenderer → mainСоздать новый экземпляр (с зашифрованным хранением учётных данных)
channelPlugin:updateInstancerenderer → mainОбновить конфигурацию экземпляра
channelPlugin:deleteInstancerenderer → mainУдалить экземпляр и связанное хранилище
channelPlugin:connectrenderer → mainПодключить указанный экземпляр
channelPlugin:disconnectrenderer → mainОтключить указанный экземпляр
channelPlugin:testConnectionrenderer → mainПроверить валидность учётных данных
channelPlugin:getMarketplacerenderer → mainПолучить список плагинов Marketplace
channelPlugin:downloadPluginrenderer → mainЗагрузить и установить плагин из CDN
channelPlugin:removePluginrenderer → mainУдалить установленный плагин
channelPlugin:updateTriggerrenderer → mainОбновить правила триггеров
channelPlugin:statusChangemain → rendererУведомление об изменении статуса экземпляра
channelPlugin:downloadProgressmain → rendererУведомление о прогрессе загрузки плагина

Сохранение данных

Экземпляры Channel

Конфигурации экземпляров хранятся в таблице magi_channels, управление ведётся через операции channelsUpsert / channelsUpdate / channelsDelete в ChannelPluginRouter.

Хранилище ключ-значение плагина

Каждый экземпляр плагина владеет независимым хранилищем ключ-значение (интерфейс ChannelStorageDb) для платформо-специфичных данных состояния. Базовая реализация — таблицы SQLite с кеширующим слоем в памяти.

Журналы активности сообщений

Входящие и исходящие сообщения записываются в файловую систему в формате JSONL:

{channelDataDir}/{channelId}/conversations/{chatDir}/{YYYY-MM-DD}.jsonl

Запись использует механизм буферизации (сброс каждые 2 секунды) для снижения дисковых операций ввода-вывода.

Следующие шаги