Проектирование Main Process
Main process — ядро Elftia, отвечающее за всю бизнес-логику, внешние API-вызовы, операции с базой данных и средства контроля безопасности. Входной файл — packages/desktop/app/main/index.ts.
Обзор сервисных модулей
Main process содержит более 45 сервисных модулей, организованных по функциональным областям в packages/desktop/app/main/services/:
graph LR
subgraph "Core Infrastructure"
Core[core/]
Config[config/]
Settings[settings/]
end
subgraph "Auth & Accounts"
Auth[auth/]
Account[account/]
OAuth[oauth/]
end
subgraph "AI Engines"
Engine[engine/]
Completion[completion/]
LLM[llm/]
Prompt[prompt/]
end
subgraph "Agent Orchestration"
Magi[magi/]
Agent[agent/]
Plugin[plugin/]
end
subgraph "Messaging Channels"
Channel[channel/]
Security[security/]
end
subgraph "Media & Content"
Media[media/]
Project[project/]
Search[search/]
end
Core --> Engine
Core --> Channel
Engine --> Magi
LLM --> Completion
Completion --> Engine
Magi --> Agent
Channel --> Security
Список сервисов по областям
| Область | Сервис | Описание |
|---|---|---|
| Core (core/) | LoggerService | Логирование Winston + daily-rotate-file |
AppPaths | Разрешение путей приложения (userData, dbPath, configDir и т. д.) | |
RuntimeService | Информация о среде выполнения (версия, канал, платформа) | |
CacheService | Кэш общего назначения (очистка по истечении TTL) | |
ConfigManager | Управление конфигурационными файлами | |
SecurityService | Сервис шифрования AES-256-GCM | |
CryptoService | Вывод ключа PBKDF2 + encrypt/decrypt | |
PerformanceMonitor | Мониторинг производительности и оповещения | |
ErrorHandler | Глобальная обработка ошибок | |
PluginManager | Управление жизненным циклом плагинов | |
DatabaseOptimizer | Оптимизация SQLite (VACUUM, ANALYZE) | |
CommandService | Сервис выполнения команд | |
| Auth (auth/) | AuthService | Проверка токена аутентификации IPC |
AuthSessionService | Сессия входа + обработка Deep Link | |
AuthTokenStore | Постоянное хранение auth-токенов | |
TokenRefreshService | Автоматическое обновление токенов | |
| Account (account/) | AccountService | Управление учетными данными пользователя |
AccountTokensService | Управление OAuth-токенами | |
LimitsService | Проверки лимитов подписки | |
| LLM (llm/) | LLMConfigService | CRUD конфигурации провайдеров/моделей |
TransformerService | Цепочка преобразования формата запроса | |
| Completion (completion/) | CompletionService | Точка входа для LLM API-вызовов |
ApiKeyPoolService | Round-robin для нескольких ключей + привязка к сессии | |
| Engine (engine/) | EngineDispatcher | Регистрация и маршрутизация движков |
ApiEngine | Движок Media API | |
ChatEngine | Движок общего чата | |
ClaudeSdkEngine | Движок Claude Agent SDK | |
TinyElfEngine | Встроенный Agent-движок | |
CliRunnerEngine | Движок CLI-подпроцессов | |
STChatEngine | Движок RP chat pipeline | |
| Magi Orchestration (magi/) | MagiService | Основной сервис обработки сообщений (включает assembleMagiMcps, который собирает MCP-набор Clawia через реестр services/capabilities/tools/mcp-builtin/; buildTinyElfDirectMcpServers — точка входа TinyElf) |
MagiSessionService | Управление постоянным хранением сессий | |
MagiWorkspaceService | Управление рабочими директориями | |
MagiSdkOptionsBuilder | Сборка промптов (V1-V4) + внедрение пользовательских MCP (setUserMcpServers / getMcpServers(allowedUserMcpNames) / getDirectMcpServers) + проба Channel; сборка встроенных MCP вынесена в mcp-providers/ начиная с Phase 5.9 | |
AgentOrchestrator | Диспетчеризация и оркестрация Agent | |
AgentDiscovery | Список Agent, доступных для планирования | |
MessageRouter | Двухрежимная маршрутизация сообщений | |
ChannelMagiBridge | Мост от Channel к Magi | |
SessionEventBus | Шина событий сессий | |
SessionDispatcherImpl | Реализация межсессионной диспетчеризации | |
SubagentRegistry | Отслеживание состояния субагентов | |
| Built-in MCP Registry (mcp-providers/) | McpProviderRegistry | 12 встроенных провайдеров + фабрика динамических провайдеров ScriptPlugin. Все встроенные MCP-обработчики работают in-process; SDK вызывает напрямую / TinyElf регистрирует как ITool / CLI получает доступ через центральный HTTP-мост BuiltinMcpHttpServer. HTTP-мосты DispatchServer / ChannelServer / VisionAssistServer были удалены в cleanup-legacy-mcp (2026-05-19) |
BuiltinMcpHttpServer | Центральный HTTP MCP-мост (область видимости — сессия); через него все in-process MCP доступны CLI-движку | |
assembleMcpForSession(ctx) | Единая точка сборки (SDK + TinyElf; возвращает McpAssembly, содержащий sdkServers / tinyElfServers / promptFragments / allowedTools / cleanups) | |
applyAssembly.ts | applyAssemblyToSdkOptions / applyAssemblyToTinyElfConfig — объединяет McpAssembly с параметрами движка | |
contextBuilders.ts | buildAssemblyContextFor{Clawia,Agent} — строит AssemblyContext с точки зрения вызывающей стороны | |
registerBuiltinMcpProviders.ts | Одноразовая точка сборки при запуске (включая обработку одноименных alias для ScriptPlugin) | |
builtin/<Name>Provider.ts | По одному модулю Provider на каждый встроенный MCP (12 статических + фабрика динамических ScriptPlugin) | |
| Channel (channel/) | ChannelPluginLoader | Обнаружение и загрузка плагинов |
ChannelPluginRegistry | Регистрация плагинов и управление экземплярами | |
ChannelMessageRouter | Маршрутизация триггеров сообщений | |
ChannelMarketplaceService | Marketplace плагинов | |
| Security (security/) | ExecutionFirewall | Файрвол путей к файлам |
GuardianAgent | Проверка вызовов AI-инструментов | |
PromptGuardian | Обнаружение prompt injection | |
RateLimiter | Ограничение частоты запросов | |
InputSanitizer | Санитизация ввода | |
UserPermissionService | Управление разрешениями пользователя | |
ChannelPermissionGate | Подтверждение разрешений Channel | |
AuditLogger | Аудит-лог безопасности | |
| Media (media/) | ImageGenerationService | Генерация изображений |
MusicGenerationService | Генерация музыки | |
MediaStorageService | Хранение медиафайлов | |
MediaResourceService | Хранилище ресурсов с content-addressing | |
MediaConfigService | Конфигурация Media-провайдеров | |
AsrService / TtsService | Распознавание/синтез речи | |
| Project (project/) | ProjectService | CRUD проектов |
FileIndexService | Сервис файлового индекса | |
GitService | Операции Git | |
| Search (search/) | WebSearchService | Единая точка входа поиска |
JinaProvider / TavilyProvider / SearxngProvider | Адаптеры поисковых движков | |
| UI (ui/) | ThemeService | Управление темой |
WindowControlsService | Управление окнами | |
TrayService | Системный трей | |
NotificationService | Desktop-уведомления | |
| Config (config/) | ConfigStore | electron-store + hot-reload через fs.watch |
| Cron (cron/) | CronService | Диспетчеризация запланированных задач Cron |
| MCP (mcp/) | McpService | Управление MCP-серверами |
| Plugins (plugin/) | ScriptPluginLoader | Загрузка script-плагинов |
ScriptPluginRegistry | Реестр script-плагинов | |
ScriptPluginBridgeManager | Управление мостами плагинов |
Архитектура IPC Router
Вся коммуникация от frontend к backend проходит через слой IPC Router; сейчас зарегистрировано более 68 модулей маршрутизаторов.
Паттерн secureHandle
Каждый IPC-канал оборачивается в secureHandle, который принудительно проверяет токен аутентификации:
{/* packages/desktop/app/main/ipc/safe-handle.ts */}
function secureHandle(
channel: string,
handler: (event: IpcMainInvokeEvent, params: unknown) => Promise<unknown>,
validateToken: (token: string) => boolean,
): void;
Поток:
sequenceDiagram
participant R as Renderer
participant P as Preload
participant S as secureHandle
participant H as Router Handler
R->>P: window.api.someMethod(params)
P->>S: ipcRenderer.invoke(channel, {token, ...params})
S->>S: validateToken(token)
alt token invalid
S-->>P: throw AuthError
else token valid
S->>H: handler(event, params)
H-->>S: result
S-->>P: result
P-->>R: result
end
Регистрация маршрутов
Все маршруты централизованно регистрируются в registerAllRouters(). Каждый класс Router наследует BaseRouter и регистрирует свои каналы в методе register():
{/* Simplified Router structure */}
class SomeRouter extends BaseRouter {
register() {
secureHandle('domain:action', async (_event, params) => {
const validated = SomeSchema.parse(params);
return this.service.doSomething(validated);
}, this.validate);
}
}
Категории и количество маршрутов
| Директория/файл Router | Префикс канала | Количество основных каналов |
|---|---|---|
auth/ | auth:* | 5+ |
account/ | accounts:*, accountTokens:* | 8+ |
session/ | sessions:*, sessionOrganizer:* | 10+ |
chat/ | chatMessages:*, chatAssistants:*, chatControl:*, mediaSession:* | 15+ |
completion/ | completion:* | 5+ |
capabilities/llm/ | llmProviders:*, llmModels:*, apiKeys:*, transformers:* | 15+ |
project/ | projects:*, files:*, git:* | 10+ |
media/ | media:*, imageProviders:*, musicProviders:*, videoProviders:*, asr:*, tts:* | 20+ |
settings/ | settings:*, appPreferences:* | 8+ |
ui/ | theme:*, window:* | 6+ |
MagiRouter | magi:* | 10+ |
ChannelPluginRouter | channels:* | 8+ |
sillytavern/ | characterCards:*, worldInfo:*, regexScripts:*, groupChat:*, etc. | 25+ |
| Прочие | mcp:*, webSearch:*, todo:*, tasks:*, notes:*, tags:*, cron:*, elfi:*, etc. | 30+ |
Паттерн Worker Thread
Длительные операции ввода-вывода выполняются в Worker Threads, чтобы не блокировать main thread.
DbClient — Database Worker
DbClient — самый критичный Worker, инкапсулирующий все взаимодействия с базой данных SQLite:
sequenceDiagram
participant S as Service
participant C as DbClient
participant W as db.worker.ts
participant D as SQLite (WAL)
S->>C: db.someMethod(params)
C->>C: seq++, create Promise
C->>W: postMessage({id: seq, method, params})
W->>D: Execute SQL query
D-->>W: Result
W-->>C: postMessage({id: seq, result})
C->>C: resolve(pending[seq])
C-->>S: Promise<result>
{/* Simplified DbClient RPC pattern */}
class DbClient extends EventEmitter implements DbRpc {
private worker: Worker;
private seq = 0;
private pending = Map<number, {resolve, reject}>;
async send(method: string, params: unknown): Promise<unknown> {
const id = ++this.seq;
return new Promise((resolve, reject) => {
this.pending.set(id, { resolve, reject });
this.worker.postMessage({ id, method, params });
});
}
async ready(): Promise<void>;
}
Ключевые проектные моменты:
- Async RPC: каждому вызову назначается уникальный порядковый номер; запросы отправляются через
postMessage - Ожидание готовности:
await db.ready()гарантирует, что Worker завершил инициализацию (создание схемы) перед использованием - Проброс ошибок: ошибки Worker всплывают через EventEmitter
Список Worker Threads
| Файл Worker | Назначение | Коммуникация |
|---|---|---|
db.worker.ts | Чтение/запись базы данных SQLite (100+ RPC-методов) | DbClient RPC |
fileSearch.worker.ts | Поиск файлов (fuzzy match) | MessagePort |
fileWatcher.worker.ts | Наблюдение за файловой системой (chokidar) | MessagePort |
mcp.worker.ts | Управление процессами MCP-серверов | MessagePort |
diagnostics.worker.ts | Сбор системных диагностических данных | MessagePort |
project.worker.ts | Построение индекса файлов проекта | MessagePort |
fileSnapshot.worker.ts | Сравнение снимков файлов | MessagePort |
Ключевая инфраструктура
LoggerService
Основан на Winston, поддерживает фильтрацию по уровню логирования и автоматическую ротацию лог-файлов:
{/* Simplified LoggerService interface */}
class LoggerService {
info(message: string, meta?: Record<string, unknown>): void;
warn(message: string, err?: Error, meta?: Record<string, unknown>): void;
error(message: string, err?: unknown, meta?: Record<string, unknown>): void;
debug(message: string, meta?: Record<string, unknown>): void;
}
- Расположение логов:
{userData}/logs/ - Политика ротации: daily-rotate-file, хранение 14 дней
- Формат: JSON + timestamp
SecurityService / CryptoService
{/* Core encryption service interface */}
class SecurityService {
encrypt(plaintext: string): string;
decrypt(ciphertext: string): string;
}
class CryptoService {
deriveKey(password: string, salt: Buffer): Buffer;
encrypt(data: string, key: Buffer): EncryptedData;
decrypt(data: EncryptedData, key: Buffer): string;
}
AppPaths
Централизованно управляет всеми путями директорий приложения:
| Свойство | Путь | Назначение |
|---|---|---|
userData | {appData}/elftia/ | Корень данных приложения |
dbPath | {userData}/elftia.db | База данных SQLite |
configDir | {userData}/config/ | Директория конфигурационных файлов |
resourcesDir | {userData}/resources/ | Media-ресурсы |
diagnosticsDir | {userData}/diagnostics/ | Диагностические данные |
logsDir | {userData}/logs/ | Лог-файлы |
Связанные файлы
| Файл | Описание |
|---|---|
packages/desktop/app/main/index.ts | Вход main process; создание и запуск всех сервисов |
packages/desktop/app/main/services/routers/index.ts | Центр регистрации маршрутов, registerAllRouters() |
packages/desktop/app/main/services/routers/BaseRouter.ts | Базовый класс Router |
packages/desktop/app/main/ipc/safe-handle.ts | Защитная IPC-обертка secureHandle |
packages/desktop/app/main/workers/DbClient.ts | Клиент Database Worker |
packages/desktop/app/main/workers/db.worker.ts | Реализация Database Worker |
packages/desktop/app/main/workers/types.ts | Определения типов Worker RPC |
packages/desktop/app/main/services/infra/logger/LoggerService.ts | Сервис логирования |
packages/desktop/app/main/services/platform/security/SecurityService.ts | Сервис шифрования |
packages/desktop/app/main/services/infra/paths/paths.ts | Управление путями |
packages/desktop/app/main/services/agent-core/engine/EngineDispatcher.ts | Диспетчер движков |