Commit graph

22 commits

Author SHA1 Message Date
yunchan8804
45a580878a feat(V2-1a): Monorepo 구조 전환 — apps/desktop으로 V1 이동
- npm workspaces 루트 (apps/*, packages/*) 세팅
- V1 전체를 apps/desktop/으로 git mv (src, resources, tests, sidecar,
  scripts, electron.vite.config.ts, electron-builder.yml, vitest.config.ts,
  tsconfig.node.json, tsconfig.web.json)
- apps/desktop/package.json 신규 (name=@d3ro/desktop)
- productName: 'd3ro-voice' 명시 — app.getName()을 고정하여 userData 경로
  %APPDATA%\d3ro-voice\ 그대로 유지 (기존 DB/설정 연속성 보장)
- 루트 package.json을 workspace 루트로 재구성, 공통 devDep만 유지
  (typescript, eslint, prettier)
- turbo.json, tsconfig.base.json 추가 (Turborepo 자체 설치는 별도 sub-phase)
- memory/project_status.md 생성 (규칙 13)

검증:
- npm run typecheck 통과
- npm run build 통과 (electron-vite main+preload+renderer)
- npm run dev 실제 실행 → DB/핫키/Ollama 자동 실행 모두 정상
2026-04-08 14:04:41 +09:00
yunchan8804
3a160b9032 feat: Ollama 미실행 시 설치 경로 탐색 후 자동 스폰
- LocalLLMService.ensureRunning(): /api/tags 핑 → 바이너리 탐색 → detached 스폰
- 플랫폼별 기본 설치 경로 + where/which PATH 폴백
- bootstrap initLLMPolling에서 startPolling 전에 호출
- 감지는 기존 5초 폴링이 담당, 블로킹 없음
2026-04-08 13:49:42 +09:00
Yun Chan
d4928ffa60 Phase 14.5 구현: 회의 모드 고도화 — 다중 문서 생성/편집/내보내기
PLAUD 수준의 기능 확장:
- 전사 편집: 인라인 편집 + 원본 보존 + 수정됨 표시(점선 밑줄)
- 다중 문서 생성: 회의록/보고서/아이디어노트/커스텀 템플릿
- MD 에디터: 렌더링/편집 토글 (react-markdown + remark-gfm)
- 상세 페이지 리디자인: 풀스크린 탭 전환 구조
- 내보내기: MD, PDF, TXT, DOCX 4종 (docx 패키지)
- 커스텀 프롬프트 템플릿 저장/재사용 (electron-store)
- SSOT: 마크다운 파싱 유틸 추출, 후처리에서 자동 문서 생성 제거

DB: meeting_documents 테이블 + edited_transcript 컬럼
IPC: 8+4 채널, 서비스 2개(MeetingModeService 확장 + MeetingDocTemplateService 신규)
UI: 8개 신규 컴포넌트 (meeting/ 디렉토리), 12개 locale i18n
2026-04-08 09:53:54 +09:00
Yun Chan
acab319589 fix: MeetingModePage 렌더링 크래시 수정
d3roPalette.indicator → d3roPalette.tag, d3roTypo.reading → d3roTypo.body,
PhosphorText variant="reading" → "body", ScreenPanel sx prop 제거.
bootstrap.ts require() → dynamic import() 변환.
2026-04-08 08:51:24 +09:00
Yun Chan
d0c4f9ee53 Phase 14 구현: 회의 모드 (Meeting Mode)
실시간 녹음 + 타임스탬프 메모 + STT 전사 + LLM 구조화 회의록 + PDF/MD 내보내기.
CaptionService 연동, 동시 사용 충돌 방지, 긴 회의 2-pass 요약 지원.
DB 2테이블, IPC 15채널, UI 3뷰(목록/녹음/상세), 12개 locale i18n.
2026-04-08 01:16:52 +09:00
Yun Chan
eb83682269 Phase 12~13 전체 구현: Pro+ 피처 6종 + 음성 대화 + RAG + OS 자동화
Phase 12:
- FileTranscriptionService: ffmpeg PCM 변환 + 30초 청크 순차 STT
- MeetingSummaryService: 자막 세션 → LLM 자동 요약 + DB summaryText
- DictationTemplateService: 필드별 음성 입력 상태 머신 + 프리셋 3개

Phase 13.1:
- VoiceConversationService: STT→Ollama /api/chat→TTS 대화 루프 (10턴)
- TTSPlaybackService: Windows SAPI 문장 단위 큐 재생
- LocalLLMService.chatStream: Ollama /api/chat 스트리밍

Phase 13.2:
- RAGService: Ollama 임베딩 + SQLite 벡터 + 코사인 유사도 검색
- KnowledgeBasePage: 문서 관리 + 질문/답변 UI
- PDF 파서: zlib FlateDecode 해제 + BT/ET 텍스트 추출

Phase 13.3:
- VoiceActionService: LLM JSON 액션 플랜 생성 + 실행
- 프리셋 6개 (크롬/메모장/탐색기/볼륨), 위험 명령 차단

공통: IPC ~70채널, 에러코드 780-878, i18n 100+키
버그픽스: 라이선스 로컬 키 우선, i18n featureLabel, DOM 중첩
2026-04-05 23:52:14 +09:00
Yun Chan
a31f96bbb8 Phase 10~11 전체 구현: 킬러 피처 5종 + 수익화 시스템
Phase 10 킬러 피처:
- MemoService: 태그 CRUD + 마크다운 내보내기 (memo_tags DB)
- VoiceCommandService: 키워드→명령어 매칭, 프리셋 4종
- ScreenContextService: PowerShell 활성 윈도우 + Ctrl+C 선택 텍스트
- ChainService: LLM 명령어 순차 실행 파이프라인
- CaptionService: 6초 청크 연속 전사 + 시스템 오디오 루프백

VoiceModeService 파이프라인 통합:
- 녹음 시작 → 컨텍스트 캡처 → STT → 키워드 매칭 → LLM(체인/컨텍스트 주입) → 삽입

시스템 오디오 캡처:
- setDisplayMediaRequestHandler + audio: 'loopback' (IPC 브릿지)
- electron-audio-loopback 패키지 contextIsolation 호환 불가 → 직접 구현

Phase 11 수익화:
- LicenseService: Free/Pro/Pro+ 3티어, LemonSqueezy API
- Feature Gate: requireFeature/checkFeature/consumeFeature
- 일일 쿼터: Free dictation 20/일, LLM 10/일 (SQLite daily_usage)
- LicenseModal, ProBadge, UpgradePromptModal UI

디자인 보강:
- d3roTypo(13종), d3roShadow(10종), d3roRadius(7종) 토큰 시스템
- ScreenPanel, ButtonGroup DS 컴포넌트 신규
- PhosphorText 4→13종 변형, MetalDial conic-gradient 광택
- 공유 컴포넌트: EmptyStateCard, SearchInput, PageHeader, HistoryEntryCard

기타:
- 자막 핫키 SSOT 전체 연동 (Config→Hotkey→VoiceMode→Caption→Settings)
- StatusBar 자막 LED + 효과음, 자막 로딩 UI
- LLM 상태 이벤트 전파 수정 (폴링 제거 → onStatusChanged)
- 커맨드 팝업 "선택 해제" 항목 추가
2026-04-05 21:36:09 +09:00
Yun Chan
561502ec36 Settings 열기 속도 개선: 디바이스 비동기 로드 + 부팅 시 프리캐싱
- SettingsModal: 설정+핫키 먼저 로드 → 즉시 표시, 디바이스는 백그라운드
- bootstrap: 앱 부팅 시 getDevices() 미리 호출 → 캐싱
- 첫 번째 Settings 열기도 빠르게 (캐시 히트)
2026-04-05 13:43:33 +09:00
Yun Chan
ea48168b1e 실시간 UI 갱신: 세션 완료/명령어 변경 시 렌더러 자동 리로드
- bootstrap: notifyRenderer('app:dataChanged') 이벤트 발행
  - session-completed: Dashboard 통계 + History 갱신
  - command:selected: CMD 페이지 활성 명령어 갱신
- preload: app.onDataChanged 이벤트 리스너 추가
- DashboardPage/CommandsPage/HistoryPage: onDataChanged 구독하여 자동 loadData()
2026-04-05 13:31:57 +09:00
Yun Chan
1361b95a4d 커맨드 선택 팝업 (Ctrl+Shift+C): 커서 위치에서 빠른 명령어 전환
- command-popup: Vanilla JS 팝업 (히스토리 팝업과 동일 패턴)
  Arrow↑↓ 선택, Enter 적용, 1-5 직접 선택, ESC 닫기
- WindowManager: showCommandPopup/hideCommandPopup/sendKeyToCommandPopup
- bootstrap: Ctrl+Shift+C 단축키 등록 + command:selected IPC
- electron.vite.config: command-popup HTML 빌드 엔트리 추가
- 선택한 명령어가 즉시 activeInstructionId로 설정 → 다음 녹음에 적용
2026-04-05 13:26:59 +09:00
Yun Chan
6e9e8b1f29 히스토리 팝업 수정: ESC 닫기 + Arrow 키 네비게이션
- Arrow↑↓/Enter/Escape/1-9 키를 팝업 열릴 때 globalShortcut 등록, 닫힐 때 해제
- showHistoryPopup: 2-phase 제거 → 즉시 show (렌더러 비활성 문제 방지)
- hideHistoryPopup/itemSelected/popupDismissed에서 nav 키 해제
2026-04-05 12:38:54 +09:00
Yun Chan
74e027d058 bootstrap await import 수정: path/app을 최상위 import로 변경 2026-04-05 12:18:33 +09:00
Yun Chan
c338a19c90 Phase 9 완료: 전체 남은 기능 구현
1. RecordingTip: thinking 상태 전환 시 opacity 보장
2. 히스토리 오디오 경로: WAV 파일 경로를 DB에 기록
3. 마이크 테스트 UI: Settings Audio 탭에 TEST 버튼 + 레벨 바
4. 온보딩 플로우: 첫 실행 시 3단계 안내 (환영→마이크→핫키→완료)
5. MetalDial 컴포넌트: 동심원 그루브, 회전 포인터, LED 인디케이터
2026-04-05 12:16:39 +09:00
Yun Chan
c64ab3b58f 3대 근본 버그 수정 (RE 조사 기반)
1. HotkeyService: modifier 먼저 놓기 대응
   - Alt+1에서 Alt를 먼저 놓아도 release 감지
   - _handleKeyUp에서 pressed 핫키의 구성 키(main/modifier) 매칭

2. ResultPopup auto-close IPC 핸들러 추가
   - window:hideResultPopup 핸들러가 없어서 팝업이 안 꺼지던 버그
   - window-handlers.ts에 hideResultPopup/hideRecordingTip 핸들러 등록

3. bootstrap.ts 이중 팝업 제어 제거
   - session-completed에서 무조건 showResultPopup 호출하던 코드 제거
   - 팝업 제어는 VoiceModeService 내부에서만 처리
   - bootstrap은 효과음만 담당
2026-04-05 10:50:18 +09:00
Yun Chan
3f4d0c5828 Phase 7~8 구현: 테스트 + 빌드 + CI/CD + SoundEffect + AutoLaunch + UI 리디자인
- vitest 41개 단위 테스트 (HistoryService, DictionaryService, CustomInstructionService, VoiceModeService, D3ROError)
- electron-builder.yml (NSIS, asarUnpack, extraResources)
- .gitlab-ci.yml (lint, typecheck, test, build, release)
- SoundEffectService: WAV 프리로드 + PowerShell 재생 + VoiceMode 연동
- AutoLaunchService: app.setLoginItemSettings + ConfigService 동기화
- TextInsertService: 간이 삽입 검증 (EditMonitor 경량)
- 번들링 인프라: SoX 다운로드 스크립트, PyInstaller 빌드, 경로 해상도 유틸
- AudioCaptureService/LocalSTTService: 번들 경로 자동 감지
- 08-design-system.md 기반 MUI 테마 (다크+라이트+auto 테마 시스템)
- 전체 UI 컴포넌트 리디자인: AppLayout, Dashboard, StatusBar, History, Dictionary, Commands, Settings
- 효과음 WAV 생성: recording-start, recording-stop, error
- EPIPE 에러 핸들링 추가
2026-04-05 09:12:56 +09:00
Yun Chan
d940c5020e Phase 6 구현: 커스텀 명령어 + i18n (ko/en)
- CustomInstructionService: 프리셋 5개 (번역/요약/전문리라이트/코드설명/자유프롬프트)
- 커스텀 명령어 CRUD + 프리셋 보호 (삭제 불가)
- CommandsPage: 명령어 목록 + 추가/편집 다이얼로그
- i18n: ko.json/en.json 리소스 파일, t() 함수, React 컨텍스트
- IPC: instruction 핸들러 6개
- AppLayout: Commands 네비게이션 추가
2026-04-05 02:53:32 +09:00
Yun Chan
5ccbf85a65 ESM 패키지 번들링 + electron-rebuild + import 수정
- electron-vite: nanoid/electron-store를 externalize 제외 (ESM 전용 번들 포함)
- electron-rebuild: better-sqlite3/uiohook-napi Electron용 리빌드
- bootstrap: 동적 require → 정적 import으로 수정
2026-04-05 02:41:48 +09:00
Yun Chan
f131b581a9 Phase 3.5 구현: 커서 위치 히스토리 팝업 (D3RO 고유 기능)
- HistoryPopup: Vanilla JS, 다크 카드(#242427), 앰버 악센트(#f25b29)
- Ctrl+Shift+V → 커서 위치에 최근 10건 히스토리 팝업
- Arrow↑↓ 선택, Enter 붙여넣기, 1-9 직접 선택, ESC 닫기
- focusable: false → 활성 앱 포커스 유지
- 2-phase 리사이즈, 등장/퇴장 애니메이션
- WindowManager: HistoryPopup 관리 + 프리로딩
- Bootstrap: globalShortcut 등록 + IPC 연동
2026-04-05 02:37:35 +09:00
Yun Chan
291e2a29d0 Phase 5 구현: SQLite DB + History/Dictionary 서비스 + UI
- DB: better-sqlite3 + drizzle-orm (history/dictionary/stats, WAL 모드)
- HistoryService: CRUD + 검색 + 통계 + 30일 보존 정책, 세션 완료 시 자동 저장
- DictionaryService: CRUD + 검색 + 사용 횟수 추적 + STT 프롬프트 힌트
- HistoryPage: 목록 + 검색 + 삭제 + 복사 + 페이지네이션
- DictionaryPage: 목록 + 검색 + 추가 다이얼로그 + 삭제
- DashboardPage: 실데이터 통계 (총/오늘 세션, 시간, 단어수, 연속일수)
- IPC: history/dictionary/stats 핸들러 + preload API
- Bootstrap: DB 초기화 (critical) + 이력 자동 저장 연동
2026-04-05 02:32:53 +09:00
Yun Chan
4a5cf6c819 Phase 4 구현: Ollama LLM 연동 (다듬기, 번역, 스트리밍)
- LocalLLMService: Ollama REST API, 스트리밍 NDJSON 파싱, 5초 가용성 폴링
- 시스템 프롬프트: refine/translate/summarize/grammar/expand/custom 6개 액션
- VoiceModeService: 전사→LLM 후처리→텍스트 삽입, LLM 실패 시 원본 폴백
- LLM IPC 핸들러: status/models/process/cancel/serverUrl 8개
- StatusBar: Ollama 연결 상태 + 활성 모델 표시
- Preload: llm API 섹션 추가
- Bootstrap: llm-polling 초기화 단계 추가
2026-04-05 02:18:26 +09:00
Yun Chan
517210af2f Phase 3 구현: 텍스트 삽입 + RecordingTip/ResultPopup + Settings
- TextInsertService: clipboard save→set→Ctrl+V→restore (@nut-tree-fork/nut-js)
- RecordingTip 팝업: 9개 웨이브바 cos분포, thinking 점근수렴, 2-phase 리사이즈
- ResultPopup 팝업: 복사 버튼, auto-close, 마우스 호버 유지, 다크모드
- WindowManager: 팝업 프리로딩, 커서 위치 표시, 멀티모니터 보정
- Settings 모달: General/Audio/STT/LLM 탭
- VoiceModeService: 전사 완료 시 자동 텍스트 삽입 + 팝업 연동
- electron-vite: 팝업 HTML 멀티 엔트리 + popup preload 빌드
2026-04-05 02:11:58 +09:00
Yun Chan
1d152d01a1 Phase 1+2 구현: Electron 뼈대 + STT/핫키/오케스트레이터
Phase 1:
- 프로젝트 초기화 (TypeScript strict, electron-vite, ESLint, Prettier)
- shared 타입 (ipc-channels 113채널, types, errors, constants)
- 메인 프로세스 뼈대 (bootstrap, lifecycle, 단일 인스턴스)
- LoggerService, ConfigService (electron-store ESM dynamic import)
- React 19 + MUI 7 Dashboard, 시스템 트레이

Phase 2:
- AudioCaptureService (node-record-lpcm16, PCM16 16kHz mono)
- HotkeyService (uiohook-napi, 더블프레스, holdMode/toggleMode)
- LocalSTTService (faster-whisper Python sidecar, 이중 조건 플러시)
- VoiceModeService 오케스트레이터 (이중 상태머신, Action Queue)
- Python sidecar (FastAPI: health/load/transcribe/shutdown)
- IPC 핸들러 (voice, stt, hotkey) + Preload API 확장
2026-04-05 02:01:37 +09:00