본문으로 건너뛰기

Preload API

Elftia는 Electron의 contextBridge를 사용하여 백엔드 기능을 프론트엔드에 안전하게 노출합니다. 프론트엔드는 window.api 전역 객체를 통해 모든 백엔드 기능을 호출합니다.

인증

모든 IPC 호출은 자동으로 인증 토큰을 포함하므로 직접 처리할 필요가 없습니다:

{/* packages/desktop/app/preload/index.ts — simplified illustration */}

const authToken = ipcRenderer.sendSync('auth:bootstrap');

const invoke = (channel: string, ...args: any[]) =>
ipcRenderer.invoke(channel, authToken, ...args);

네임스페이스 인덱스

네임스페이스역할메서드 수
runtime런타임 환경1
authSession인증 세션8
account계정 관리7
projects프로젝트 관리6
files파일 조작12
sessions프로젝트 세션3
chat채팅 핵심 기능6
chatSessions채팅 세션 CRUD5
chatMessages채팅 메시지 CRUD7
chatAssistants채팅 어시스턴트 CRUD6
completionLLM 완성10
llmConfigLLM 설정30+
settings앱 설정4
appPreferences앱 환경설정2
config파일 설정7
theme테마 관리11
mcpMCP 서버12
agentAgent 조작15+
magiMagi 서비스4
elfiElfi 어시스턴트3
image이미지 생성3
video영상 생성3
music음악 생성1
media미디어 관리10
webSearch웹 검색9
windowControls창 제어7
diagnostics시스템 진단6
env환경 감지5
gitGit 조작2
prompts프롬프트 관리9
export내보내기 기능2
channelPluginsChannel 플러그인6

runtime

window.api.runtime.getEnvironment(): Promise<RuntimeEnvironment>

런타임 환경 정보(플랫폼, 버전, 경로 등)를 반환합니다.


authSession

window.api.authSession.getState(): Promise<AuthState>
window.api.authSession.startBrowserLogin(): Promise<void>
window.api.authSession.refresh(): Promise<void>
window.api.authSession.syncProfile(): Promise<void>
window.api.authSession.getAccessToken(): Promise<string>
window.api.authSession.logout(): Promise<void>
window.api.authSession.retrySteamLogin(): Promise<void>
window.api.authSession.subscribe(cb: (state: AuthState) => void): () => void

subscribe는 구독 해제 함수를 반환합니다.


account

window.api.account.list(type?: string): Promise<Account[]>
window.api.account.create(payload: CreateAccountInput): Promise<Account>
window.api.account.delete(id: string): Promise<void>
window.api.account.toggle(id: string, isActive: boolean): Promise<void>
window.api.account.reveal(id: string): Promise<string>
window.api.account.export(options?: ExportOptions): Promise<ExportResult>
window.api.account.clear(type?: string): Promise<void>

projects

window.api.projects.list(): Promise<Project[]>
window.api.projects.create(input: { path: string; displayName?: string }): Promise<Project>
window.api.projects.rename(projectId: string, displayName?: string): Promise<void>
window.api.projects.delete(projectId: string): Promise<void>
window.api.projects.browse(dirPath?: string): Promise<BrowseResult>
window.api.projects.createWorkspace(payload: { path: string; workspaceType: string }): Promise<void>

files

window.api.files.snapshot(projectId: string): Promise<FileTree>
window.api.files.subscribe(projectId: string, cb: (patch: FilePatch) => void): () => void
window.api.files.watch(projectId: string): Promise<void>
window.api.files.unwatch(projectId: string): Promise<void>
window.api.files.read(projectId: string, filePath: string): Promise<string>
window.api.files.readBinary(projectId: string, filePath: string): Promise<Buffer>
window.api.files.write(projectId: string, filePath: string, content: string): Promise<void>
window.api.files.shallow(projectId: string, dirPath?: string): Promise<FileEntry[]>
window.api.files.search(projectId: string, params?: SearchParams): Promise<SearchResult[]>
window.api.files.searchMetrics(): Promise<SearchMetrics>
window.api.files.revealInFolder(filePath: string): Promise<void>
window.api.files.clearCache(projectId: string): Promise<void>

chat

window.api.chat.appendMessage(sessionId: string, msg: any): Promise<void>
window.api.chat.getMessages(sessionId: string, query?: any): Promise<Message[]>
window.api.chat.sendCommand(payload: CommandPayload): Promise<void>
window.api.chat.abortSession(payload: { sessionId: string }): Promise<void>
window.api.chat.checkSessionStatus(payload: { sessionId: string }): Promise<SessionStatus>
window.api.chat.onEvent(cb: (data: ChatEvent) => void): () => void

chatSessions

window.api.chatSessions.list(query?: ListQuery): Promise<ChatSession[]>
window.api.chatSessions.get(id: string): Promise<ChatSession>
window.api.chatSessions.create(input: CreateChatSessionInput): Promise<ChatSession>
window.api.chatSessions.update(id: string, input: UpdateInput): Promise<ChatSession>
window.api.chatSessions.delete(id: string): Promise<void>

chatMessages

window.api.chatMessages.getActivePath(sessionId: string): Promise<Message[]>
window.api.chatMessages.getPage(query: PageQuery): Promise<PageResult>
window.api.chatMessages.getBranches(sessionId: string, parentId: string | null): Promise<Message[]>
window.api.chatMessages.append(sessionId: string, message: MessageInput): Promise<Message>
window.api.chatMessages.update(messageId: string, updates: MessageUpdate): Promise<Message>
window.api.chatMessages.switchBranch(messageId: string): Promise<void>
window.api.chatMessages.delete(messageId: string): Promise<void>

chatAssistants

window.api.chatAssistants.list(): Promise<ChatAssistant[]>
window.api.chatAssistants.get(id: string): Promise<ChatAssistant>
window.api.chatAssistants.create(input: CreateAssistantInput): Promise<ChatAssistant>
window.api.chatAssistants.update(id: string, input: UpdateInput): Promise<ChatAssistant>
window.api.chatAssistants.delete(id: string): Promise<void>
window.api.chatAssistants.setDefault(id: string): Promise<void>

completion

window.api.completion.complete(payload: CompletePayload): Promise<CompleteResult>
window.api.completion.stream(payload: StreamPayload): Promise<{ streamId: string }>
window.api.completion.onStreamEvent(streamId: string, cb: (data: StreamEvent) => void): () => void
window.api.completion.getModels(providerId: string): Promise<Model[]>
window.api.completion.testModel(providerId: string, modelId: string): Promise<TestResult>
window.api.completion.chatInSession(payload: ChatInSessionPayload): Promise<void>
window.api.completion.regenerateInSession(payload: RegeneratePayload): Promise<void>
window.api.completion.onChatCompleted(cb: (data: ChatCompletedEvent) => void): () => void
window.api.completion.createRPFirstMessage(payload: { sessionId: string }): Promise<void>

llmConfig

{/* Provider CRUD */}
window.api.llmConfig.getProviders(): Promise<Provider[]>
window.api.llmConfig.getProvider(id: string): Promise<Provider>
window.api.llmConfig.addProvider(payload: AddProviderInput): Promise<Provider>
window.api.llmConfig.updateProvider(payload: UpdateProviderInput): Promise<Provider>
window.api.llmConfig.deleteProvider(id: string): Promise<void>
window.api.llmConfig.toggleProvider(id: string, enabled: boolean): Promise<void>
window.api.llmConfig.discoverModels(id: string, options?: { forceRefresh?: boolean }): Promise<Model[]>

{/* Presets */}
window.api.llmConfig.getProviderPresets(): Promise<Preset[]>
window.api.llmConfig.addFromPreset(payload: { presetId: string; apiKey?: string }): Promise<Provider>

{/* Model parameters */}
window.api.llmConfig.getAgentDefaultModels(): Promise<DefaultModels>
window.api.llmConfig.setAgentDefaultModels(payload: DefaultModels): Promise<void>
window.api.llmConfig.getGlobalModelParameters(): Promise<GlobalModelParameters>
window.api.llmConfig.setGlobalModelParameters(payload: GlobalModelParameters): Promise<void>

{/* API key pool */}
window.api.llmConfig.getApiKeys(providerId: string): Promise<ApiKeyEntry[]>
window.api.llmConfig.addApiKey(input: ApiKeyInput): Promise<ApiKeyEntry>
window.api.llmConfig.updateApiKey(id: string, updates: ApiKeyUpdate): Promise<ApiKeyEntry>
window.api.llmConfig.deleteApiKey(id: string): Promise<void>
window.api.llmConfig.toggleApiKey(id: string, enabled: boolean): Promise<void>

{/* Import/export */}
window.api.llmConfig.exportConfig(): Promise<ExportedConfig>
window.api.llmConfig.importConfig(payload: ExportedConfig): Promise<void>

settings

window.api.settings.get(key: string): Promise<any>
window.api.settings.set(key: string, value: any): Promise<void>
window.api.settings.getExperimentalFeatures(): Promise<ExperimentalFeatures>
window.api.settings.setExperimentalFeatures(payload: ExperimentalFeatures): Promise<void>

appPreferences

window.api.appPreferences.get(): Promise<AppPreferences>
window.api.appPreferences.update(payload: Partial<AppPreferences>): Promise<void>

config

window.api.config.get(key: string): Promise<any>
window.api.config.getAll(): Promise<Record<string, any>>
window.api.config.getPath(): Promise<string>
window.api.config.set(key: string, value: any): Promise<void>
window.api.config.merge(key: string, patch: any): Promise<void>
window.api.config.reset(key: string): Promise<void>
window.api.config.onChange(cb: (event: ConfigChangeEvent) => void): () => void

theme

window.api.theme.getState(): Promise<ThemeState>
window.api.theme.setMode(mode: 'light' | 'dark' | 'system'): Promise<void>
window.api.theme.updateUserTheme(payload: UserThemeUpdate): Promise<void>
window.api.theme.setCustomCss(css: string): Promise<void>
window.api.theme.setWallpaper(payload: WallpaperConfig): Promise<void>
window.api.theme.setWallpaperPreferences(payload: WallpaperPreferences): Promise<void>
window.api.theme.setRemoteAssetsPolicy(payload: RemoteAssetsPolicy): Promise<void>
window.api.theme.exportProfile(): Promise<ThemeProfile>
window.api.theme.importProfile(payload: ThemeProfile): Promise<void>
window.api.theme.resetProfile(): Promise<void>
window.api.theme.onUpdated(cb: (state: ThemeState) => void): () => void

mcp

window.api.mcp.list(): Promise<McpServer[]>
window.api.mcp.add(payload: AddMcpInput): Promise<McpServer>
window.api.mcp.addJson(payload: JsonMcpConfig): Promise<McpServer>
window.api.mcp.remove(payload: { id: string }): Promise<void>
window.api.mcp.test(payload: { id: string }): Promise<TestResult>
window.api.mcp.discover(payload: { id: string }): Promise<DiscoveryResult>
window.api.mcp.update(payload: { id: string; updates: McpUpdate }): Promise<void>
window.api.mcp.listServerTools(serverId: string): Promise<Tool[]>
window.api.mcp.listAllTools(): Promise<Tool[]>
window.api.mcp.callTool(payload: CallToolInput): Promise<ToolResult>
window.api.mcp.checkDependency(command: string): Promise<boolean>
window.api.mcp.installDependency(command: string): Promise<void>

agent

window.api.agent.checkAvailability(): Promise<boolean>
window.api.agent.getBackends(): Promise<BackendInfo[]>
window.api.agent.createSession(options: CreateSessionOptions): Promise<{ sessionId: string }>
window.api.agent.resumeSession(params: ResumeParams): Promise<void>
window.api.agent.interrupt(sessionId: string): Promise<void>
window.api.agent.respondPermission(params: { requestId: string; result: any }): Promise<void>
window.api.agent.respondAskUserQuestion(params: { requestId: string; result: { answers: Record<string, string>; annotations?: Record<string, { notes?: string }>; cancelled?: boolean } }): Promise<{ success: boolean }>
window.api.agent.getActiveSessions(): Promise<ActiveSession[]>
window.api.agent.isSessionActive(sessionId: string): Promise<boolean>
window.api.agent.selectFolder(): Promise<{ canceled: boolean; path: string | null }>
window.api.agent.onEvent(cb: (data: AgentEvent) => void): () => void
window.api.agent.onPermissionRequest(cb: (data: PermissionRequest) => void): () => void
window.api.agent.onAskUserQuestion(cb: (data: AskUserQuestionRequest) => void): () => void
window.api.agent.onA2UIRender(cb: (data: A2UIEvent) => void): () => void
window.api.agent.onDevPreview(cb: (data: PreviewStatus) => void): () => void

{/* 하위 네임스페이스 */}
window.api.agent.customAgents.list/get/create/update/delete/run/export/import(...)
window.api.agent.mcpRefs.list/attach/detach/toggleEnabled(...)
window.api.agent.agentSessions.create/get/list/update/delete(...)
window.api.agent.sharedComponents.create/get/list/update/delete(...)
window.api.agent.personas.list/get/create/update/delete(...)

image

window.api.image.generate(payload: ImageGeneratePayload): Promise<ImageResult>
window.api.image.generateInSession(payload: SessionImagePayload): Promise<void>
window.api.image.onGenerationCompleted(cb: (data: GenerationCompletedEvent) => void): () => void

video

window.api.video.generate(payload: VideoGeneratePayload): Promise<VideoResult>
window.api.video.generateInSession(payload: SessionVideoPayload): Promise<void>
window.api.video.onGenerationCompleted(cb: (data: GenerationCompletedEvent) => void): () => void

music

window.api.music.generateInSession(payload: SessionMusicPayload): Promise<void>

sessions

window.api.sessions.list(projectId: string, query?: any): Promise<Session[]>
window.api.sessions.delete(projectId: string, sessionId: string): Promise<void>
window.api.sessions.getTokenUsage(projectId: string, sessionId: string): Promise<TokenUsage>

magi

window.api.magi.getStatus(): Promise<MagiStatus>
window.api.magi.getConfig(): Promise<MagiConfig>
window.api.magi.updateConfig(payload: Partial<MagiConfig>): Promise<void>
window.api.magi.resetSession(): Promise<void>

elfi

window.api.elfi.ask(payload: { question: string; context?: string }): Promise<ElfiResponse>
window.api.elfi.getKnowledge(path: string): Promise<string>
window.api.elfi.searchKnowledge(query: string): Promise<KnowledgeResult[]>

media

window.api.media.migrateBase64ToFiles(): Promise<MigrationResult>
window.api.media.getMigrationStatus(): Promise<MigrationStatus>
window.api.media.onMigrationProgress(cb: (data: ProgressEvent) => void): () => void
window.api.media.generateMissingThumbnails(): Promise<MigrationResult>
window.api.media.onThumbnailProgress(cb: (data: ProgressEvent) => void): () => void
window.api.media.compressImage(payload: { base64: string; mimeType: string }): Promise<CompressResult>
window.api.media.compressDataUrl(dataUrl: string): Promise<CompressResult>
window.api.media.compressMany(payload: CompressInput[]): Promise<CompressResult[]>
window.api.media.migrateAttachmentsToFiles(): Promise<MigrationResult>
window.api.media.getAttachmentMigrationStatus(): Promise<MigrationStatus>

env

window.api.env.checkAll(options?: { force?: boolean }): Promise<EnvCheckResult>
window.api.env.installTool(name: string): Promise<void>
window.api.env.repairAll(): Promise<void>
window.api.env.getLastResult(): Promise<EnvCheckResult>
window.api.env.onProgress(cb: (data: ProgressEvent) => void): () => void

git

window.api.git.status(projectId: string): Promise<GitStatus>
window.api.git.diff(projectId: string, filePath: string, options?: { staged?: boolean; isUntracked?: boolean }): Promise<string>

prompts

window.api.prompts.list(query?: ListQuery): Promise<Prompt[]>
window.api.prompts.get(id: string): Promise<Prompt>
window.api.prompts.create(input: CreatePromptInput): Promise<Prompt>
window.api.prompts.update(id: string, input: UpdatePromptInput): Promise<Prompt>
window.api.prompts.delete(id: string): Promise<void>
window.api.prompts.reorder(ids: string[], sortOrders: number[]): Promise<void>
window.api.prompts.incrementUsage(id: string): Promise<void>
window.api.prompts.search(query: string, limit?: number): Promise<Prompt[]>
window.api.prompts.quickList(): Promise<Prompt[]>

export

window.api.export.sessions(input: ExportSessionsInput): Promise<ExportResult[]>
window.api.export.messages(input: ExportMessagesInput): Promise<ExportResult>

channelPlugins

window.api.channelPlugins.listPlugins(): Promise<ChannelPlugin[]>
window.api.channelPlugins.listInstances(): Promise<ChannelInstance[]>
window.api.channelPlugins.add(payload: AddChannelInput): Promise<ChannelInstance>
window.api.channelPlugins.remove(id: string): Promise<void>
window.api.channelPlugins.update(payload: UpdateChannelInput): Promise<void>
window.api.channelPlugins.changeStatus(payload: { id: string; status: ChannelStatus }): Promise<void>

webSearch

window.api.webSearch.search(query: string, providerId: string, options?: SearchOptions): Promise<SearchResult[]>
window.api.webSearch.configureProvider(config: ProviderConfig): Promise<void>
window.api.webSearch.configureProviders(configs: ProviderConfig[]): Promise<void>
window.api.webSearch.isProviderEnabled(providerId: string): Promise<boolean>
window.api.webSearch.getProviderConfig(providerId: string): Promise<ProviderConfig>
window.api.webSearch.getProviders(): Promise<Provider[]>
window.api.webSearch.jinaReader(url: string, options?: { timeout?: number }): Promise<string>
window.api.webSearch.isAvailable(): Promise<boolean>

windowControls

window.api.windowControls.minimize(): Promise<void>
window.api.windowControls.toggleMaximize(): Promise<void>
window.api.windowControls.close(): Promise<void>
window.api.windowControls.toggleDevTools(): Promise<void>
window.api.windowControls.getDeveloperMode(): Promise<boolean>
window.api.windowControls.enableDeveloperMode(): Promise<void>
window.api.windowControls.disableDeveloperMode(): Promise<void>

diagnostics

window.api.diagnostics.dump(): Promise<DiagnosticsData>
window.api.diagnostics.export(options: ExportOptions): Promise<string>
window.api.diagnostics.bundle(options: BundleOptions): Promise<string>
window.api.diagnostics.clearCaches(): Promise<void>
window.api.diagnostics.dbVacuum(): Promise<void>
window.api.diagnostics.dbGetSize(): Promise<number>

이벤트 구독 패턴

모든 onXxx 메서드는 구독 해제 함수를 반환합니다. 일반적인 사용 방법:

useEffect(() => {
const unsubscribe = window.api.chat.onEvent((data) => {
handleChatEvent(data);
});
return unsubscribe; // 컴포넌트가 언마운트될 때 자동으로 구독 해제됩니다
}, []);

주요 이벤트 채널 요약

메서드푸시 채널이벤트 내용
authSession.subscribeauthSession:state인증 상태 변경
chat.onEventchat:event채팅 스트리밍 이벤트
completion.onStreamEventcompletion:stream:{id}완성 스트리밍 이벤트
completion.onChatCompletedchat:completed채팅 완료
image.onGenerationCompletedgeneration:completed이미지 생성 완료
video.onGenerationCompletedvideo:generation:completed영상 생성 완료
agent.onEventagent:eventAgent 이벤트
agent.onPermissionRequestagent:permissionRequest권한 요청
agent.onAskUserQuestionagent:askUserQuestionAgent 질문 (ask_user_question MCP)
theme.onUpdatedtheme:updated테마 변경
config.onChangeconfig:changed설정 변경
files.subscribefiles:patch:{projectId}파일 변경 패치
env.onProgressenv:progress환경 점검 진행 상황