Обзор архитектуры
Elftia — это десктопное AI-приложение для общения на базе Electron + React, построенное на архитектуре со строгим разделением фронтенда и бэкенда. В этом документе описаны общая структура системы, основные принципы проектирования и ключевые технологические решения.
Многопроцессная модель
Приложение Electron работает в трёх процессах плюс нескольких рабочих потоках (Worker threads):
graph TB
subgraph "Renderer Process (React)"
UI[React UI Components]
Ctx[Context / Zustand Store]
Hooks[Custom Hooks]
end
subgraph "Preload Script (contextBridge)"
Bridge[window.api / window.native]
end
subgraph "Main Process (Node.js)"
Services[45+ Service Modules]
Routers[68+ IPC Routers]
Engines[5 Engines: API / Chat / ClaudeSDK / TinyElf / CLI]
Security[Security Control Layer]
end
subgraph "Worker Threads"
DbWorker[db.worker — SQLite read/write]
FileSearch[fileSearch.worker — file search]
FileWatcher[fileWatcher.worker — file watching]
McpWorker[mcp.worker — MCP server]
DiagWorker[diagnostics.worker — diagnostics]
ProjWorker[project.worker — project indexing]
end
subgraph "External APIs"
LLM[LLM Provider APIs]
Media[Media Generation APIs]
Search[Search Engine APIs]
Channel[Channel Platform APIs]
end
UI --> Bridge
Bridge --> Routers
Routers --> Services
Services --> Engines
Services --> Security
Services --> DbWorker
Services --> FileSearch
Services --> FileWatcher
Services --> McpWorker
Services --> DiagWorker
Services --> ProjWorker
Services --> LLM
Services --> Media
Services --> Search
Engines --> Channel
Обязанности процессов
| Процесс | Обязанности | Ключевые файлы |
|---|---|---|
| Главный процесс | Вся бизнес-логика, вызовы внешних API, операции с базой данных, доступ к файловой системе, контроль безопасности | packages/desktop/app/main/index.ts |
| Процесс рендерера | Чистая отрисовка UI и взаимодействие с пользователем; не обращается напрямую к внешним API или файловой системе | packages/renderer/src/app/App.tsx |
| Preload-скрипт | Предоставляет процессу рендерера безопасный IPC-интерфейс через contextBridge | packages/desktop/app/preload/index.ts |
| Worker-потоки | Длительные I/O-операции (база данных, индексация файлов, управление процессами MCP) | packages/desktop/app/main/workers/ |
Основные принципы проектирования
1. Строгое разделение фронтенда и бэкенда
Процесс рендерера отвечает только за UI; все внешние вызовы обрабатываются исключительно главным процессом:
Renderer ──(IPC)──> Main Process ──> External API / Filesystem / Database
│
└──> Process response and return final result
│
Renderer <──(IPC)──< Main Process
Запрещено: делать вызовы внешних API непосредственно из фронтенда или обрабатывать там большие объёмы данных перед отправкой их обратно на бэкенд.
2. Безопасность прежде всего
- Context Isolation: Процесс рендерера полностью изолирован и может общаться только через интерфейсы, предоставленные через
contextBridge - IPC Auth Token: Каждый IPC-вызов содержит токен аутентификации, который проверяется
secureHandleв главном процессе - API-ключи хранятся только в главном процессе: Все ключи шифруются с помощью
SecurityService(AES-256-GCM) перед сохранением - ExecutionFirewall: Блокирует доступ к системным каталогам и файлам с учётными данными
- GuardianAgent: AI-проверка безопасности вызовов инструментов
3. Плагинная архитектура
Система поддерживает несколько типов плагинов:
| Тип плагина | Описание | Место загрузки |
|---|---|---|
| Agent Packages | Предварительно настроенные определения Agent (MCP, Skill, Prompt) | agent-packages/ |
| Persona Packages | Предварительно настроенные определения Persona (персонаж) | persona-packages/ |
| Script Plugins | Горячеподключаемые серверы инструментов MCP | script-plugins/ |
| Channel Plugins | Многоплатформенные каналы сообщений (Discord, Telegram и др.) | elftia-channels/ |
| Extensions | Расширения, совместимые с SillyTavern | Загружаются динамически |
4. Многодвижковая диспетчеризация
Пятью движками управляет единый EngineDispatcher, который направляет запросы к нужному движку в зависимости от конфигурации Agent:
{/* Simplified engine registration */}
interface IEngine {
type: EngineType;
chat(session: EngineSession): Promise<EngineResult>;
cancel(sessionId: string): Promise<void>;
}
type EngineType = 'api' | 'chat' | 'claude-sdk' | 'tinyelf' | 'cli' | 'st-roleplay';
| Движок | Назначение | Файл реализации |
|---|---|---|
ApiEngine | API генерации медиа (изображения, музыка и т. д.) | services/agent-core/engine/ApiEngine.ts |
ChatEngine | Общее LLM-чат-завершение | services/agent-core/engine/ChatEngine.ts |
ClaudeSdkEngine | Сессии Claude Agent SDK | services/agent-core/engine/ClaudeSdkEngine.ts |
TinyElfEngine | Встроенный лёгкий движок Agent | services/agent-core/engine/tinyelf/ |
CliRunnerEngine | CLI-subprocess-агенты (Claude CLI, Codex CLI) | services/agent-core/engine/cli/CliRunnerEngine.ts |
STChatEngine | RP-пайплайн, совместимый с SillyTavern | services/agent-core/engine/STChatEngine.ts |
Пользовательские протоколы
Electron регистрирует 4 пользовательских протокола для безопасной загрузки локальных ресурсов:
| Протокол | Назначение | Разрешения |
|---|---|---|
elftia:// | Deep Link (OAuth-коллбэки и т. д.) | Default protocol client |
wallpaper:// | Загрузка фоновых изображений | secure, fetchAPI, stream, bypassCSP, CORS |
media:// | Медиафайлы (изображения, аудио, видео) | secure, fetchAPI, stream, bypassCSP, CORS |
resource:// | Файлы общих ресурсов | secure, fetchAPI, stream, bypassCSP, CORS |
Обзор базы данных
- Движок: better-sqlite3 + Drizzle ORM
- Режим: WAL (Write-Ahead Logging), поддерживает параллельное чтение
- Расположение:
{userData}/elftia.db - Паттерн доступа: Главный процесс через Worker Thread (
DbClient→db.worker.ts) с асинхронным RPC
Подробное описание структуры базы данных см. в разделе Database.
Структура монорепозитория
elftia/
├── packages/
│ ├── desktop/ # Electron main process + preload
│ │ └── app/
│ │ ├── main/ # Main process code
│ │ │ ├── services/ # 45+ service modules
│ │ │ ├── workers/ # Worker threads
│ │ │ ├── db/ # Drizzle ORM schema
│ │ │ └── ipc/ # IPC security utilities
│ │ ├── preload/ # contextBridge definitions
│ │ └── shared/ # Frontend/backend shared types
│ ├── renderer/ # React frontend (Vite)
│ │ └── src/
│ │ ├── app/ # App entry, layout, Provider host
│ │ ├── features/ # Feature domains (components/hooks/state)
│ │ ├── pages/ # Page-level components
│ │ ├── shared/ # Cross-feature shared (state/Zustand, hooks, utils, components/ui)
│ │ ├── components/ # Legacy shared UI components (including components/ui)
│ │ ├── contexts/ # React Context (limited, retained)
│ │ └── locales/ # i18n (en/zh/ja)
│ ├── server/ # Web server (Fastify) — optional
│ ├── channel-sdk/ # Channel plugin SDK
│ └── pack-cli/ # Agent package management CLI
├── agent-packages/ # Built-in Agent definitions
├── persona-packages/ # Built-in Persona definitions
├── script-plugins/ # Built-in Script plugins
├── elftia-channels/ # Built-in Channel plugins
└── docs/ # Development documentation
Псевдонимы путей
| Псевдоним | Указывает на | Используется в |
|---|---|---|
@/* | packages/renderer/src/* | Процесс рендерера |
@shared/* | packages/desktop/app/shared/* | Общие глобальные типы |
@main/* | packages/desktop/app/main/* | Внутренние модули главного процесса |
Технологический стек
| Слой | Технология | Версия |
|---|---|---|
| Десктопный фреймворк | Electron | 31.7 |
| Фронтенд-фреймворк | React + TypeScript | 18.2 / 5.6 |
| Инструменты сборки | Vite (renderer) / tsup (main) | 7.0 |
| Стилизация | Tailwind CSS + CSS-переменные | 3.4 |
| Управление состоянием | React Context + Zustand | — |
| База данных | better-sqlite3 + Drizzle ORM | — |
| Редактор кода | CodeMirror 6 | — |
| Эмулятор терминала | xterm 5.5 | — |
| AI SDK | @anthropic-ai/claude-agent-sdk | — |
Связанные файлы
| Файл | Описание |
|---|---|
packages/desktop/app/main/index.ts | Точка входа главного процесса; инициализация сервисов и определение этапов запуска |
packages/renderer/src/app/App.tsx | Точка входа процесса рендерера; иерархия Context Provider |
packages/desktop/app/preload/index.ts | Preload-скрипт; экспозиция интерфейса contextBridge |
packages/desktop/app/shared/contracts/ | Контракты общих типов между фронтендом и бэкендом |
packages/desktop/app/main/services/agent-core/engine/EngineDispatcher.ts | Диспетчер движков |
packages/desktop/app/main/ipc/safe-handle.ts | Утилита безопасного IPC-handle |
vite.config.js | Конфигурация сборки Vite |
tsconfig.base.json | Базовая конфигурация TypeScript |