Phase 14 구현: 회의 모드 (Meeting Mode)

실시간 녹음 + 타임스탬프 메모 + STT 전사 + LLM 구조화 회의록 + PDF/MD 내보내기.
CaptionService 연동, 동시 사용 충돌 방지, 긴 회의 2-pass 요약 지원.
DB 2테이블, IPC 15채널, UI 3뷰(목록/녹음/상세), 12개 locale i18n.
This commit is contained in:
Yun Chan 2026-04-08 01:16:52 +09:00
parent dd68fc9ccd
commit d0c4f9ee53
38 changed files with 2550 additions and 769 deletions

View file

@ -151,6 +151,14 @@ export enum ErrorCode {
VoiceActionBlocked = 877,
VoiceActionInvalidPlan = 878,
// === Phase 14: Meeting Mode (880-889) ===
MeetingAlreadyRecording = 880,
MeetingNotRecording = 881,
MeetingProcessingFailed = 882,
MeetingSessionNotFound = 883,
MeetingExportFailed = 884,
MeetingPdfFailed = 885,
// === Config (800-849) ===
ConfigReadFailed = 800,
ConfigWriteFailed = 801,

View file

@ -305,6 +305,26 @@ export const IPC_CHANNELS = {
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',
// Main → Renderer events
STATE_CHANGED: 'meetingMode:stateChanged',
SEGMENT: 'meetingMode:segment',
PROCESSING_PROGRESS: 'meetingMode:processingProgress',
SESSION_COMPLETED: 'meetingMode:sessionCompleted',
ERROR: 'meetingMode:error',
},
// ── Phase 11: License & Monetization ──
LICENSE: {
GET_INFO: 'license:getInfo',

View file

@ -1262,3 +1262,99 @@ export interface VoiceActionErrorEvent {
message: string
userText: string
}
// ============================================================
// Phase 14: Meeting Mode
// ============================================================
export type MeetingModeState = 'idle' | 'recording' | 'processing' | 'completed' | 'error'
export interface MeetingMemo {
id: string
sessionId: string
content: string
/** 녹음 시작 기준 상대 타임스탬프 (ms) */
timestampMs: number
createdAt: number
}
export interface MeetingSessionSummary {
id: string
title: string | null
status: 'recording' | 'processing' | 'completed' | 'error'
startedAt: number
endedAt: number | null
durationMs: number | null
memoCount: number
}
export interface MeetingSessionDetail extends MeetingSessionSummary {
rawTranscript: string | null
minutesMarkdown: string | null
minutes: MeetingMinutes | null
memos: MeetingMemo[]
sttModel: string | null
llmModel: string | null
errorMessage: string | null
}
export interface MeetingMinutes {
summary: string
decisions: string[]
actionItems: Array<{ task: string; assignee?: string; deadline?: string }>
timeline: Array<{ time: string; content: string; type: 'transcript' | 'memo' }>
}
export interface MeetingSessionPage {
sessions: MeetingSessionSummary[]
total: number
page: number
pageSize: number
totalPages: number
}
export interface MeetingStartResult {
sessionId: string
}
export interface MeetingAddMemoParams {
content: string
}
export interface MeetingGetSessionsParams {
page: number
pageSize: number
}
export interface MeetingGetSessionParams {
sessionId: string
}
export interface MeetingDeleteSessionParams {
sessionId: string
}
export interface MeetingExportParams {
sessionId: string
}
export interface MeetingModeStateInfo {
state: MeetingModeState
sessionId: string | null
elapsedMs: number
memoCount: number
segmentCount: number
}
export type MeetingProcessingStep =
| 'merging'
| 'generating'
| 'parsing'
| 'saving'
| 'notifying'
export interface MeetingProcessingProgress {
sessionId: string
step: MeetingProcessingStep
percent: number
}