メインコンテンツまでスキップ

起動フェーズ

Elftia のメインプロセス起動フローは 13 のフェーズに分かれており、それぞれの責務と依存関係が明確に定義されています。すべてのフェーズのコードは、packages/desktop/app/main/index.ts 内の createServices() 関数にあります。

起動フェーズの概要

flowchart TB
P0[Phase 0: Protocol Registration + Logger]
P1[Phase 1: Core Services]
P2[Phase 2: Feature Services]
P25[Phase 2.5: Package Loading]
P26[Phase 2.6: Package Sync]
P27[Phase 2.7: Package Management Service]
PS1[Phase S1: Magi Dispatch]
PS2[Phase S2: MagiService]
PS25[Phase S2.5: CronService]
PC1[Phase C1: Channel Plugins]
PS3[Phase S3: ChannelMagiBridge]
P3[Phase 3: IPC Route Registration]
PT[Phase T1-T3: Todo/Task/Notes]
PW1[Phase W1: Window Creation]
PW2[Phase W2: WebSocket/Protocol]

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

Phase 0: プロトコル登録 + Logger

app.whenReady() の前に実行されます。カスタムプロトコルとコアロギングサービスを登録します。

flowchart LR
A[Register elftia:// protocol] --> B[Register privileged schemes]
B --> C[wallpaper://]
B --> D[media://]
B --> E[resource://]
ステップアクション説明
1app.setAsDefaultProtocolClient('elftia')Deep Link プロトコルを登録
2protocol.registerSchemesAsPrivileged()wallpaper/media/resource の privileged protocol を登録
3new LoggerService()ロギングサービスを作成(Winston + daily-rotate)
4setIpcLogger(logger)IPC レイヤーの logger を設定
5new ErrorHandler(logger)グローバルエラーハンドラーを作成
6setIpcErrorHandler(errorHandler)IPC レイヤーのエラーハンドラーを設定
7new AutoUpdateService(logger)自動更新サービスを作成
8new DownloadService(logger)ダウンロードサービスを作成
9new WebUpdateService(logger, downloadManager)Web 更新サービスを作成

主要ファイル: packages/desktop/app/main/services/infra/logger/LoggerService.ts, packages/desktop/app/main/services/infra/error/ErrorHandler.ts

Phase 1: コアサービス

アプリケーションの実行に必要な基盤サービスを作成します。これらのサービスには外部依存関係がありません。

flowchart LR
RT[RuntimeService] --> AP[AppPaths]
AP --> DB[DbClient + ready]
DB --> SS[SettingsService]
SS --> CS[ConfigStore]
CS --> Migrate[Config Migration]
Migrate --> Auth[Auth Service Chain]
Auth --> WC[WindowControlsService]
ステップサービス依存関係説明
1RuntimeServiceなしランタイム情報(バージョン、プラットフォーム、チャネル)
2AppPathsなしパス解決
3DbClientAppPathsDatabase Worker の作成
4await db.ready()DbClientWorker の初期化完了まで ブロッキング待機
5initDatabase()db.readyDrizzle ORM + WAL + migrate
6SettingsServiceAppPathsアプリケーション設定
7ConfigStoreAppPathselectron-store の config ファイル
8migrateSettingsToConfigStore()Settings, ConfigStoreSQLite -> config.json の移行
9settings.setConfigStore(configStore)-Delegate パターンの接続
10configStore.startWatching()-fs.watch による config のホットリロード
11AccountServiceAppPathsユーザー認証情報
12AuthTokenStoreAccountServiceToken ストレージ
13AuthSessionServiceRuntime, AuthStore, AuthApiAuth セッション
14AppPreferencesServiceConfigStoreアプリケーション設定値
15WindowControlsServiceSettingsウィンドウ制御

重要ポイント: await db.ready() は、処理を進める前に SQLite Worker がスキーマ作成を完了したことを保証する ブロッキングポイント です。これにより、初回起動時に 2 つの接続が同時に書き込むことで発生する SQLITE_BUSY エラーを防ぎます。

Phase 2: 機能サービス

軽量な機能サービスを作成します。重い初期化は使用時まで遅延されます。

サービス依存関係説明
ConfigManagerLogger, AppPathsConfig ファイル管理
SecurityServiceLoggerAES-256-GCM 暗号化
PerformanceMonitorLoggerパフォーマンス監視
CacheServiceLogger汎用キャッシュ
DatabaseOptimizerLogger, DbClientSQLite 最適化
NotificationServiceLoggerデスクトップ通知
PluginManagerLoggerPlugin ライフサイクル
ProjectServiceDbClient, AccountServiceプロジェクト管理
DiagnosticsServiceAppPaths, ProjectService診断サービス
ChatServiceLoggerチャットサービス
McpServiceLoggerMCP server 管理
LLMConfigServiceAppPaths, DbClientLLM 設定
CompletionServiceAppPaths, LLMConfigServiceLLM completion
ApiKeyPoolServiceDB, CompletionService複数キーの round-robin
ElfiServiceConfigStore, LLMConfig, CompletionElfi assistant
MediaConfigServiceAppPaths, DbClientメディア設定
ImageGenerationServiceMediaConfig画像生成
ThemeServiceSettings, AuthSessionテーマ管理
AgentServiceDbClient, Settings, LoggerAgent サービス
TransformerService-リクエスト変換
WebSearchService-Web 検索
EngineDispatcher + engine registration各 engine の依存関係Engine dispatch

Engine 登録順序

{/* Engine registration */}
engineDispatcher.registerEngine(new ApiEngine(...));
engineDispatcher.registerEngine(new ChatEngine(...));
engineDispatcher.registerEngine(new ClaudeSdkEngine(...));
engineDispatcher.registerEngine(new CliRunnerEngine(...));
engineDispatcher.registerEngine(new TinyElfEngine(...));
engineDispatcher.registerEngine(new STChatEngine(...));

Phase 2.5: パッケージ読み込み

Agent パッケージ、Persona パッケージ、Script plugin をディスクからメモリに読み込みます。

flowchart TB
subgraph "Phase 2.5a: Agent Packages"
AL[AgentPackageLoader] --> BP[Load builtin packages]
BP --> UP[Load user packages]
UP --> AR[AgentPackageRegistry]
end

subgraph "Phase 2.5b: Persona Packages"
PL[PersonaPackageLoader] --> BPP[Load builtin packages]
BPP --> UPP[Load user packages]
UPP --> PR[PersonaPackageRegistry]
end

subgraph "Phase 2.5c: Script Plugins"
SL[ScriptPluginLoader] --> BSP[Load builtin plugins]
BSP --> USP[Load user plugins]
USP --> SR[ScriptPluginRegistry]
end

読み込みパス(二重ディレクトリパターン):

パッケージ種別Builtin Path(packaged)Builtin Path(dev)User Path
Agentresources/agent-packages/../../agent-packages/{userData}/agent-packages/
Personaresources/persona-packages/../../persona-packages/{userData}/persona-packages/
Scriptresources/script-plugins/../../script-plugins/{userData}/script-plugins/

Phase 2.6-2.7: パッケージ同期と管理

フェーズアクション説明
2.6PackageSyncService.syncAll()メモリ内のパッケージ定義をデータベースへ同期(FK anchor の upsert + persona データ)
2.7new AgentPackageService(...)install/uninstall をサポートするパッケージ管理サービスを作成

Phase S1: Magi Dispatch

Agent のオーケストレーションと 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 -.->|injected into| TE[TinyElfEngine]
ステップサービス説明
1AgentManagementServiceAgent CRUD + package registry クエリ
2InternalSessionEventBusSession event の publish/subscribe
3AgentDiscoveryスケジュール可能な Agent roster(DB + package registry から検出)
4AgentOrchestratorAgent dispatch とオーケストレーション、API dispatch handler
5MessageRouterデュアルモードの message routing(direct / Orchestrator 経由)
6SessionDispatcherImplセッション横断 dispatch の実装
7TinyElfEngine へ注入tinyElfEngine.setSessionDispatcher(sessionDispatcher)
8SubagentRegistry.setDb(db)Subagent registry の write-through persistence

履歴メモ: DispatchServer HTTP dispatch server は cleanup-legacy-mcp(2026-05-19)で削除されました。dispatch tool は現在、統合 registry を通じて MagiDispatchProvider + MagiDispatchHandlers によりプロセス内で構成されます。handlers は HTTP を経由せず、AgentOrchestrator / AgentDiscovery を直接呼び出します。CLI subprocess は、中央の services/capabilities/tools/mcp-builtin/BuiltinMcpHttpServer.ts を通じてこれにアクセスします。

Phase S2: MagiService

コアのメッセージ処理サービスを作成し、すべての依存関係を注入します。

{/* MagiService dependency injection chain */}
const magiService = new MagiService(
magiWorkspace, magiSession, magiOptionsBuilder,
magiOrchestrator, magiMessageRouter, magiEventBus,
llmConfig, logger, configStore,
);

// Deferred injection (avoids circular dependencies)
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 server list が変更されると、Magi workspace に自動で同期され、active session がホットリロードされます。

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

Phase S2.5: CronService

Cron scheduled task サービスを作成します:

注入目的
setNotificationService(notification)デスクトップ通知
setNotificationChecker(...)通知設定を確認
setAgentExecutor(...)MagiService 経由で scheduled task を実行
setStatusBroadcaster(...)タスク状態をフロントエンドへブロードキャスト

Phase C1: Channel Plugins

Channel plugin を検出、読み込み、登録します。

flowchart TB
CL[ChannelPluginLoader] --> Discover[discover plugins]
Discover --> Load[load each plugin]
Load --> CR[ChannelPluginRegistry.registerPlugin]
CR --> CM[ChannelMarketplaceService<br/>async fetch remote manifest]

subgraph "Security Service Wiring"
UPS[UserPermissionService] --> CMR[ChannelMessageRouter]
CPG[ChannelPermissionGate] --> CMR
AL[AuditLogger] --> TE[TinyElfEngine]
RL[RateLimiter] --> CMR
IS[InputSanitizer] --> CMR
PG[PromptGuardian] --> CMR
end

CR --> CMR

読み込みパス(二重ディレクトリパターン):

ソースPath(packaged)Path(dev)
Bundled(read-only)resources/bundled-channel-plugins/elftia-channels/dist-plugins/
Marketplace(writable){userData}/channel-plugins/same

Security service wiring order:

  1. UserPermissionService -> ChannelMessageRouter(ユーザー権限チェック)
  2. ChannelPermissionGate -> ChannelMessageRouter + TinyElfEngine(権限確認)
  3. AuditLogger -> TinyElfEngine(監査ログ)
  4. RateLimiter -> ChannelMessageRouter(レート制限)
  5. InputSanitizer -> ChannelMessageRouter(入力サニタイズ)
  6. PromptGuardian -> ChannelMessageRouter(prompt injection 検出)

Phase S3: ChannelMagiBridge

Channel event を MagiService に橋渡しします:

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

履歴メモ: ChannelServer HTTP server は cleanup-legacy-mcp(2026-05-19)で削除されました。channel_send / channel_list などの tool は現在、統合 registry を通じて MagiChannelProvider + MagiChannelHandlers によりプロセス内で構成されます。handlers は ChannelPluginRegistry / ChannelMessageRouter を直接呼び出します。

Phase 3: IPC ルート登録

すべての IPC handler は、ウィンドウ作成の 前に 登録されます。

const router = new Router(/* 60+ service dependencies */);
const { skillHubDownloadService } = router.register();

registerAllRouters() は内部で 68 個以上の Router instance を作成して登録します:

Router ClassChannel Prefix
AuthRouterauth:*
ProjectRouterprojects:*
SessionRoutersessions:*
CompletionRoutercompletion:*
LLMRouterllmProviders:*, llmModels:*
MediaRoutermedia:*
MagiRoutermagi:*
ChannelPluginRouterchannels:*
SecurityRoutersecurity:*
TodoRoutertodo:*
TaskRoutertasks:*
NoteRouternotes:*
SubagentRoutersubagents:*
ElfiRouterelfi:*
EnvironmentRouterenv:*
... and 50+ other routers...

Phase T1-T3: Todo/Task/Notes

flowchart LR
T1[Phase T1: TodoService] --> T1a[initialize — load TODO.md]
T2[Phase T2: TaskService] --> T2a[initialize — scan tasks]
T3[Phase T3: NoteFileService + NoteWatcher] --> T3a[ensureVaultDir]
T3a --> T3b[scanAllNotes + reindex]
T3b --> T3c[DB notes migration check]
フェーズサービスアクション
T1TodoServiceMarkdown to-do system を初期化
T2TaskServicefilesystem + SQLite task management を初期化
T3NoteFileServicevault directory の存在を保証
T3NoteWatcherFilesystem watcher
T3Notes migrationDB から .md files への一回限りの移行
T3Startup reindexすべての notes をスキャンして DB index を更新

Phase W1: ウィンドウ作成

すべての service と IPC route が登録された後に BrowserWindow を作成します:

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

Phase W2: WebSocket/Protocol 処理

ウィンドウ作成後の初期化:

ステップアクション
1wallpaper:// protocol handler を登録
2media:// protocol handler を登録
3resource:// protocol handler を登録
4renderer URL(dev server または file://)を読み込み
5保留中の Deep Link を処理
6Channel instance を復元(autoConnect)
7Content Security Policy 設定
8Navigation interception(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メインプロセス entry、createServices() 関数
packages/desktop/app/main/services/routers/index.tsregisterAllRouters() route 登録
packages/desktop/app/main/db/index.tsinitDatabase() database 初期化
packages/desktop/app/main/workers/DbClient.tsDatabase Worker client
packages/desktop/app/main/services/infra/logger/LoggerService.tsLogging service
packages/desktop/app/main/services/infra/paths/paths.tsAppPaths path 管理
packages/desktop/app/main/services/platform/config/store/ConfigStore.tsConfig store + fs.watch
packages/desktop/app/main/services/agent-core/agent/AgentPackageLoader.tsAgent package loader
packages/desktop/app/main/services/agent-core/agent/PersonaPackageLoader.tsPersona package loader
packages/desktop/app/main/services/capabilities/tools/script-plugin/ScriptPluginLoader.tsScript plugin loader
packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tsChannel plugin loader
packages/desktop/app/main/services/agent-core/magi/MagiService.tsMagi core service
packages/desktop/app/main/services/agent-core/magi/AgentOrchestrator.tsAgent dispatch orchestrator
packages/desktop/app/main/services/platform/cron/CronService.tsScheduled task service
packages/desktop/app/main/services/content/workspace/todo/TodoService.tsTo-do service
packages/desktop/app/main/services/content/workspace/tasks/TaskService.tsTask management service
packages/desktop/app/main/services/content/workspace/notes/NoteFileService.tsNote file service