// src/shared/ipc-channels.ts // IPC 채널명 중앙 정의 — 모든 채널명은 이 파일에서만 정의한다. export const IPC_CHANNELS = { VOICE: { START_RECORDING: 'voice:startRecording', STOP_RECORDING: 'voice:stopRecording', CANCEL_RECORDING: 'voice:cancelRecording', GET_STATE: 'voice:getState', SET_MODE: 'voice:setMode', GET_MODE: 'voice:getMode', // Main → Renderer events STATE_CHANGED: 'voice:stateChanged', TRANSCRIPTION_DELTA: 'voice:transcriptionDelta', TRANSCRIPTION_COMPLETE: 'voice:transcriptionComplete', ERROR: 'voice:error', AUDIO_LEVEL: 'voice:audioLevel' }, AUDIO: { GET_DEVICES: 'audio:getDevices', GET_SELECTED_DEVICE: 'audio:getSelectedDevice', SET_SELECTED_DEVICE: 'audio:setSelectedDevice', TEST_DEVICE: 'audio:testDevice', STOP_TEST: 'audio:stopTest', // Main → Renderer events DEVICE_CHANGED: 'audio:deviceChanged', /** 마이크 테스트 레벨 스트림 — done=true가 테스트 종료 신호 (level 0은 무음일 뿐) */ TEST_LEVEL: 'audio:testLevel' }, STT: { GET_STATUS: 'stt:getStatus', GET_MODELS: 'stt:getModels', GET_ACTIVE_MODEL: 'stt:getActiveModel', SET_MODEL: 'stt:setModel', DOWNLOAD_MODEL: 'stt:downloadModel', CANCEL_DOWNLOAD: 'stt:cancelDownload', GET_LANGUAGE: 'stt:getLanguage', SET_LANGUAGE: 'stt:setLanguage', GET_PROVIDERS: 'stt:getProviders', GET_ACTIVE_PROVIDER: 'stt:getActiveProvider', SET_PROVIDER: 'stt:setProvider', GET_PROVIDER_CONFIG: 'stt:getProviderConfig', SET_PROVIDER_CONFIG: 'stt:setProviderConfig', TEST_CONNECTION: 'stt:testConnection', // Main → Renderer events STATUS_CHANGED: 'stt:statusChanged', DOWNLOAD_PROGRESS: 'stt:downloadProgress' }, TTS: { SPEAK: 'tts:speak', STOP: 'tts:stop', GET_VOICES: 'tts:getVoices', GET_ACTIVE_VOICE: 'tts:getActiveVoice', SET_VOICE: 'tts:setVoice', GET_STATUS: 'tts:getStatus', DOWNLOAD_VOICE: 'tts:downloadVoice', // Main → Renderer events STATUS_CHANGED: 'tts:statusChanged', SPEAKING_STATE_CHANGED: 'tts:speakingStateChanged' }, LLM: { GET_STATUS: 'llm:getStatus', GET_MODELS: 'llm:getModels', GET_ACTIVE_MODEL: 'llm:getActiveModel', SET_MODEL: 'llm:setModel', PROCESS: 'llm:process', CANCEL_PROCESS: 'llm:cancelProcess', GET_SERVER_URL: 'llm:getServerUrl', SET_SERVER_URL: 'llm:setServerUrl', PULL_MODEL: 'llm:pullModel', START_SERVER: 'llm:startServer', CHECK_CONNECTION: 'llm:checkConnection', // Phase 3.2: Premium LLM (Supabase llm-proxy → Claude) PREMIUM_GET_STATUS: 'llm:premium:getStatus', PREMIUM_GET_QUOTA: 'llm:premium:getQuota', // Main → Renderer events STATUS_CHANGED: 'llm:statusChanged', PROCESS_PROGRESS: 'llm:processProgress', PULL_PROGRESS: 'llm:pullProgress', /** Phase 3.2: Premium LLM 호출 실패 → Local 자동 fallback 알림 */ PREMIUM_FALLBACK: 'llm:premiumFallback', /** Phase 3.2: 쿼터 경고 (80%+ 또는 초과) */ PREMIUM_QUOTA_WARNING: 'llm:premiumQuotaWarning', /** Phase 3.2: 업그레이드 요구 (쿼터 초과 / 모델 권한 / 인증) */ PREMIUM_UPGRADE_REQUIRED: 'llm:premiumUpgradeRequired' }, HOTKEY: { GET_DICTATION_SHORTCUT: 'hotkey:getDictationShortcut', SET_DICTATION_SHORTCUT: 'hotkey:setDictationShortcut', GET_HANDS_FREE_SHORTCUT: 'hotkey:getHandsFreeShortcut', SET_HANDS_FREE_SHORTCUT: 'hotkey:setHandsFreeShortcut', GET_COMMAND_SHORTCUT: 'hotkey:getCommandShortcut', SET_COMMAND_SHORTCUT: 'hotkey:setCommandShortcut', GET_CAPTION_SHORTCUT: 'hotkey:getCaptionShortcut', SET_CAPTION_SHORTCUT: 'hotkey:setCaptionShortcut', IS_ENABLED: 'hotkey:isEnabled', SET_ENABLED: 'hotkey:setEnabled', START_RECORDING: 'hotkey:startRecording', STOP_RECORDING: 'hotkey:stopRecording', // Main → Renderer events TRIGGERED: 'hotkey:triggered', RECORDING_RESULT: 'hotkey:recordingResult' }, CONFIG: { GET: 'config:get', SET: 'config:set', GET_ALL: 'config:getAll', RESET: 'config:reset', GET_THEME: 'config:getTheme', SET_THEME: 'config:setTheme', GET_LANGUAGE: 'config:getLanguage', SET_LANGUAGE: 'config:setLanguage', GET_AUTO_LAUNCH: 'config:getAutoLaunch', SET_AUTO_LAUNCH: 'config:setAutoLaunch', GET_CLOSE_TO_TRAY: 'config:getCloseToTray', SET_CLOSE_TO_TRAY: 'config:setCloseToTray', // Main → Renderer events CHANGED: 'config:changed' }, HISTORY: { GET_ALL: 'history:getAll', GET_BY_ID: 'history:getById', DELETE: 'history:delete', DELETE_ALL: 'history:deleteAll', SEARCH: 'history:search', EXPORT: 'history:export', // Main → Renderer events ADDED: 'history:added' }, DICTIONARY: { GET_ALL: 'dictionary:getAll', ADD: 'dictionary:add', UPDATE: 'dictionary:update', DELETE: 'dictionary:delete', IMPORT: 'dictionary:import', EXPORT: 'dictionary:export', SEARCH: 'dictionary:search' }, WINDOW: { MINIMIZE: 'window:minimize', MAXIMIZE: 'window:maximize', CLOSE: 'window:close', IS_MAXIMIZED: 'window:isMaximized', SHOW_RECORDING_TIP: 'window:showRecordingTip', HIDE_RECORDING_TIP: 'window:hideRecordingTip', SHOW_RESULT_POPUP: 'window:showResultPopup', HIDE_RESULT_POPUP: 'window:hideResultPopup', TIP_MEASURED: 'window:tipMeasured', // Main → Renderer events TIP_STATE_CHANGED: 'window:tipStateChanged', TIP_PREPARE: 'window:tipPrepare', TIP_SHOW: 'window:tipShow' }, SYSTEM: { GET_PLATFORM: 'system:getPlatform', GET_VERSION: 'system:getVersion', CHECK_MIC_PERMISSION: 'system:checkMicPermission', REQUEST_MIC_PERMISSION: 'system:requestMicPermission', SHOW_NOTIFICATION: 'system:showNotification', OPEN_EXTERNAL: 'system:openExternal', GET_ACTIVE_APP: 'system:getActiveApp', INSERT_TEXT: 'system:insertText', PLAY_SOUND: 'system:playSound', SET_SOUND_ENABLED: 'system:setSoundEnabled', IS_SOUND_ENABLED: 'system:isSoundEnabled' }, STATS: { GET_SUMMARY: 'stats:getSummary', GET_DAILY: 'stats:getDaily', GET_WEEKLY: 'stats:getWeekly', // Main → Renderer events UPDATED: 'stats:updated' }, // ── Phase 10: Memo Tags (10.3) ── MEMO: { GET_TAGS: 'memo:getTags', ADD_TAG: 'memo:addTag', REMOVE_TAG: 'memo:removeTag', GET_ALL_TAGS: 'memo:getAllTags', SEARCH_BY_TAG: 'memo:searchByTag', EXPORT: 'memo:export', }, // ── Phase 10: Voice Commands (10.5) ── VOICE_COMMAND: { GET_ALL: 'voiceCommand:getAll', SET_KEYWORDS: 'voiceCommand:setKeywords', SET_ENABLED: 'voiceCommand:setEnabled', IS_ENABLED: 'voiceCommand:isEnabled', // Main → Renderer events MATCHED: 'voiceCommand:matched', }, // ── Phase 10: Screen Context (10.2) ── CONTEXT: { CAPTURE: 'context:capture', GET_CONFIG: 'context:getConfig', SET_ENABLED: 'context:setEnabled', IS_ENABLED: 'context:isEnabled', }, // ── Phase 10: LLM Chain (10.4) ── CHAIN: { GET_ALL: 'chain:getAll', CREATE: 'chain:create', UPDATE: 'chain:update', DELETE: 'chain:delete', EXECUTE: 'chain:execute', // Main → Renderer events PROGRESS: 'chain:progress', }, // ── Phase 10: Live Caption (10.1) ── CAPTION: { START: 'caption:start', STOP: 'caption:stop', GET_STATE: 'caption:getState', SET_CONFIG: 'caption:setConfig', GET_CONFIG: 'caption:getConfig', /** 렌더러 → 메인: 시스템 오디오 PCM 데이터 전달 */ SYSTEM_AUDIO_DATA: 'caption:systemAudioData', // Main → Renderer events SEGMENT: 'caption:segment', DELTA: 'caption:delta', STATE_CHANGED: 'caption:stateChanged', SESSION_SAVED: 'caption:sessionSaved', /** 메인 → 렌더러: 시스템 오디오 캡처 시작/정지 요청 */ START_SYSTEM_AUDIO: 'caption:startSystemAudio', STOP_SYSTEM_AUDIO: 'caption:stopSystemAudio', }, // ── Phase 12: File Transcription (12.1) ── FILE_TRANSCRIPTION: { START: 'fileTranscription:start', CANCEL: 'fileTranscription:cancel', GET_STATE: 'fileTranscription:getState', // Main → Renderer events PROGRESS: 'fileTranscription:progress', COMPLETE: 'fileTranscription:complete', ERROR: 'fileTranscription:error', }, // ── Phase 12: Meeting Summary (12.2) ── MEETING_SUMMARY: { SUMMARIZE: 'meetingSummary:summarize', GET_SUMMARY: 'meetingSummary:getSummary', EXPORT_MARKDOWN: 'meetingSummary:exportMarkdown', // Main → Renderer events SUMMARY_READY: 'meetingSummary:summaryReady', SUMMARY_PROGRESS: 'meetingSummary:progress', }, // ── Phase 12: Dictation Templates (12.3) ── DICTATION_TEMPLATE: { GET_ALL: 'dictationTemplate:getAll', CREATE: 'dictationTemplate:create', UPDATE: 'dictationTemplate:update', DELETE: 'dictationTemplate:delete', START_SESSION: 'dictationTemplate:startSession', CANCEL_SESSION: 'dictationTemplate:cancelSession', GET_SESSION_STATE: 'dictationTemplate:getSessionState', SET_FIELD_VALUE: 'dictationTemplate:setFieldValue', // Main → Renderer events SESSION_STATE_CHANGED: 'dictationTemplate:sessionStateChanged', FIELD_COMPLETED: 'dictationTemplate:fieldCompleted', SESSION_COMPLETED: 'dictationTemplate:sessionCompleted', }, // ── Phase 13: Voice Conversation (13.1) ── VOICE_CONVERSATION: { START_SESSION: 'voiceConversation:startSession', STOP_SESSION: 'voiceConversation:stopSession', SEND_MESSAGE: 'voiceConversation:sendMessage', GET_STATE: 'voiceConversation:getState', GET_HISTORY: 'voiceConversation:getHistory', CLEAR_HISTORY: 'voiceConversation:clearHistory', CANCEL_RESPONSE: 'voiceConversation:cancelResponse', FINISH_LISTENING: 'voiceConversation:finishListening', /** OpenAI Realtime ephemeral token 발급 (Supabase realtime-token 경유) */ GET_REALTIME_TOKEN: 'voiceConversation:getRealtimeToken', // Main → Renderer events STATE_CHANGED: 'voiceConversation:stateChanged', USER_MESSAGE: 'voiceConversation:userMessage', ASSISTANT_DELTA: 'voiceConversation:assistantDelta', ASSISTANT_MESSAGE: 'voiceConversation:assistantMessage', TTS_STARTED: 'voiceConversation:ttsStarted', TTS_FINISHED: 'voiceConversation:ttsFinished', ERROR: 'voiceConversation:error', AUDIO_LEVEL: 'voiceConversation:audioLevel', }, // ── Phase 13: Local RAG (13.2) ── RAG: { ADD_DOCUMENT: 'rag:addDocument', REMOVE_DOCUMENT: 'rag:removeDocument', GET_DOCUMENTS: 'rag:getDocuments', QUERY: 'rag:query', GET_STATE: 'rag:getState', REINDEX: 'rag:reindex', // Main → Renderer events INDEX_PROGRESS: 'rag:indexProgress', INDEX_COMPLETE: 'rag:indexComplete', QUERY_RESULT: 'rag:queryResult', }, // ── Phase 13: Voice Action / OS Automation (13.3) ── VOICE_ACTION: { EXECUTE: 'voiceAction:execute', GET_PRESETS: 'voiceAction:getPresets', GET_HISTORY: 'voiceAction:getHistory', CLEAR_HISTORY: 'voiceAction:clearHistory', SET_ENABLED: 'voiceAction:setEnabled', IS_ENABLED: 'voiceAction:isEnabled', // Main → Renderer events ACTION_PLANNED: 'voiceAction:actionPlanned', ACTION_EXECUTED: 'voiceAction:actionExecuted', ACTION_ERROR: 'voiceAction:actionError', }, // ── Phase 14: Meeting Mode ── MEETING_MODE: { START_RECORDING: 'meetingMode:startRecording', STOP_RECORDING: 'meetingMode:stopRecording', ADD_MEMO: 'meetingMode:addMemo', GET_STATE: 'meetingMode:getState', GET_SESSIONS: 'meetingMode:getSessions', GET_SESSION: 'meetingMode:getSession', DELETE_SESSION: 'meetingMode:deleteSession', UPDATE_TITLE: 'meetingMode:updateTitle', EXPORT_PDF: 'meetingMode:exportPdf', EXPORT_MARKDOWN: 'meetingMode:exportMarkdown', // Phase 14.5: 문서 생성/편집/내보내기 UPDATE_TRANSCRIPT: 'meetingMode:updateTranscript', GENERATE_DOCUMENT: 'meetingMode:generateDocument', GET_DOCUMENTS: 'meetingMode:getDocuments', UPDATE_DOCUMENT: 'meetingMode:updateDocument', DELETE_DOCUMENT: 'meetingMode:deleteDocument', EXPORT_DOCUMENT: 'meetingMode:exportDocument', EXPORT_TRANSCRIPT: 'meetingMode:exportTranscript', EDIT_SEGMENT: 'meetingMode:editSegment', // Main → Renderer events STATE_CHANGED: 'meetingMode:stateChanged', SEGMENT: 'meetingMode:segment', PROCESSING_PROGRESS: 'meetingMode:processingProgress', SESSION_COMPLETED: 'meetingMode:sessionCompleted', DOC_GENERATING_PROGRESS: 'meetingMode:docGeneratingProgress', POLISH_TRANSCRIPT: 'meetingMode:polishTranscript', DIARIZE: 'meetingMode:diarize', DIARIZATION_PROGRESS: 'meetingMode:diarizationProgress', ERROR: 'meetingMode:error', }, // ── Phase 14.5: Meeting Document Templates ── MEETING_DOC_TEMPLATE: { GET_ALL: 'meetingDocTemplate:getAll', CREATE: 'meetingDocTemplate:create', UPDATE: 'meetingDocTemplate:update', DELETE: 'meetingDocTemplate:delete', }, // ── Phase 15: Meeting AI Chat ── MEETING_CHAT: { SEND: 'meetingChat:send', CANCEL: 'meetingChat:cancel', CLEAR: 'meetingChat:clear', DELTA: 'meetingChat:delta', MESSAGE: 'meetingChat:message', ERROR: 'meetingChat:error', }, // ── Phase 11: License & Monetization ── LICENSE: { GET_INFO: 'license:getInfo', ACTIVATE: 'license:activate', DEACTIVATE: 'license:deactivate', CHECK_FEATURE: 'license:checkFeature', GET_USAGE: 'license:getUsage', GET_ALL_USAGE: 'license:getAllUsage', GET_TIER_COMPARISON: 'license:getTierComparison', OPEN_BILLING: 'license:openBilling', // Main → Renderer events UPGRADE_PROMPT: 'license:upgradePrompt', TIER_CHANGED: 'license:tierChanged', }, CLOUD_SYNC: { GET_STATE: 'cloudSync:getState', SIGN_IN: 'cloudSync:signIn', SIGN_OUT: 'cloudSync:signOut', PUSH_ALL: 'cloudSync:pushAll', PULL_ALL: 'cloudSync:pullAll', HANDLE_CALLBACK: 'cloudSync:handleCallback', // events AUTH_CHANGED: 'cloudSync:authChanged', SYNC_PROGRESS: 'cloudSync:syncProgress', SYNC_COMPLETE: 'cloudSync:syncComplete', SYNC_ERROR: 'cloudSync:syncError', }, // ── Custom Instructions ── INSTRUCTION: { GET_ALL: 'instruction:getAll', GET_BY_ID: 'instruction:getById', CREATE: 'instruction:create', UPDATE: 'instruction:update', DELETE: 'instruction:delete', REORDER: 'instruction:reorder', }, // ── System Audio (Caption loopback) ── SYSTEM_AUDIO: { ENABLE_LOOPBACK: 'system-audio:enable-loopback', DISABLE_LOOPBACK: 'system-audio:disable-loopback', }, // ── Popup Internal Channels (ResultPopup 2-phase) ── POPUP_RESULT: { PREPARE: 'result:prepare', MEASURED: 'result:measured', SHOW: 'result:show', }, // ── Popup Internal Channels (HistoryPopup) ── POPUP_HISTORY: { SHOW_POPUP: 'history:showPopup', ITEM_SELECTED: 'history:itemSelected', POPUP_DISMISSED: 'history:popupDismissed', SHOW_ITEMS: 'history:showItems', SHOW: 'history:show', HIDE: 'history:hide', KEY_EVENT: 'history:keyEvent', }, // ── Popup Internal Channels (CommandPopup) ── POPUP_COMMAND: { SELECTED: 'command:selected', DISMISSED: 'command:dismissed', SHOW_ITEMS: 'command:showItems', SHOW: 'command:show', HIDE: 'command:hide', KEY_EVENT: 'command:keyEvent', }, // ── Popup Internal Channels (Caption) ── POPUP_CAPTION: { HIDE: 'caption:hide', }, // ── Voice Partial Transcript (RecordingTip) ── VOICE_PARTIAL: { PARTIAL_TRANSCRIPT: 'voice:partialTranscript', }, // ── Clipboard ── CLIPBOARD: { COPY: 'clipboard:copy', }, // ── App-wide events ── APP: { DATA_CHANGED: 'app:dataChanged', }, ONLINE_AUTH: { REGISTER: 'onlineAuth:register', LOGIN: 'onlineAuth:login', LOGOUT: 'onlineAuth:logout', GET_USER: 'onlineAuth:getUser', }, // ── Ad Monetization & Mediation ── ADS: { GET_CONFIG: 'ads:getConfig', SET_CONFIG: 'ads:setConfig', REQUEST_AUCTION: 'ads:requestAuction', RECORD_IMPRESSION: 'ads:recordImpression', RECORD_CLICK: 'ads:recordClick', CLAIM_REWARD: 'ads:claimReward', GET_REVENUE_STATS: 'ads:getRevenueStats', GET_SETTLEMENTS: 'ads:getSettlements', REQUEST_PAYOUT: 'ads:requestPayout', GET_PUBLISHER_ACCOUNT: 'ads:getPublisherAccount', SET_PUBLISHER_ACCOUNT: 'ads:setPublisherAccount', }, // ── Customer Assistance (CA/CS) & Diagnostics ── SUPPORT: { GET_DIAGNOSTICS: 'support:getDiagnostics', QUERY_AI: 'support:queryAI', CREATE_TICKET: 'support:createTicket', GET_TICKETS: 'support:getTickets', CHECK_REFUND: 'support:checkRefund', }, // ── Multi-PG Payment & Billing ── PAYMENT: { CREATE_CHECKOUT_SESSION: 'payment:createCheckoutSession', VERIFY_PAYMENT: 'payment:verifyPayment', GET_SUBSCRIPTION_STATUS: 'payment:getSubscriptionStatus', CANCEL_SUBSCRIPTION: 'payment:cancelSubscription', }, } as const // 타입 유틸리티: 채널명 유니온 추출 type NestedValues = T extends Record ? V extends string ? V : NestedValues : never export type IPCChannel = NestedValues