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

Фазы запуска

Процесс запуска главного процесса Elftia разделён на 13 фаз, каждая из которых имеет чётко определённые обязанности и зависимости. Весь код фаз находится в функции createServices() в файле packages/desktop/app/main/index.ts.

Обзор фаз запуска

flowchart TB
P0[Фаза 0: Регистрация протоколов + Logger]
P1[Фаза 1: Ядровые сервисы]
P2[Фаза 2: Функциональные сервисы]
P25[Фаза 2.5: Загрузка пакетов]
P26[Фаза 2.6: Синхронизация пакетов]
P27[Фаза 2.7: Сервис управления пакетами]
PS1[Фаза S1: Magi Dispatch]
PS2[Фаза S2: MagiService]
PS25[Фаза S2.5: CronService]
PC1[Фаза C1: Channel-плагины]
PS3[Фаза S3: ChannelMagiBridge]
P3[Фаза 3: Регистрация IPC-маршрутов]
PT[Фаза T1-T3: Todo/Task/Notes]
PW1[Фаза W1: Создание окна]
PW2[Фаза W2: WebSocket/Протоколы]

P0 --> P1 --> P2 --> P25 --> P26 --> P27
P27 --> PS1 --> PS2 --> PS25
PS25 --> PC1 --> PS3
PS3 --> P3 --> PT --> PW1 --> PW2

Фаза 0: Регистрация протоколов + Logger

Выполняется до app.whenReady(). Регистрирует кастомные протоколы и основной сервис логирования.

flowchart LR
A[Зарегистрировать протокол elftia://] --> B[Зарегистрировать привилегированные схемы]
B --> C[wallpaper://]
B --> D[media://]
B --> E[resource://]
ШагДействиеОписание
1app.setAsDefaultProtocolClient('elftia')Зарегистрировать протокол Deep Link
2protocol.registerSchemesAsPrivileged()Зарегистрировать привилегированные протоколы wallpaper/media/resource
3new LoggerService()Создать сервис логирования (Winston + daily-rotate)
4setIpcLogger(logger)Установить логгер для IPC-слоя
5new ErrorHandler(logger)Создать глобальный обработчик ошибок
6setIpcErrorHandler(errorHandler)Установить обработчик ошибок для IPC-слоя
7new AutoUpdateService(logger)Создать сервис автоматического обновления
8new DownloadService(logger)Создать сервис загрузки
9new WebUpdateService(logger, downloadManager)Создать сервис веб-обновлений

Ключевые файлы: packages/desktop/app/main/services/infra/logger/LoggerService.ts, packages/desktop/app/main/services/infra/error/ErrorHandler.ts

Фаза 1: Ядровые сервисы

Создаёт базовые сервисы, необходимые для работы приложения; эти сервисы не имеют внешних зависимостей.

flowchart LR
RT[RuntimeService] --> AP[AppPaths]
AP --> DB[DbClient + ready]
DB --> SS[SettingsService]
SS --> CS[ConfigStore]
CS --> Migrate[Миграция конфигурации]
Migrate --> Auth[Цепочка Auth-сервисов]
Auth --> WC[WindowControlsService]
ШагСервисЗависимостиОписание
1RuntimeServiceНетИнформация о среде выполнения (версия, платформа, канал)
2AppPathsНетРазрешение путей
3DbClientAppPathsСоздание Worker базы данных
4await db.ready()DbClientБлокирующее ожидание завершения инициализации Worker
5initDatabase()db.readyDrizzle ORM + WAL + migrate
6SettingsServiceAppPathsНастройки приложения
7ConfigStoreAppPathsФайл конфигурации electron-store
8migrateSettingsToConfigStore()Settings, ConfigStoreМиграция SQLite -> config.json
9settings.setConfigStore(configStore)-Связывание через паттерн делегата
10configStore.startWatching()-Горячая перезагрузка конфигурации через fs.watch
11AccountServiceAppPathsУчётные данные пользователя
12AuthTokenStoreAccountServiceХранение токенов
13AuthSessionServiceRuntime, AuthStore, AuthApiСессия аутентификации
14AppPreferencesServiceConfigStoreПредпочтения приложения
15WindowControlsServiceSettingsУправление окном

Ключевой момент: await db.ready() является точкой блокировки, которая гарантирует, что Worker SQLite завершил создание схемы до продолжения работы. Это предотвращает ошибку SQLITE_BUSY, возникающую при одновременной записи двух соединений при первом запуске.

Фаза 2: Функциональные сервисы

Создаёт лёгкие функциональные сервисы; тяжёлая инициализация откладывается до момента использования.

СервисЗависимостиОписание
ConfigManagerLogger, AppPathsУправление файлами конфигурации
SecurityServiceLoggerШифрование AES-256-GCM
PerformanceMonitorLoggerМониторинг производительности
CacheServiceLoggerКэш общего назначения
DatabaseOptimizerLogger, DbClientОптимизация SQLite
NotificationServiceLoggerУведомления рабочего стола
PluginManagerLoggerЖизненный цикл плагинов
ProjectServiceDbClient, AccountServiceУправление проектами
DiagnosticsServiceAppPaths, ProjectServiceДиагностический сервис
ChatServiceLoggerСервис чата
McpServiceLoggerУправление MCP-сервером
LLMConfigServiceAppPaths, DbClientКонфигурация LLM
CompletionServiceAppPaths, LLMConfigServiceЗавершение LLM
ApiKeyPoolServiceDB, CompletionServiceЦиклическое использование нескольких ключей
ElfiServiceConfigStore, LLMConfig, CompletionАссистент Elfi
MediaConfigServiceAppPaths, DbClientКонфигурация медиа
ImageGenerationServiceMediaConfigГенерация изображений
ThemeServiceSettings, AuthSessionУправление темой
AgentServiceDbClient, Settings, LoggerСервис агентов
TransformerService-Трансформация запросов
WebSearchService-Веб-поиск
EngineDispatcher + регистрация движковЗависимости каждого движкаДиспетчер движков

Порядок регистрации движков

{/* Регистрация движков */}
engineDispatcher.registerEngine(new ApiEngine(...));
engineDispatcher.registerEngine(new ChatEngine(...));
engineDispatcher.registerEngine(new ClaudeSdkEngine(...));
engineDispatcher.registerEngine(new CliRunnerEngine(...));
engineDispatcher.registerEngine(new TinyElfEngine(...));
engineDispatcher.registerEngine(new STChatEngine(...));

Фаза 2.5: Загрузка пакетов

Загружает пакеты Agent, пакеты Persona и Script-плагины с диска в память.

flowchart TB
subgraph "Phase 2.5a: Agent Packages"
AL[AgentPackageLoader] --> BP[Загрузить встроенные пакеты]
BP --> UP[Загрузить пакеты пользователя]
UP --> AR[AgentPackageRegistry]
end

subgraph "Phase 2.5b: Persona Packages"
PL[PersonaPackageLoader] --> BPP[Загрузить встроенные пакеты]
BPP --> UPP[Загрузить пакеты пользователя]
UPP --> PR[PersonaPackageRegistry]
end

subgraph "Phase 2.5c: Script Plugins"
SL[ScriptPluginLoader] --> BSP[Загрузить встроенные плагины]
BSP --> USP[Загрузить плагины пользователя]
USP --> SR[ScriptPluginRegistry]
end

Пути загрузки (паттерн двух директорий):

Тип пакетаВстроенный путь (упакованный)Встроенный путь (dev)Пользовательский путь
Agentresources/agent-packages/../../agent-packages/{userData}/agent-packages/
Personaresources/persona-packages/../../persona-packages/{userData}/persona-packages/
Scriptresources/script-plugins/../../script-plugins/{userData}/script-plugins/

Фазы 2.6-2.7: Синхронизация и управление пакетами

ФазаДействиеОписание
2.6PackageSyncService.syncAll()Синхронизирует определения пакетов из памяти в базу данных (upsert FK anchors + данные persona)
2.7new AgentPackageService(...)Создаёт сервис управления пакетами, поддерживающий install/uninstall

Фаза S1: Magi Dispatch

Создаёт сервисы, связанные с оркестрацией и диспетчеризацией агентов.

flowchart TB
AGM[AgentManagementService] --> EB[SessionEventBus]
EB --> AD[AgentDiscovery]
AD --> AO[AgentOrchestrator]
AO --> MR[MessageRouter]
MR --> SDI[SessionDispatcherImpl]

AO -.->|setEngineDispatcher| ED[EngineDispatcher]
AO -.->|setDbProvider| DB[DbClient]
SDI -.->|внедряется в| TE[TinyElfEngine]
ШагСервисОписание
1AgentManagementServiceCRUD агентов + запросы к реестру пакетов
2InternalSessionEventBusПубликация/подписка на события сессии
3AgentDiscoveryРеестр планируемых агентов (обнаруженных из БД + реестра пакетов)
4AgentOrchestratorДиспетчеризация и оркестрация агентов; обработчик API dispatch
5MessageRouterДвухрежимная маршрутизация сообщений (прямая / через Orchestrator)
6SessionDispatcherImplРеализация межсессионной диспетчеризации
7Внедряется в TinyElfEnginetinyElfEngine.setSessionDispatcher(sessionDispatcher)
8SubagentRegistry.setDb(db)Сквозная запись реестра субагентов в хранилище

Историческая справка: HTTP-сервер диспетчеризации DispatchServer был удалён в cleanup-legacy-mcp (2026-05-19). Инструмент dispatch теперь собирается внутри процесса через MagiDispatchProvider + MagiDispatchHandlers посредством единого реестра; обработчики вызывают AgentOrchestrator / AgentDiscovery напрямую без использования HTTP. CLI-подпроцессы обращаются к нему через центральный services/capabilities/tools/mcp-builtin/BuiltinMcpHttpServer.ts.

Фаза S2: MagiService

Создаёт основной сервис обработки сообщений и внедряет все зависимости.

{/* Цепочка внедрения зависимостей MagiService */}
const magiService = new MagiService(
magiWorkspace, magiSession, magiOptionsBuilder,
magiOrchestrator, magiMessageRouter, magiEventBus,
llmConfig, logger, configStore,
);

// Отложенное внедрение (избегает циклических зависимостей)
magiService.setAgentService(agent);
magiService.setCompletionService(completion);
magiService.setAsrService(new AsrService(asrConfig));
magiService.setEngineDispatcher(engineDispatcher);
magiService.setDbProvider(db);
magiService.setMcpListProvider(() => mcp.list());
magiService.setDeveloperModeProvider(() => ...);

Горячая перезагрузка MCP: При изменении списка MCP-серверов происходит автоматическая синхронизация с рабочим пространством Magi и горячая перезагрузка активных сессий:

mcp.on('servers:changed', () => {
magiService.syncMcpServersToWorkspace();
magiService.notifyMcpChanged();
});

Фаза S2.5: CronService

Создаёт сервис планировщика задач Cron:

ВнедрениеНазначение
setNotificationService(notification)Уведомления рабочего стола
setNotificationChecker(...)Проверка предпочтений уведомлений
setAgentExecutor(...)Выполнение запланированных задач через MagiService
setStatusBroadcaster(...)Трансляция статуса задач во фронтенд

Фаза C1: Channel-плагины

Обнаруживает, загружает и регистрирует Channel-плагины.

flowchart TB
CL[ChannelPluginLoader] --> Discover[обнаружить плагины]
Discover --> Load[загрузить каждый плагин]
Load --> CR[ChannelPluginRegistry.registerPlugin]
CR --> CM[ChannelMarketplaceService<br/>асинхронно получить удалённый манифест]

subgraph "Подключение сервисов безопасности"
UPS[UserPermissionService] --> CMR[ChannelMessageRouter]
CPG[ChannelPermissionGate] --> CMR
AL[AuditLogger] --> TE[TinyElfEngine]
RL[RateLimiter] --> CMR
IS[InputSanitizer] --> CMR
PG[PromptGuardian] --> CMR
end

CR --> CMR

Пути загрузки (паттерн двух директорий):

ИсточникПуть (упакованный)Путь (dev)
Встроенный (только чтение)resources/bundled-channel-plugins/elftia-channels/dist-plugins/
Marketplace (с записью){userData}/channel-plugins/то же

Порядок подключения сервисов безопасности:

  1. UserPermissionService -> ChannelMessageRouter (проверка прав пользователя)
  2. ChannelPermissionGate -> ChannelMessageRouter + TinyElfEngine (подтверждение разрешений)
  3. AuditLogger -> TinyElfEngine (аудит-логирование)
  4. RateLimiter -> ChannelMessageRouter (ограничение частоты запросов)
  5. InputSanitizer -> ChannelMessageRouter (санитизация входных данных)
  6. PromptGuardian -> ChannelMessageRouter (обнаружение инъекций промптов)

Фаза S3: ChannelMagiBridge

Связывает события Channel с MagiService:

const channelMagiBridge = new ChannelMagiBridge(
channelRegistry,
channelMessageRouter,
magiService,
logger,
);

Историческая справка: HTTP-сервер ChannelServer был удалён в cleanup-legacy-mcp (2026-05-19). Инструменты channel_send / channel_list и другие теперь собираются внутри процесса через MagiChannelProvider + MagiChannelHandlers посредством единого реестра; обработчики вызывают ChannelPluginRegistry / ChannelMessageRouter напрямую.

Фаза 3: Регистрация IPC-маршрутов

Все IPC-обработчики регистрируются до создания окна.

const router = new Router(/* 60+ зависимостей сервисов */);
const { skillHubDownloadService } = router.register();

registerAllRouters() внутренне создаёт и регистрирует 68+ экземпляров Router:

Класс RouterПрефикс канала
AuthRouterauth:*
ProjectRouterprojects:*
SessionRoutersessions:*
CompletionRoutercompletion:*
LLMRouterllmProviders:*, llmModels:*
MediaRoutermedia:*
MagiRoutermagi:*
ChannelPluginRouterchannels:*
SecurityRoutersecurity:*
TodoRoutertodo:*
TaskRoutertasks:*
NoteRouternotes:*
SubagentRoutersubagents:*
ElfiRouterelfi:*
EnvironmentRouterenv:*
... и 50+ других маршрутизаторов...

Фаза T1-T3: Todo/Task/Notes

flowchart LR
T1[Фаза T1: TodoService] --> T1a[initialize — загрузить TODO.md]
T2[Фаза T2: TaskService] --> T2a[initialize — сканировать задачи]
T3[Фаза T3: NoteFileService + NoteWatcher] --> T3a[ensureVaultDir]
T3a --> T3b[scanAllNotes + reindex]
T3b --> T3c[Проверка миграции заметок в БД]
ФазаСервисДействие
T1TodoServiceИнициализировать систему задач на Markdown
T2TaskServiceИнициализировать управление задачами через файловую систему + SQLite
T3NoteFileServiceУбедиться, что директория хранилища существует
T3NoteWatcherНаблюдатель за файловой системой
T3Миграция заметокОднократная миграция из БД в .md-файлы
T3Переиндексация при запускеСканирование всех заметок и обновление индекса БД

Фаза W1: Создание окна

Создаёт BrowserWindow после регистрации всех сервисов и IPC-маршрутов:

mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
preload: preloadPath,
},
});

Фаза W2: Обработка WebSocket/протоколов

Инициализация после создания окна:

ШагДействие
1Зарегистрировать обработчик протокола wallpaper://
2Зарегистрировать обработчик протокола media://
3Зарегистрировать обработчик протокола resource://
4Загрузить URL рендерера (dev-сервер или file://)
5Обработать ожидающие Deep Link
6Восстановить экземпляры Channel (autoConnect)
7Настройка политики безопасности контента (Content Security Policy)
8Перехват навигации (isAllowedNavigation)

Время запуска

createServices() записывает время на ключевых фазах:

[INFO] Core services initialized { duration: ~50ms }
[INFO] Feature services created { duration: ~200ms }
[INFO] Agent packages loaded { builtin: N, user: M }
[INFO] Persona packages loaded { builtin: N, user: M }
[INFO] Script plugins loaded { builtin: N, user: M }
[INFO] Magi dispatch services created (Phase S1)
[INFO] MagiService created (Phase S2)
[INFO] ChannelMagiBridge created (Phase S3)
[INFO] IPC handlers registered { duration: ~500ms }

Связанные файлы

ФайлОписание
packages/desktop/app/main/index.tsТочка входа главного процесса; функция createServices()
packages/desktop/app/main/services/routers/index.tsРегистрация маршрутов registerAllRouters()
packages/desktop/app/main/db/index.tsИнициализация базы данных initDatabase()
packages/desktop/app/main/workers/DbClient.tsКлиент Worker базы данных
packages/desktop/app/main/services/infra/logger/LoggerService.tsСервис логирования
packages/desktop/app/main/services/infra/paths/paths.tsУправление путями AppPaths
packages/desktop/app/main/services/platform/config/store/ConfigStore.tsХранилище конфигурации + fs.watch
packages/desktop/app/main/services/agent-core/agent/AgentPackageLoader.tsЗагрузчик пакетов агентов
packages/desktop/app/main/services/agent-core/agent/PersonaPackageLoader.tsЗагрузчик пакетов Persona
packages/desktop/app/main/services/capabilities/tools/script-plugin/ScriptPluginLoader.tsЗагрузчик Script-плагинов
packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tsЗагрузчик Channel-плагинов
packages/desktop/app/main/services/agent-core/magi/MagiService.tsОсновной сервис Magi
packages/desktop/app/main/services/agent-core/magi/AgentOrchestrator.tsОркестратор диспетчеризации агентов
packages/desktop/app/main/services/platform/cron/CronService.tsСервис планировщика задач
packages/desktop/app/main/services/content/workspace/todo/TodoService.tsСервис задач (Todo)
packages/desktop/app/main/services/content/workspace/tasks/TaskService.tsСервис управления задачами
packages/desktop/app/main/services/content/workspace/notes/NoteFileService.tsСервис файлов заметок