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

メインプロセス設計

メインプロセスは Elftia の中核であり、すべてのビジネスロジック、外部 API 呼び出し、データベース操作、セキュリティ制御を担当します。エントリーファイルは packages/desktop/app/main/index.ts です。

サービスモジュール概要

メインプロセスには 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

ドメイン別サービス一覧

DomainServiceDescription
Core (core/)LoggerServiceWinston + daily-rotate-file によるロギング
AppPathsアプリケーションパスの解決(userData、dbPath、configDir など)
RuntimeServiceランタイム情報(バージョン、チャネル、プラットフォーム)
CacheService汎用キャッシュ(TTL 期限切れクリーンアップ)
ConfigManager設定ファイル管理
SecurityServiceAES-256-GCM 暗号化サービス
CryptoServicePBKDF2 鍵導出 + 暗号化/復号
PerformanceMonitorパフォーマンス監視とアラート
ErrorHandlerグローバルエラー処理
PluginManagerプラグインライフサイクル管理
DatabaseOptimizerSQLite 最適化(VACUUM、ANALYZE)
CommandServiceコマンド実行サービス
Auth (auth/)AuthServiceIPC 認証トークン検証
AuthSessionServiceログインセッション + Deep Link 処理
AuthTokenStore認証トークンの永続化
TokenRefreshService認証トークンの自動更新
Account (account/)AccountServiceユーザー認証情報管理
AccountTokensServiceOAuth トークン管理
LimitsServiceメンバーシップ制限チェック
LLM (llm/)LLMConfigServiceプロバイダー/モデル設定 CRUD
TransformerServiceリクエスト形式変換チェーン
Completion (completion/)CompletionServiceLLM API 呼び出しのエントリーポイント
ApiKeyPoolService複数キーのラウンドロビン + セッションアフィニティ
Engine (engine/)EngineDispatcherエンジン登録とルーティング
ApiEngineメディア API エンジン
ChatEngine汎用チャットエンジン
ClaudeSdkEngineClaude Agent SDK エンジン
TinyElfEngine組み込み Agent エンジン
CliRunnerEngineCLI サブプロセスエンジン
STChatEngineRP チャットパイプラインエンジン
Magi Orchestration (magi/)MagiServiceコアメッセージ処理サービス(Clawia の MCP セットを services/capabilities/tools/mcp-builtin/ レジストリ経由で収集する assembleMagiMcps を含む。buildTinyElfDirectMcpServers は TinyElf のエントリーポイント)
MagiSessionServiceセッション永続化管理
MagiWorkspaceServiceワークスペースディレクトリ管理
MagiSdkOptionsBuilderプロンプト構築(V1-V4)+ ユーザー MCP 注入(setUserMcpServers / getMcpServers(allowedUserMcpNames) / getDirectMcpServers)+ Channel プローブ。組み込み MCP アセンブリは Phase 5.9 以降 mcp-providers/ に移行済み
AgentOrchestratorAgent ディスパッチとオーケストレーション
AgentDiscoveryスケジュール可能な Agent 名簿
MessageRouterデュアルモードメッセージルーティング
ChannelMagiBridgeChannel から Magi へのブリッジ
SessionEventBusセッションイベントバス
SessionDispatcherImplクロスセッションディスパッチ実装
SubagentRegistryサブエージェント状態追跡
Built-in MCP Registry (mcp-providers/)McpProviderRegistry12 個の組み込みプロバイダー + 動的 ScriptPlugin プロバイダーファクトリ。すべての組み込み MCP ハンドラーはインプロセスで実行されます。SDK は直接呼び出し、TinyElf は ITool として登録し、CLI は中央の BuiltinMcpHttpServer HTTP ブリッジ経由でアクセスします。DispatchServer / ChannelServer / VisionAssistServer HTTP ブリッジは cleanup-legacy-mcp(2026-05-19)で削除されました
BuiltinMcpHttpServer中央 HTTP MCP ブリッジ(セッション単位スコープ)。すべてのインプロセス MCP はこれを通じて CLI エンジンに公開されます
assembleMcpForSession(ctx)統一アセンブリエントリー(SDK + TinyElf。sdkServers / tinyElfServers / promptFragments / allowedTools / cleanups を含む McpAssembly を返します)
applyAssembly.tsapplyAssemblyToSdkOptions / applyAssemblyToTinyElfConfigMcpAssembly をエンジンオプションにマージします
contextBuilders.tsbuildAssemblyContextFor{Clawia,Agent} — 呼び出し元の視点から AssemblyContext を構築します
registerBuiltinMcpProviders.ts1 回限りの起動時アセンブリポイント(ScriptPlugin の同名エイリアス処理を含む)
builtin/<Name>Provider.ts組み込み MCP ごとに 1 つの Provider モジュール(12 個の静的 + 動的 ScriptPlugin ファクトリ)
Channel (channel/)ChannelPluginLoaderプラグインの検出と読み込み
ChannelPluginRegistryプラグイン登録とインスタンス管理
ChannelMessageRouterメッセージトリガールーティング
ChannelMarketplaceServiceプラグインマーケットプレイス
Security (security/)ExecutionFirewallファイルパスファイアウォール
GuardianAgentAI ツール呼び出しレビュー
PromptGuardianプロンプトインジェクション検出
RateLimiterレート制限
InputSanitizer入力サニタイズ
UserPermissionServiceユーザー権限管理
ChannelPermissionGateChannel 権限確認
AuditLoggerセキュリティ監査ログ
Media (media/)ImageGenerationService画像生成
MusicGenerationService音楽生成
MediaStorageServiceメディアファイルストレージ
MediaResourceServiceコンテンツアドレス指定リソースストレージ
MediaConfigServiceメディアプロバイダー設定
AsrService / TtsService音声認識/合成
Project (project/)ProjectServiceプロジェクト CRUD
FileIndexServiceファイルインデックスサービス
GitServiceGit 操作
Search (search/)WebSearchService統一検索エントリーポイント
JinaProvider / TavilyProvider / SearxngProvider検索エンジンアダプター
UI (ui/)ThemeServiceテーマ管理
WindowControlsServiceウィンドウコントロール
TrayServiceシステムトレイ
NotificationServiceデスクトップ通知
Config (config/)ConfigStoreelectron-store + fs.watch ホットリロード
Cron (cron/)CronServiceCron スケジュールタスクのディスパッチ
MCP (mcp/)McpServiceMCP サーバー管理
Plugins (plugin/)ScriptPluginLoaderスクリプトプラグイン読み込み
ScriptPluginRegistryスクリプトプラグインレジストリ
ScriptPluginBridgeManagerプラグインブリッジ管理

IPC Router アーキテクチャ

フロントエンドからバックエンドへのすべての通信は 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 Directory/FileChannel PrefixMain Channel Count
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+
MagiRoutermagi:*10+
ChannelPluginRouterchannels:*8+
sillytavern/characterCards:*, worldInfo:*, regexScripts:*, groupChat:*, etc.25+
Othersmcp:*, webSearch:*, todo:*, tasks:*, notes:*, tags:*, cron:*, elfi:*, etc.30+

Worker スレッドパターン

時間のかかる I/O 操作は、メインスレッドをブロックしないように Worker Threads で実行されます。

DbClient — データベース 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 で送信されます
  • Ready wait: await db.ready() により、Worker の初期化(スキーマ作成)が完了してから使用することを保証します
  • Error forwarding: Worker エラーは EventEmitter を通じて上位へ伝播します

Worker スレッド一覧

Worker FilePurposeCommunication
db.worker.tsSQLite データベースの読み書き(100 個以上の RPC メソッド)DbClient RPC
fileSearch.worker.tsファイル検索(あいまい一致)MessagePort
fileWatcher.worker.tsファイルシステム監視(chokidar)MessagePort
mcp.worker.tsMCP サーバープロセス管理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

すべてのアプリケーションディレクトリパスを一元管理します。

PropertyPathPurpose
userData{appData}/elftia/アプリケーションデータルート
dbPath{userData}/elftia.dbSQLite データベース
configDir{userData}/config/設定ファイルディレクトリ
resourcesDir{userData}/resources/メディアリソース
diagnosticsDir{userData}/diagnostics/診断データ
logsDir{userData}/logs/ログファイル

関連ファイル

FileDescription
packages/desktop/app/main/index.tsメインプロセスのエントリー。すべてのサービスの作成と起動
packages/desktop/app/main/services/routers/index.tsルート登録センター、registerAllRouters()
packages/desktop/app/main/services/routers/BaseRouter.tsRouter ベースクラス
packages/desktop/app/main/ipc/safe-handle.tssecureHandle IPC セキュリティラッパー
packages/desktop/app/main/workers/DbClient.tsデータベース Worker クライアント
packages/desktop/app/main/workers/db.worker.tsデータベース Worker 実装
packages/desktop/app/main/workers/types.tsWorker 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エンジンディスパッチャー