feat(V2-1b): packages/core 추출 — 공유 타입/에러/채널/유틸 분리

packages/core (@d3ro/core) 신규 생성:
- types.ts, errors.ts, ipc-channels.ts, constants.ts (shared에서 이동)
- utils/meeting-markdown.ts, utils/markdown-to-docx.ts (main/utils에서 이동)
- subpath exports 정의 (./types, ./errors, ./ipc-channels, ./constants,
  ./utils/meeting-markdown, ./utils/markdown-to-docx)
- src/index.ts barrel export 추가
- docx를 core 자체 dependency로 선언

apps/desktop 연결:
- package.json에 @d3ro/core: '*' dep 추가
- tsconfig.node/web.json paths에 @d3ro/core/* 추가
- electron.vite.config.ts 3개 섹션 alias 추가 (main/preload/renderer)
- externalizeDepsPlugin exclude에 @d3ro/core (workspace 소스 번들 대상)
- vitest.config.ts alias 추가

일괄 치환 (79 파일, 167건):
- @shared/{types,errors,ipc-channels,constants} → @d3ro/core/*
- static/dynamic import + type expression import 모두 포함
- MeetingModeService.ts의 ../utils/* 상대 경로 → @d3ro/core/utils/*
- @shared/theme-vars는 V2-1c 범위로 남김 (WindowManager만 사용)

M1 수정 포함:
- electron.vite.config.ts의 resolve('src/shared') → resolve(__dirname, ...)
  CWD 독립적으로 동작하도록 견고화

검증:
- typecheck 통과
- build 통과 (main+preload+renderer)
- dev 런타임 → DB/핫키/Ollama 모두 정상, 기존 데이터 연속성 유지
This commit is contained in:
yunchan8804 2026-04-08 14:39:46 +09:00
parent a4cb4c0805
commit 3b0eb3393b
95 changed files with 315 additions and 212 deletions

View file

@ -2,17 +2,20 @@ import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
const sharedAlias = {
'@shared': resolve(__dirname, 'src/shared'),
'@d3ro/core': resolve(__dirname, '../../packages/core/src')
}
export default defineConfig({ export default defineConfig({
main: { main: {
plugins: [externalizeDepsPlugin({ exclude: ['nanoid', 'electron-store'] })], plugins: [
resolve: { externalizeDepsPlugin({ exclude: ['nanoid', 'electron-store', '@d3ro/core'] })
alias: { ],
'@shared': resolve('src/shared') resolve: { alias: sharedAlias }
}
}
}, },
preload: { preload: {
plugins: [externalizeDepsPlugin()], plugins: [externalizeDepsPlugin({ exclude: ['@d3ro/core'] })],
build: { build: {
rollupOptions: { rollupOptions: {
input: { input: {
@ -21,11 +24,7 @@ export default defineConfig({
} }
} }
}, },
resolve: { resolve: { alias: sharedAlias }
alias: {
'@shared': resolve('src/shared')
}
}
}, },
renderer: { renderer: {
build: { build: {
@ -55,11 +54,7 @@ export default defineConfig({
} }
} }
}, },
resolve: { resolve: { alias: sharedAlias },
alias: {
'@shared': resolve('src/shared')
}
},
plugins: [react()] plugins: [react()]
} }
}) })

View file

@ -40,6 +40,7 @@
"vitest": "^2.1.0" "vitest": "^2.1.0"
}, },
"dependencies": { "dependencies": {
"@d3ro/core": "*",
"@electron-toolkit/preload": "^3.0.2", "@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/utils": "^4.0.0", "@electron-toolkit/utils": "^4.0.0",
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",

View file

@ -157,7 +157,7 @@ async function initPopupWindows(): Promise<void> {
unregisterPopupNavKeys() unregisterPopupNavKeys()
} else { } else {
const instructions = getCustomInstructionService().getAll() const instructions = getCustomInstructionService().getAll()
const activeId = configGet('activeInstructionId' as keyof import('@shared/types').AppConfig) as unknown as string const activeId = configGet('activeInstructionId' as keyof import('@d3ro/core/types').AppConfig) as unknown as string
showCommandPopup(instructions as unknown as Array<Record<string, unknown>>, activeId || null) showCommandPopup(instructions as unknown as Array<Record<string, unknown>>, activeId || null)
registerPopupNavKeys('command') registerPopupNavKeys('command')
} }
@ -345,12 +345,12 @@ function setupCommandPopupIPC(): void {
if (data.id) { if (data.id) {
// 명령어 선택 → 활성 명령어로 설정 // 명령어 선택 → 활성 명령어로 설정
configSet('activeInstructionId' as keyof import('@shared/types').AppConfig, data.id as never) configSet('activeInstructionId' as keyof import('@d3ro/core/types').AppConfig, data.id as never)
configSet('defaultLLMAction', 'custom') configSet('defaultLLMAction', 'custom')
logger.info(`Active command set: ${data.name} (${data.id})`) logger.info(`Active command set: ${data.name} (${data.id})`)
} else { } else {
// 선택 해제 → 명령어 없음 (원본 삽입) // 선택 해제 → 명령어 없음 (원본 삽입)
configSet('activeInstructionId' as keyof import('@shared/types').AppConfig, '' as never) configSet('activeInstructionId' as keyof import('@d3ro/core/types').AppConfig, '' as never)
configSet('defaultLLMAction', 'none') configSet('defaultLLMAction', 'none')
logger.info('Active command cleared (none)') logger.info('Active command cleared (none)')
} }

View file

@ -1,13 +1,13 @@
// src/main/ipc/audio-handlers.ts // src/main/ipc/audio-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getAudioCaptureService, calculateRMS } from '../services/AudioCaptureService' import { getAudioCaptureService, calculateRMS } from '../services/AudioCaptureService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { configGet, configSet } from '../services/ConfigService' import { configGet, configSet } from '../services/ConfigService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { SetDeviceParams } from '@shared/types' import type { SetDeviceParams } from '@d3ro/core/types'
const logger = getLogger('audio-handlers') const logger = getLogger('audio-handlers')

View file

@ -2,10 +2,10 @@
// Phase 10.1: Live Caption IPC 핸들러 // Phase 10.1: Live Caption IPC 핸들러
import { ipcMain, session, desktopCapturer } from 'electron' import { ipcMain, session, desktopCapturer } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getCaptionService } from '../services/CaptionService' import { getCaptionService } from '../services/CaptionService'
import type { CaptionConfig } from '@shared/types' import type { CaptionConfig } from '@d3ro/core/types'
export function registerCaptionHandlers(): void { export function registerCaptionHandlers(): void {
// 시스템 오디오 루프백: setDisplayMediaRequestHandler로 audio: 'loopback' 설정 // 시스템 오디오 루프백: setDisplayMediaRequestHandler로 audio: 'loopback' 설정

View file

@ -2,15 +2,15 @@
// Phase 10.4: Multi-LLM Chain IPC 핸들러 // Phase 10.4: Multi-LLM Chain IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@d3ro/core/errors'
import { getChainService } from '../services/ChainService' import { getChainService } from '../services/ChainService'
import type { import type {
CreateChainParams, CreateChainParams,
UpdateChainParams, UpdateChainParams,
DeleteChainParams, DeleteChainParams,
ExecuteChainParams ExecuteChainParams
} from '@shared/types' } from '@d3ro/core/types'
export function registerChainHandlers(): void { export function registerChainHandlers(): void {
ipcMain.handle(IPC_CHANNELS.CHAIN.GET_ALL, async () => { ipcMain.handle(IPC_CHANNELS.CHAIN.GET_ALL, async () => {

View file

@ -1,8 +1,8 @@
// src/main/ipc/config-handlers.ts // src/main/ipc/config-handlers.ts
import { ipcMain, BrowserWindow } from 'electron' import { ipcMain, BrowserWindow } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { configGet, configSet, configGetAll, configReset } from '../services/ConfigService' import { configGet, configSet, configGetAll, configReset } from '../services/ConfigService'
import { getAutoLaunchService } from '../services/AutoLaunchService' import { getAutoLaunchService } from '../services/AutoLaunchService'
import { reapplyThemeToAllPopups } from '../windows/WindowManager' import { reapplyThemeToAllPopups } from '../windows/WindowManager'
@ -22,7 +22,7 @@ import type {
SetAutoLaunchParams, SetAutoLaunchParams,
SetCloseToTrayParams, SetCloseToTrayParams,
AppConfig AppConfig
} from '@shared/types' } from '@d3ro/core/types'
export function registerConfigHandlers(): void { export function registerConfigHandlers(): void {
ipcMain.handle(IPC_CHANNELS.CONFIG.GET, async (_event, params: ConfigGetParams) => { ipcMain.handle(IPC_CHANNELS.CONFIG.GET, async (_event, params: ConfigGetParams) => {

View file

@ -2,8 +2,8 @@
// Phase 10.2 스크린 컨텍스트 IPC 핸들러 // Phase 10.2 스크린 컨텍스트 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getScreenContextService } from '../services/ScreenContextService' import { getScreenContextService } from '../services/ScreenContextService'
export function registerContextHandlers(): void { export function registerContextHandlers(): void {

View file

@ -1,8 +1,8 @@
// src/main/ipc/dictionary-handlers.ts // src/main/ipc/dictionary-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getDictionaryService } from '../services/DictionaryService' import { getDictionaryService } from '../services/DictionaryService'
import type { import type {
DictionaryQueryParams, DictionaryQueryParams,
@ -10,7 +10,7 @@ import type {
DictionaryUpdateParams, DictionaryUpdateParams,
DictionaryDeleteParams, DictionaryDeleteParams,
DictionarySearchParams DictionarySearchParams
} from '@shared/types' } from '@d3ro/core/types'
export function registerDictionaryHandlers(): void { export function registerDictionaryHandlers(): void {
ipcMain.handle(IPC_CHANNELS.DICTIONARY.GET_ALL, async (_event, params: DictionaryQueryParams) => { ipcMain.handle(IPC_CHANNELS.DICTIONARY.GET_ALL, async (_event, params: DictionaryQueryParams) => {

View file

@ -2,11 +2,11 @@
// Phase 12.1: 파일 전사 IPC 핸들러 // Phase 12.1: 파일 전사 IPC 핸들러
import { ipcMain, dialog } from 'electron' import { ipcMain, dialog } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getFileTranscriptionService } from '../services/FileTranscriptionService' import { getFileTranscriptionService } from '../services/FileTranscriptionService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { FileTranscriptionStartParams } from '@shared/types' import type { FileTranscriptionStartParams } from '@d3ro/core/types'
const logger = getLogger('file-transcription-handlers') const logger = getLogger('file-transcription-handlers')

View file

@ -1,15 +1,15 @@
// src/main/ipc/history-handlers.ts // src/main/ipc/history-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getHistoryService } from '../services/HistoryService' import { getHistoryService } from '../services/HistoryService'
import type { import type {
HistoryQueryParams, HistoryQueryParams,
HistoryGetByIdParams, HistoryGetByIdParams,
HistoryDeleteParams, HistoryDeleteParams,
HistorySearchParams HistorySearchParams
} from '@shared/types' } from '@d3ro/core/types'
export function registerHistoryHandlers(): void { export function registerHistoryHandlers(): void {
ipcMain.handle(IPC_CHANNELS.HISTORY.GET_ALL, async (_event, params: HistoryQueryParams) => { ipcMain.handle(IPC_CHANNELS.HISTORY.GET_ALL, async (_event, params: HistoryQueryParams) => {

View file

@ -1,11 +1,11 @@
// src/main/ipc/hotkey-handlers.ts // src/main/ipc/hotkey-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getHotkeyService } from '../services/HotkeyService' import { getHotkeyService } from '../services/HotkeyService'
import { configGet, configSet } from '../services/ConfigService' import { configGet, configSet } from '../services/ConfigService'
import type { SetHotkeyParams, SetEnabledParams } from '@shared/types' import type { SetHotkeyParams, SetEnabledParams } from '@d3ro/core/types'
export function registerHotkeyHandlers(): void { export function registerHotkeyHandlers(): void {
ipcMain.handle(IPC_CHANNELS.HOTKEY.GET_DICTATION_SHORTCUT, async () => { ipcMain.handle(IPC_CHANNELS.HOTKEY.GET_DICTATION_SHORTCUT, async () => {

View file

@ -1,7 +1,7 @@
// src/main/ipc/instruction-handlers.ts // src/main/ipc/instruction-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getCustomInstructionService } from '../services/CustomInstructionService' import { getCustomInstructionService } from '../services/CustomInstructionService'
import type { CustomInstruction } from '../services/CustomInstructionService' import type { CustomInstruction } from '../services/CustomInstructionService'

View file

@ -2,15 +2,15 @@
// Phase 11: 라이센스 IPC 핸들러 // Phase 11: 라이센스 IPC 핸들러
import { ipcMain, BrowserWindow } from 'electron' import { ipcMain, BrowserWindow } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getLicenseService } from '../services/LicenseService' import { getLicenseService } from '../services/LicenseService'
import type { import type {
ActivateLicenseParams, ActivateLicenseParams,
UpgradePromptEvent, UpgradePromptEvent,
LicenseInfo, LicenseInfo,
} from '@shared/types' } from '@d3ro/core/types'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
/** 업그레이드 유도 이벤트를 모든 렌더러에 broadcast */ /** 업그레이드 유도 이벤트를 모든 렌더러에 broadcast */
function broadcastUpgradePrompt(event: UpgradePromptEvent): void { function broadcastUpgradePrompt(event: UpgradePromptEvent): void {

View file

@ -1,12 +1,12 @@
// src/main/ipc/llm-handlers.ts // src/main/ipc/llm-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getLocalLLMService } from '../services/LocalLLMService' import { getLocalLLMService } from '../services/LocalLLMService'
import { configGet, configSet } from '../services/ConfigService' import { configGet, configSet } from '../services/ConfigService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import type { SetLLMModelParams, SetServerUrlParams, LLMProcessParams } from '@shared/types' import type { SetLLMModelParams, SetServerUrlParams, LLMProcessParams } from '@d3ro/core/types'
export function registerLLMHandlers(): void { export function registerLLMHandlers(): void {
// LLM 가용성 변경 시 렌더러에 상태 전파 // LLM 가용성 변경 시 렌더러에 상태 전파

View file

@ -2,15 +2,15 @@
// Phase 14.5: Meeting Document Template IPC 핸들러 // Phase 14.5: Meeting Document Template IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getMeetingDocTemplateService } from '../services/MeetingDocTemplateService' import { getMeetingDocTemplateService } from '../services/MeetingDocTemplateService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { import type {
CreateMeetingDocTemplateParams, CreateMeetingDocTemplateParams,
UpdateMeetingDocTemplateParams, UpdateMeetingDocTemplateParams,
DeleteMeetingDocTemplateParams, DeleteMeetingDocTemplateParams,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('meeting-doc-template-handlers') const logger = getLogger('meeting-doc-template-handlers')

View file

@ -2,8 +2,8 @@
// Phase 14 / 14.5: Meeting Mode IPC 핸들러 // Phase 14 / 14.5: Meeting Mode IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getMeetingModeService } from '../services/MeetingModeService' import { getMeetingModeService } from '../services/MeetingModeService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { import type {
@ -15,7 +15,7 @@ import type {
MeetingGenerateDocParams, MeetingGenerateDocParams,
MeetingExportFormat, MeetingExportFormat,
MeetingChatSendParams, MeetingChatSendParams,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('meeting-mode-handlers') const logger = getLogger('meeting-mode-handlers')

View file

@ -2,11 +2,11 @@
// Phase 12.2: 회의록 요약 IPC 핸들러 // Phase 12.2: 회의록 요약 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getMeetingSummaryService } from '../services/MeetingSummaryService' import { getMeetingSummaryService } from '../services/MeetingSummaryService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { MeetingSummarizeParams, MeetingSummaryGetParams, MeetingSummaryExportParams } from '@shared/types' import type { MeetingSummarizeParams, MeetingSummaryGetParams, MeetingSummaryExportParams } from '@d3ro/core/types'
const logger = getLogger('meeting-summary-handlers') const logger = getLogger('meeting-summary-handlers')

View file

@ -2,8 +2,8 @@
// Phase 10.3: 음성 메모 태그 IPC 핸들러 // Phase 10.3: 음성 메모 태그 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@d3ro/core/errors'
import { getMemoService } from '../services/MemoService' import { getMemoService } from '../services/MemoService'
import type { import type {
GetTagsParams, GetTagsParams,
@ -11,7 +11,7 @@ import type {
RemoveTagParams, RemoveTagParams,
SearchByTagParams, SearchByTagParams,
ExportMemoParams ExportMemoParams
} from '@shared/types' } from '@d3ro/core/types'
export function registerMemoHandlers(): void { export function registerMemoHandlers(): void {
ipcMain.handle(IPC_CHANNELS.MEMO.GET_TAGS, async (_event, params: GetTagsParams) => { ipcMain.handle(IPC_CHANNELS.MEMO.GET_TAGS, async (_event, params: GetTagsParams) => {

View file

@ -2,11 +2,11 @@
// Phase 13.2: 로컬 RAG IPC 핸들러 // Phase 13.2: 로컬 RAG IPC 핸들러
import { ipcMain, dialog } from 'electron' import { ipcMain, dialog } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getRAGService } from '../services/RAGService' import { getRAGService } from '../services/RAGService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { RAGQueryParams, RAGRemoveDocumentParams } from '@shared/types' import type { RAGQueryParams, RAGRemoveDocumentParams } from '@d3ro/core/types'
const logger = getLogger('rag-handlers') const logger = getLogger('rag-handlers')

View file

@ -1,11 +1,11 @@
// src/main/ipc/stt-handlers.ts // src/main/ipc/stt-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getLocalSTTService } from '../services/LocalSTTService' import { getLocalSTTService } from '../services/LocalSTTService'
import { configGet, configSet } from '../services/ConfigService' import { configGet, configSet } from '../services/ConfigService'
import type { SetSTTModelParams, SetSTTLanguageParams } from '@shared/types' import type { SetSTTModelParams, SetSTTLanguageParams } from '@d3ro/core/types'
export function registerSTTHandlers(): void { export function registerSTTHandlers(): void {
ipcMain.handle(IPC_CHANNELS.STT.GET_STATUS, async () => { ipcMain.handle(IPC_CHANNELS.STT.GET_STATUS, async () => {

View file

@ -1,9 +1,9 @@
// src/main/ipc/system-handlers.ts // src/main/ipc/system-handlers.ts
import { ipcMain, app, systemPreferences } from 'electron' import { ipcMain, app, systemPreferences } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess } from '@shared/errors' import { ipcSuccess } from '@d3ro/core/errors'
import type { PermissionStatus, PlaySoundParams, SetSoundEnabledParams } from '@shared/types' import type { PermissionStatus, PlaySoundParams, SetSoundEnabledParams } from '@d3ro/core/types'
import { getSoundEffectService } from '../services/SoundEffectService' import { getSoundEffectService } from '../services/SoundEffectService'
export function registerSystemHandlers(): void { export function registerSystemHandlers(): void {

View file

@ -2,8 +2,8 @@
// Phase 12.3: 딕테이션 템플릿 IPC 핸들러 // Phase 12.3: 딕테이션 템플릿 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getDictationTemplateService } from '../services/DictationTemplateService' import { getDictationTemplateService } from '../services/DictationTemplateService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { import type {
@ -12,7 +12,7 @@ import type {
DeleteTemplateParams, DeleteTemplateParams,
StartTemplateSessionParams, StartTemplateSessionParams,
SetFieldValueParams, SetFieldValueParams,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('template-handlers') const logger = getLogger('template-handlers')
@ -33,7 +33,7 @@ export function registerTemplateHandlers(): void {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('../services/LicenseService') const { getLicenseService } = await import('../services/LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.DICTATION_TEMPLATE) const access = license.canUse(Feature.DICTATION_TEMPLATE)
if (!access.allowed) { if (!access.allowed) {

View file

@ -2,11 +2,11 @@
// Phase 13.3: OS 자동화 IPC 핸들러 // Phase 13.3: OS 자동화 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getVoiceActionService } from '../services/VoiceActionService' import { getVoiceActionService } from '../services/VoiceActionService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { VoiceActionExecuteParams } from '@shared/types' import type { VoiceActionExecuteParams } from '@d3ro/core/types'
const logger = getLogger('voice-action-handlers') const logger = getLogger('voice-action-handlers')

View file

@ -2,10 +2,10 @@
// Phase 10.5: 음성 단축키 IPC 핸들러 // Phase 10.5: 음성 단축키 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getVoiceCommandService } from '../services/VoiceCommandService' import { getVoiceCommandService } from '../services/VoiceCommandService'
import type { SetVoiceCommandKeywordsParams, SetVoiceCommandEnabledParams } from '@shared/types' import type { SetVoiceCommandKeywordsParams, SetVoiceCommandEnabledParams } from '@d3ro/core/types'
export function registerVoiceCommandHandlers(): void { export function registerVoiceCommandHandlers(): void {
const CH = IPC_CHANNELS.VOICE_COMMAND const CH = IPC_CHANNELS.VOICE_COMMAND

View file

@ -2,11 +2,11 @@
// Phase 13.1: 음성 대화 모드 IPC 핸들러 // Phase 13.1: 음성 대화 모드 IPC 핸들러
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ErrorCode, ipcSuccess, ipcError } from '@shared/errors' import { ErrorCode, ipcSuccess, ipcError } from '@d3ro/core/errors'
import { getVoiceConversationService } from '../services/VoiceConversationService' import { getVoiceConversationService } from '../services/VoiceConversationService'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import type { ConversationSendParams } from '@shared/types' import type { ConversationSendParams } from '@d3ro/core/types'
const logger = getLogger('voice-conversation-handlers') const logger = getLogger('voice-conversation-handlers')

View file

@ -1,10 +1,10 @@
// src/main/ipc/voice-handlers.ts // src/main/ipc/voice-handlers.ts
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess, ipcError, ErrorCode } from '@shared/errors' import { ipcSuccess, ipcError, ErrorCode } from '@d3ro/core/errors'
import { getVoiceModeService } from '../services/VoiceModeService' import { getVoiceModeService } from '../services/VoiceModeService'
import type { StartRecordingParams, StopRecordingParams, CancelRecordingParams, SetVoiceModeParams } from '@shared/types' import type { StartRecordingParams, StopRecordingParams, CancelRecordingParams, SetVoiceModeParams } from '@d3ro/core/types'
export function registerVoiceHandlers(): void { export function registerVoiceHandlers(): void {
ipcMain.handle(IPC_CHANNELS.VOICE.START_RECORDING, async (_event, params: StartRecordingParams) => { ipcMain.handle(IPC_CHANNELS.VOICE.START_RECORDING, async (_event, params: StartRecordingParams) => {

View file

@ -1,8 +1,8 @@
// src/main/ipc/window-handlers.ts // src/main/ipc/window-handlers.ts
import { ipcMain, shell } from 'electron' import { ipcMain, shell } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { ipcSuccess } from '@shared/errors' import { ipcSuccess } from '@d3ro/core/errors'
import { getMainWindow, hideResultPopup, hideRecordingTip } from '../windows/WindowManager' import { getMainWindow, hideResultPopup, hideRecordingTip } from '../windows/WindowManager'
export function registerWindowHandlers(): void { export function registerWindowHandlers(): void {

View file

@ -10,9 +10,9 @@ import type { Readable } from 'stream'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getSoxPath } from '../utils/paths' import { getSoxPath } from '../utils/paths'
import type { AudioDevice } from '@shared/types' import type { AudioDevice } from '@d3ro/core/types'
import { AUDIO_FORMAT, TIMING } from '@shared/constants' import { AUDIO_FORMAT, TIMING } from '@d3ro/core/constants'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
const logger = getLogger('AudioCaptureService') const logger = getLogger('AudioCaptureService')

View file

@ -15,14 +15,14 @@ import {
hideCaptionOverlay, hideCaptionOverlay,
sendToCaptionOverlay, sendToCaptionOverlay,
} from '../windows/WindowManager' } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
CaptionState, CaptionState,
CaptionSegment, CaptionSegment,
CaptionConfig, CaptionConfig,
CaptionSessionSummary, CaptionSessionSummary,
} from '@shared/types' } from '@d3ro/core/types'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
const logger = getLogger('CaptionService') const logger = getLogger('CaptionService')
@ -139,7 +139,7 @@ class CaptionService extends EventEmitter {
this._totalFrameCount = 0 this._totalFrameCount = 0
// ConfigService에서 저장된 오디오 소스 읽기 // ConfigService에서 저장된 오디오 소스 읽기
const savedSource = configGet('captionAudioSource' as keyof import('@shared/types').AppConfig) as unknown as string const savedSource = configGet('captionAudioSource' as keyof import('@d3ro/core/types').AppConfig) as unknown as string
if (savedSource && (savedSource === 'mic' || savedSource === 'system' || savedSource === 'both')) { if (savedSource && (savedSource === 'mic' || savedSource === 'system' || savedSource === 'both')) {
this._config.audioSource = savedSource as 'mic' | 'system' | 'both' this._config.audioSource = savedSource as 'mic' | 'system' | 'both'
} }

View file

@ -8,8 +8,8 @@ import { configGet } from './ConfigService'
import { getCustomInstructionService } from './CustomInstructionService' import { getCustomInstructionService } from './CustomInstructionService'
import { getLocalLLMService } from './LocalLLMService' import { getLocalLLMService } from './LocalLLMService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
LLMChain, LLMChain,
ChainStep, ChainStep,
@ -17,7 +17,7 @@ import type {
UpdateChainParams, UpdateChainParams,
ChainProgress, ChainProgress,
ChainExecutionResult ChainExecutionResult
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('chain-service') const logger = getLogger('chain-service')

View file

@ -2,7 +2,7 @@
// electron-store 기반 설정 관리. 설계서 02의 AppConfig 타입 사용. // electron-store 기반 설정 관리. 설계서 02의 AppConfig 타입 사용.
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import type { AppConfig, ConfigChangedEvent } from '@shared/types' import type { AppConfig, ConfigChangedEvent } from '@d3ro/core/types'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
const logger = getLogger('ConfigService') const logger = getLogger('ConfigService')

View file

@ -7,8 +7,8 @@ import { nanoid } from 'nanoid'
import Store from 'electron-store' import Store from 'electron-store'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
DictationTemplate, DictationTemplate,
TemplateField, TemplateField,
@ -18,7 +18,7 @@ import type {
TemplateSessionCompletedEvent, TemplateSessionCompletedEvent,
CreateTemplateParams, CreateTemplateParams,
UpdateTemplateParams, UpdateTemplateParams,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('DictationTemplateService') const logger = getLogger('DictationTemplateService')

View file

@ -14,7 +14,7 @@ import type {
DictionaryAddParams, DictionaryAddParams,
DictionaryUpdateParams, DictionaryUpdateParams,
DictionarySearchParams DictionarySearchParams
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('DictionaryService') const logger = getLogger('DictionaryService')

View file

@ -13,15 +13,15 @@ import { getHistoryService } from './HistoryService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getFfmpegPath } from '../utils/paths' import { getFfmpegPath } from '../utils/paths'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
FileTranscriptionState, FileTranscriptionState,
FileTranscriptionProgress, FileTranscriptionProgress,
FileTranscriptionResult, FileTranscriptionResult,
FileTranscriptionSegment, FileTranscriptionSegment,
FileTranscriptionStateInfo, FileTranscriptionStateInfo,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('FileTranscriptionService') const logger = getLogger('FileTranscriptionService')
@ -75,7 +75,7 @@ class FileTranscriptionService extends EventEmitter {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.FILE_TRANSCRIPTION) const access = license.canUse(Feature.FILE_TRANSCRIPTION)
if (!access.allowed) { if (!access.allowed) {

View file

@ -13,7 +13,7 @@ import type {
HistoryPage, HistoryPage,
HistorySearchParams, HistorySearchParams,
StatsSummary StatsSummary
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('HistoryService') const logger = getLogger('HistoryService')

View file

@ -7,9 +7,9 @@ import { uIOhook, UiohookKey } from 'uiohook-napi'
import type { UiohookKeyboardEvent } from 'uiohook-napi' import type { UiohookKeyboardEvent } from 'uiohook-napi'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import { TIMING } from '@shared/constants' import { TIMING } from '@d3ro/core/constants'
import type { HotkeyBinding } from '@shared/types' import type { HotkeyBinding } from '@d3ro/core/types'
const logger = getLogger('HotkeyService') const logger = getLogger('HotkeyService')

View file

@ -8,7 +8,7 @@ import { eq, and } from 'drizzle-orm'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { getDatabase } from '../db' import { getDatabase } from '../db'
import { dailyUsage } from '../db/schema' import { dailyUsage } from '../db/schema'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
LicenseTier, LicenseTier,
LicenseInfo, LicenseInfo,
@ -17,8 +17,8 @@ import type {
UpgradePromptEvent, UpgradePromptEvent,
ActivateLicenseResult, ActivateLicenseResult,
TierComparison, TierComparison,
} from '@shared/types' } from '@d3ro/core/types'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
const logger = getLogger('license') const logger = getLogger('license')

View file

@ -8,8 +8,8 @@ import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { LLMStatus, LLMModel, LLMAction, LLMConnectionState } from '@shared/types' import type { LLMStatus, LLMModel, LLMAction, LLMConnectionState } from '@d3ro/core/types'
const logger = getLogger('LocalLLMService') const logger = getLogger('LocalLLMService')
@ -410,7 +410,7 @@ class LocalLLMService extends EventEmitter {
// Phase 11: LLM 처리 쿼터 체크 // Phase 11: LLM 처리 쿼터 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.LLM_PROCESS) const access = license.canUse(Feature.LLM_PROCESS)
if (!access.allowed) { if (!access.allowed) {

View file

@ -8,8 +8,8 @@ import { type ChildProcess, spawn } from 'child_process'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getSidecarCommand } from '../utils/paths' import { getSidecarCommand } from '../utils/paths'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { STTModel, STTStatus, STTEngineState } from '@shared/types' import type { STTModel, STTStatus, STTEngineState } from '@d3ro/core/types'
// ── 내부 타입 정의 ──────────────────────────────────────── // ── 내부 타입 정의 ────────────────────────────────────────

View file

@ -5,13 +5,13 @@ import { EventEmitter } from 'events'
import { nanoid } from 'nanoid' import { nanoid } from 'nanoid'
import Store from 'electron-store' import Store from 'electron-store'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
MeetingDocTemplate, MeetingDocTemplate,
CreateMeetingDocTemplateParams, CreateMeetingDocTemplateParams,
UpdateMeetingDocTemplateParams, UpdateMeetingDocTemplateParams,
MeetingDocTemplateType, MeetingDocTemplateType,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('MeetingDocTemplateService') const logger = getLogger('MeetingDocTemplateService')

View file

@ -12,8 +12,8 @@ import { configGet, configSet } from './ConfigService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { getDatabase } from '../db' import { getDatabase } from '../db'
import { meetingSessions, meetingMemos, meetingDocuments } from '../db/schema' import { meetingSessions, meetingMemos, meetingDocuments } from '../db/schema'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import { import {
parseMinutes, parseMinutes,
buildExportMarkdown, buildExportMarkdown,
@ -21,8 +21,8 @@ import {
formatTime, formatTime,
formatDateFile, formatDateFile,
formatDateRange, formatDateRange,
} from '../utils/meeting-markdown' } from '@d3ro/core/utils/meeting-markdown'
import { markdownToDocx } from '../utils/markdown-to-docx' import { markdownToDocx } from '@d3ro/core/utils/markdown-to-docx'
import type { import type {
MeetingModeState, MeetingModeState,
MeetingMemo, MeetingMemo,
@ -39,7 +39,7 @@ import type {
MeetingExportFormat, MeetingExportFormat,
MeetingDocGeneratingProgress, MeetingDocGeneratingProgress,
CaptionSegment, CaptionSegment,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('MeetingModeService') const logger = getLogger('MeetingModeService')
@ -145,7 +145,7 @@ class MeetingModeService extends EventEmitter {
// 회의 모드는 마이크 캡처 강제 — ConfigService 값도 임시 변경 // 회의 모드는 마이크 캡처 강제 — ConfigService 값도 임시 변경
// (CaptionService.start()가 ConfigService에서 다시 읽기 때문) // (CaptionService.start()가 ConfigService에서 다시 읽기 때문)
type AppConfigKey = keyof import('@shared/types').AppConfig type AppConfigKey = keyof import('@d3ro/core/types').AppConfig
const prevAudioSource = configGet('captionAudioSource' as AppConfigKey) as unknown as string const prevAudioSource = configGet('captionAudioSource' as AppConfigKey) as unknown as string
configSet('captionAudioSource' as AppConfigKey, 'mic' as never) configSet('captionAudioSource' as AppConfigKey, 'mic' as never)

View file

@ -12,9 +12,9 @@ import { getLocalLLMService } from './LocalLLMService'
import { getDatabase } from '../db' import { getDatabase } from '../db'
import { history } from '../db/schema' import { history } from '../db/schema'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { MeetingSummaryResult, MeetingSummaryProgress } from '@shared/types' import type { MeetingSummaryResult, MeetingSummaryProgress } from '@d3ro/core/types'
const logger = getLogger('MeetingSummaryService') const logger = getLogger('MeetingSummaryService')
@ -41,7 +41,7 @@ class MeetingSummaryService extends EventEmitter {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.MEETING_SUMMARY) const access = license.canUse(Feature.MEETING_SUMMARY)
if (!access.allowed) { if (!access.allowed) {

View file

@ -10,7 +10,7 @@ import { getDatabase } from '../db'
import { memoTags, history } from '../db/schema' import { memoTags, history } from '../db/schema'
import type { MemoTagRow } from '../db/schema' import type { MemoTagRow } from '../db/schema'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
MemoTag, MemoTag,
TagCount, TagCount,
@ -18,7 +18,7 @@ import type {
ExportMemoParams, ExportMemoParams,
HistoryEntry, HistoryEntry,
HistoryPage HistoryPage
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('MemoService') const logger = getLogger('MemoService')

View file

@ -13,15 +13,15 @@ import { configGet } from './ConfigService'
import { getDatabase } from '../db' import { getDatabase } from '../db'
import { ragDocuments, ragChunks } from '../db/schema' import { ragDocuments, ragChunks } from '../db/schema'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
RAGDocument, RAGDocument,
RAGQueryResult, RAGQueryResult,
RAGState, RAGState,
RAGStateInfo, RAGStateInfo,
RAGIndexProgress, RAGIndexProgress,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('RAGService') const logger = getLogger('RAGService')
@ -74,7 +74,7 @@ class RAGService extends EventEmitter {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.LOCAL_RAG) const access = license.canUse(Feature.LOCAL_RAG)
if (!access.allowed) { if (!access.allowed) {

View file

@ -5,8 +5,8 @@
import { clipboard } from 'electron' import { clipboard } from 'electron'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet, configSet } from './ConfigService' import { configGet, configSet } from './ConfigService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { ScreenContext, CaptureContextResult } from '@shared/types' import type { ScreenContext, CaptureContextResult } from '@d3ro/core/types'
const logger = getLogger('screen-context') const logger = getLogger('screen-context')

View file

@ -7,7 +7,7 @@ import { EventEmitter } from 'events'
import { spawn, type ChildProcess } from 'child_process' import { spawn, type ChildProcess } from 'child_process'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
const logger = getLogger('TTSPlaybackService') const logger = getLogger('TTSPlaybackService')

View file

@ -6,7 +6,7 @@
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { clipboard } from 'electron' import { clipboard } from 'electron'
import { getLogger } from './LoggerService' import { getLogger } from './LoggerService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
const logger = getLogger('TextInsertService') const logger = getLogger('TextInsertService')

View file

@ -10,8 +10,8 @@ import { getLogger } from './LoggerService'
import { getLocalLLMService } from './LocalLLMService' import { getLocalLLMService } from './LocalLLMService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
VoiceActionPlan, VoiceActionPlan,
VoiceActionPreset, VoiceActionPreset,
@ -19,7 +19,7 @@ import type {
VoiceActionPlannedEvent, VoiceActionPlannedEvent,
VoiceActionExecutedEvent, VoiceActionExecutedEvent,
VoiceActionErrorEvent, VoiceActionErrorEvent,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('VoiceActionService') const logger = getLogger('VoiceActionService')
@ -112,7 +112,7 @@ class VoiceActionService extends EventEmitter {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.OS_AUTOMATION) const access = license.canUse(Feature.OS_AUTOMATION)
if (!access.allowed) { if (!access.allowed) {

View file

@ -10,7 +10,7 @@ import type {
VoiceCommandKeyword, VoiceCommandKeyword,
VoiceCommandMatch, VoiceCommandMatch,
KeywordMatchMode KeywordMatchMode
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('voice-command') const logger = getLogger('voice-command')

View file

@ -11,8 +11,8 @@ import { getAudioCaptureService } from './AudioCaptureService'
import { getTTSPlaybackService } from './TTSPlaybackService' import { getTTSPlaybackService } from './TTSPlaybackService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getMainWindow } from '../windows/WindowManager' import { getMainWindow } from '../windows/WindowManager'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { import type {
ConversationState, ConversationState,
ConversationMessage, ConversationMessage,
@ -20,7 +20,7 @@ import type {
ConversationAssistantDelta, ConversationAssistantDelta,
ConversationAssistantMessage, ConversationAssistantMessage,
ConversationError, ConversationError,
} from '@shared/types' } from '@d3ro/core/types'
const logger = getLogger('VoiceConversationService') const logger = getLogger('VoiceConversationService')
@ -67,7 +67,7 @@ class VoiceConversationService extends EventEmitter {
// 라이센스 체크 // 라이센스 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.VOICE_CONVERSATION) const access = license.canUse(Feature.VOICE_CONVERSATION)
if (!access.allowed) { if (!access.allowed) {

View file

@ -17,10 +17,10 @@ import type { HotkeyConfig } from './HotkeyService'
import { configGet } from './ConfigService' import { configGet } from './ConfigService'
import { getTextInsertService } from './TextInsertService' import { getTextInsertService } from './TextInsertService'
import { getLocalLLMService } from './LocalLLMService' import { getLocalLLMService } from './LocalLLMService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import { TIMING } from '@shared/constants' import { TIMING } from '@d3ro/core/constants'
import { RecognitionState, AudioState } from '@shared/types' import { RecognitionState, AudioState } from '@d3ro/core/types'
import type { VoiceMode, VoiceState } from '@shared/types' import type { VoiceMode, VoiceState } from '@d3ro/core/types'
import { import {
showRecordingTip, showRecordingTip,
hideRecordingTip, hideRecordingTip,
@ -28,7 +28,7 @@ import {
sendAudioLevelToTip, sendAudioLevelToTip,
showResultPopup, showResultPopup,
} from '../windows/WindowManager' } from '../windows/WindowManager'
import type { ScreenContext } from '@shared/types' import type { ScreenContext } from '@d3ro/core/types'
const logger = getLogger('VoiceModeService') const logger = getLogger('VoiceModeService')
@ -189,7 +189,7 @@ class VoiceModeService extends EventEmitter {
// Phase 11: 라이센스 쿼터 체크 // Phase 11: 라이센스 쿼터 체크
try { try {
const { getLicenseService } = await import('./LicenseService') const { getLicenseService } = await import('./LicenseService')
const { Feature } = await import('@shared/types') const { Feature } = await import('@d3ro/core/types')
const license = getLicenseService() const license = getLicenseService()
const access = license.canUse(Feature.DICTATION) const access = license.canUse(Feature.DICTATION)
if (!access.allowed) { if (!access.allowed) {
@ -220,7 +220,7 @@ class VoiceModeService extends EventEmitter {
const { getScreenContextService } = await import('./ScreenContextService') const { getScreenContextService } = await import('./ScreenContextService')
const ctx = getScreenContextService() const ctx = getScreenContextService()
if (ctx.isEnabled()) { if (ctx.isEnabled()) {
const captureSelected = configGet('screenContextEnabled' as keyof import('@shared/types').AppConfig) as unknown as boolean const captureSelected = configGet('screenContextEnabled' as keyof import('@d3ro/core/types').AppConfig) as unknown as boolean
const result = await ctx.captureContext(captureSelected) const result = await ctx.captureContext(captureSelected)
screenContext = result.context screenContext = result.context
logger.info(`Screen context captured: ${screenContext.appName ?? 'unknown'}`) logger.info(`Screen context captured: ${screenContext.appName ?? 'unknown'}`)
@ -555,7 +555,7 @@ class VoiceModeService extends EventEmitter {
if (action === 'chain') { if (action === 'chain') {
try { try {
const { getChainService } = await import('./ChainService') const { getChainService } = await import('./ChainService')
const activeChainId = configGet('activeChainId' as keyof import('@shared/types').AppConfig) as unknown as string const activeChainId = configGet('activeChainId' as keyof import('@d3ro/core/types').AppConfig) as unknown as string
if (activeChainId) { if (activeChainId) {
const chainResult = await getChainService().execute(activeChainId, contextPrefix + transcribedText) const chainResult = await getChainService().execute(activeChainId, contextPrefix + transcribedText)
if (this._isInTerminalState()) return if (this._isInTerminalState()) return
@ -572,7 +572,7 @@ class VoiceModeService extends EventEmitter {
// 음성 단축키 오버라이드 또는 활성 명령어 // 음성 단축키 오버라이드 또는 활성 명령어
const effectiveInstructionId = overrideInstructionId const effectiveInstructionId = overrideInstructionId
?? (configGet('activeInstructionId' as keyof import('@shared/types').AppConfig) as unknown as string) ?? (configGet('activeInstructionId' as keyof import('@d3ro/core/types').AppConfig) as unknown as string)
if (action === 'custom' || overrideInstructionId) { if (action === 'custom' || overrideInstructionId) {
let customPrompt = contextPrefix + transcribedText let customPrompt = contextPrefix + transcribedText

View file

@ -3,9 +3,9 @@
// 서비스에서 기능 사용 전 호출하여 접근 권한 확인 + 쿼터 차단 // 서비스에서 기능 사용 전 호출하여 접근 권한 확인 + 쿼터 차단
import { getLicenseService } from '../services/LicenseService' import { getLicenseService } from '../services/LicenseService'
import { D3ROError, ErrorCode } from '@shared/errors' import { D3ROError, ErrorCode } from '@d3ro/core/errors'
import type { FeatureAccess } from '@shared/types' import type { FeatureAccess } from '@d3ro/core/types'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
/** /**
* , D3ROError를 throw한다. * , D3ROError를 throw한다.

View file

@ -4,7 +4,7 @@
import { BrowserWindow, shell, screen, ipcMain, Menu } from 'electron' import { BrowserWindow, shell, screen, ipcMain, Menu } from 'electron'
import { join } from 'path' import { join } from 'path'
import { is } from '@electron-toolkit/utils' import { is } from '@electron-toolkit/utils'
import { WINDOW_SIZE } from '@shared/constants' import { WINDOW_SIZE } from '@d3ro/core/constants'
import { getLogger } from '../services/LoggerService' import { getLogger } from '../services/LoggerService'
import { getIsQuitting } from '../lifecycle' import { getIsQuitting } from '../lifecycle'
import { configGet } from '../services/ConfigService' import { configGet } from '../services/ConfigService'

View file

@ -2,7 +2,7 @@
// contextBridge로 렌더러에 노출할 API 정의 // contextBridge로 렌더러에 노출할 API 정의
import { contextBridge, ipcRenderer } from 'electron' import { contextBridge, ipcRenderer } from 'electron'
import { IPC_CHANNELS } from '@shared/ipc-channels' import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import type { import type {
AudioDevice, AudioDevice,
SetDeviceParams, SetDeviceParams,
@ -166,9 +166,9 @@ import type {
MeetingChatSendParams, MeetingChatSendParams,
MeetingChatDelta, MeetingChatDelta,
DiarizeSessionParams, DiarizeSessionParams,
} from '@shared/types' } from '@d3ro/core/types'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
import type { IPCResult } from '@shared/errors' import type { IPCResult } from '@d3ro/core/errors'
type Unsubscribe = () => void type Unsubscribe = () => void

View file

@ -9,7 +9,7 @@ import { I18nProvider } from './i18n'
import { AppLayout } from './components/AppLayout' import { AppLayout } from './components/AppLayout'
import { UpgradePromptModal } from './components/UpgradePromptModal' import { UpgradePromptModal } from './components/UpgradePromptModal'
import { startSystemAudioCapture, stopSystemAudioCapture } from './utils/systemAudioCapture' import { startSystemAudioCapture, stopSystemAudioCapture } from './utils/systemAudioCapture'
import type { ThemeMode, ConfigChangedEvent } from '@shared/types' import type { ThemeMode, ConfigChangedEvent } from '@d3ro/core/types'
export function App(): React.ReactElement { export function App(): React.ReactElement {
const [themeMode, setThemeMode] = useState<ThemeMode>('auto') const [themeMode, setThemeMode] = useState<ThemeMode>('auto')

View file

@ -26,7 +26,7 @@ import { StatusBar } from './StatusBar'
import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow, d3roRadius } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow, d3roRadius } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { TranslationKey } from '../i18n' import type { TranslationKey } from '../i18n'
import type { LicenseTier } from '@shared/types' import type { LicenseTier } from '@d3ro/core/types'
type Route = 'dashboard' | 'history' | 'dictionary' | 'commands' | 'conversation' | 'knowledge' | 'meeting' type Route = 'dashboard' | 'history' | 'dictionary' | 'commands' | 'conversation' | 'knowledge' | 'meeting'

View file

@ -13,7 +13,7 @@ import type {
FileTranscriptionProgress, FileTranscriptionProgress,
FileTranscriptionResult, FileTranscriptionResult,
FileTranscriptionState, FileTranscriptionState,
} from '@shared/types' } from '@d3ro/core/types'
const SUPPORTED_EXTENSIONS = [ const SUPPORTED_EXTENSIONS = [
'.mp3', '.wav', '.m4a', '.ogg', '.flac', '.wma', '.aac', '.mp3', '.wav', '.m4a', '.ogg', '.flac', '.wma', '.aac',

View file

@ -17,7 +17,7 @@ import {
} from '@mui/material' } from '@mui/material'
import { d3roPalette } from '../theme' import { d3roPalette } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { HotkeyBinding } from '@shared/types' import type { HotkeyBinding } from '@d3ro/core/types'
// ── 키 이름 매핑 (Windows) ────────────────────────────── // ── 키 이름 매핑 (Windows) ──────────────────────────────
const KEY_DISPLAY_MAP: Record<number, string> = { const KEY_DISPLAY_MAP: Record<number, string> = {

View file

@ -24,7 +24,7 @@ import CancelIcon from '@mui/icons-material/Cancel'
import { MetalCard, PhosphorText, Led, ScreenPanel, PhysicalButton } from './ds' import { MetalCard, PhosphorText, Led, ScreenPanel, PhysicalButton } from './ds'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius, d3roShadow } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius, d3roShadow } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { LicenseInfo, LicenseTier, TierComparison, UsageQuota } from '@shared/types' import type { LicenseInfo, LicenseTier, TierComparison, UsageQuota } from '@d3ro/core/types'
interface LicenseModalProps { interface LicenseModalProps {
open: boolean open: boolean

View file

@ -20,7 +20,7 @@ import type {
UsageQuota, UsageQuota,
TierComparison, TierComparison,
ActivateLicenseResult, ActivateLicenseResult,
} from '@shared/types' } from '@d3ro/core/types'
export function LicenseTab(): React.ReactElement { export function LicenseTab(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -19,7 +19,7 @@ import { d3roPalette, d3roFontMono, d3roShadow } from '../theme'
import { Led } from './ds' import { Led } from './ds'
import { HotkeyRecordModal } from './HotkeyRecordModal' import { HotkeyRecordModal } from './HotkeyRecordModal'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { HotkeyBinding, AudioDevice } from '@shared/types' import type { HotkeyBinding, AudioDevice } from '@d3ro/core/types'
interface OnboardingModalProps { interface OnboardingModalProps {
open: boolean open: boolean
@ -47,7 +47,7 @@ export function OnboardingModal({ open, onClose }: OnboardingModalProps): React.
const handleFinish = () => { const handleFinish = () => {
// 온보딩 완료 플래그 저장 // 온보딩 완료 플래그 저장
window.electronAPI.config.set({ key: 'onboardingCompleted' as keyof import('@shared/types').AppConfig, value: true as never }) window.electronAPI.config.set({ key: 'onboardingCompleted' as keyof import('@d3ro/core/types').AppConfig, value: true as never })
onClose() onClose()
} }

View file

@ -7,7 +7,7 @@ import LockIcon from '@mui/icons-material/Lock'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme'
import { useProFeature } from '../hooks/useProFeature' import { useProFeature } from '../hooks/useProFeature'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { Feature } from '@shared/types' import type { Feature } from '@d3ro/core/types'
interface ProBadgeProps { interface ProBadgeProps {
feature: Feature feature: Feature

View file

@ -36,8 +36,8 @@ import { HotkeyRecordModal } from './HotkeyRecordModal'
import { LicenseTab } from './LicenseTab' import { LicenseTab } from './LicenseTab'
import { useI18n, LOCALE_META } from '../i18n' import { useI18n, LOCALE_META } from '../i18n'
import type { Locale } from '../i18n' import type { Locale } from '../i18n'
import type { ThemeMode, AppConfig, HotkeyBinding, AudioDevice } from '@shared/types' import type { ThemeMode, AppConfig, HotkeyBinding, AudioDevice } from '@d3ro/core/types'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
interface SettingsModalProps { interface SettingsModalProps {
open: boolean open: boolean
@ -840,7 +840,7 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac
size="small" size="small"
onClick={() => { onClick={() => {
window.electronAPI.config.set({ window.electronAPI.config.set({
key: 'onboardingCompleted' as keyof import('@shared/types').AppConfig, key: 'onboardingCompleted' as keyof import('@d3ro/core/types').AppConfig,
value: false as never, value: false as never,
}) })
onClose() onClose()

View file

@ -9,7 +9,7 @@ import { Led } from './ds'
import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow, d3roRadius } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow, d3roRadius } from '../theme'
import { OllamaGuideModal } from './OllamaGuideModal' import { OllamaGuideModal } from './OllamaGuideModal'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { LLMStatus } from '@shared/types' import type { LLMStatus } from '@d3ro/core/types'
export function StatusBar(): React.ReactElement { export function StatusBar(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -11,7 +11,7 @@ import { MetalCard, PhosphorText, Led, PhysicalButton } from './ds'
import { PageHeader, EmptyStateCard } from './shared' import { PageHeader, EmptyStateCard } from './shared'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { DictationTemplate, TemplateField, TemplateSessionInfo } from '@shared/types' import type { DictationTemplate, TemplateField, TemplateSessionInfo } from '@d3ro/core/types'
export function TemplateSection(): React.ReactElement { export function TemplateSection(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -16,7 +16,7 @@ import LockIcon from '@mui/icons-material/Lock'
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius, d3roShadow } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius, d3roShadow } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { UpgradePromptEvent, UsageQuota } from '@shared/types' import type { UpgradePromptEvent, UsageQuota } from '@d3ro/core/types'
export function UpgradePromptModal(): React.ReactElement { export function UpgradePromptModal(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -9,7 +9,7 @@ import { ExportMenu } from './ExportMenu'
import { PhysicalButton } from '../ds/PhysicalButton' import { PhysicalButton } from '../ds/PhysicalButton'
import { d3roPalette, d3roTypo } from '../../theme' import { d3roPalette, d3roTypo } from '../../theme'
import { useI18n } from '../../i18n' import { useI18n } from '../../i18n'
import type { MeetingExportFormat } from '@shared/types' import type { MeetingExportFormat } from '@d3ro/core/types'
interface DocumentTabDoc { interface DocumentTabDoc {
id: string id: string

View file

@ -7,7 +7,7 @@ import FileDownloadIcon from '@mui/icons-material/FileDownload'
import { PhysicalButton } from '../ds/PhysicalButton' import { PhysicalButton } from '../ds/PhysicalButton'
import { d3roPalette, d3roTypo, d3roFontMono, d3roRadius, d3roShadow } from '../../theme' import { d3roPalette, d3roTypo, d3roFontMono, d3roRadius, d3roShadow } from '../../theme'
import { useI18n } from '../../i18n' import { useI18n } from '../../i18n'
import type { MeetingExportFormat } from '@shared/types' import type { MeetingExportFormat } from '@d3ro/core/types'
interface ExportMenuProps { interface ExportMenuProps {
onExport: (format: MeetingExportFormat) => void onExport: (format: MeetingExportFormat) => void

View file

@ -11,7 +11,7 @@ import { PhosphorText } from '../ds/PhosphorText'
import { PhysicalButton } from '../ds/PhysicalButton' import { PhysicalButton } from '../ds/PhysicalButton'
import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow } from '../../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roShadow } from '../../theme'
import { useI18n } from '../../i18n' import { useI18n } from '../../i18n'
import type { MeetingChatMessage } from '@shared/types' import type { MeetingChatMessage } from '@d3ro/core/types'
interface MeetingChatPanelProps { interface MeetingChatPanelProps {
sessionId: string sessionId: string

View file

@ -26,7 +26,7 @@ import type {
MeetingDocument, MeetingDocument,
MeetingDocTemplate, MeetingDocTemplate,
MeetingExportFormat, MeetingExportFormat,
} from '@shared/types' } from '@d3ro/core/types'
interface MeetingDetailTabsProps { interface MeetingDetailTabsProps {
detail: MeetingSessionDetail detail: MeetingSessionDetail

View file

@ -14,7 +14,7 @@ import { MetalCard, Led } from '../ds'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../../theme'
import { useI18n } from '../../i18n' import { useI18n } from '../../i18n'
import { formatDuration } from '../../utils/formatters' import { formatDuration } from '../../utils/formatters'
import type { HistoryEntry, MemoTag, MeetingSummaryResult } from '@shared/types' import type { HistoryEntry, MemoTag, MeetingSummaryResult } from '@d3ro/core/types'
interface HistoryEntryCardProps { interface HistoryEntryCardProps {
entry: HistoryEntry entry: HistoryEntry

View file

@ -2,8 +2,8 @@
// Pro feature gating hook: checks access, subscribes to tier changes // Pro feature gating hook: checks access, subscribes to tier changes
import { useState, useEffect, useCallback } from 'react' import { useState, useEffect, useCallback } from 'react'
import { Feature } from '@shared/types' import { Feature } from '@d3ro/core/types'
import type { FeatureAccess } from '@shared/types' import type { FeatureAccess } from '@d3ro/core/types'
interface UseProFeatureResult { interface UseProFeatureResult {
/** Feature is unlocked for current tier */ /** Feature is unlocked for current tier */

View file

@ -15,7 +15,7 @@ import { PageHeader, EmptyStateCard } from '../components/shared'
import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo, d3roRadius } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import { TemplateSection } from '../components/TemplateSection' import { TemplateSection } from '../components/TemplateSection'
import type { VoiceCommandRule, VoiceCommandKeyword, KeywordMatchMode, LLMChain, ChainStep } from '@shared/types' import type { VoiceCommandRule, VoiceCommandKeyword, KeywordMatchMode, LLMChain, ChainStep } from '@d3ro/core/types'
interface CustomInstruction { interface CustomInstruction {
id: string id: string
@ -69,10 +69,10 @@ export function CommandsPage(): React.ReactElement {
const newId = activeId === id ? null : id const newId = activeId === id ? null : id
setActiveId(newId) setActiveId(newId)
if (newId) { if (newId) {
window.electronAPI.config.set({ key: 'activeInstructionId' as keyof import('@shared/types').AppConfig, value: newId as never }) window.electronAPI.config.set({ key: 'activeInstructionId' as keyof import('@d3ro/core/types').AppConfig, value: newId as never })
window.electronAPI.config.set({ key: 'defaultLLMAction', value: 'custom' }) window.electronAPI.config.set({ key: 'defaultLLMAction', value: 'custom' })
} else { } else {
window.electronAPI.config.set({ key: 'activeInstructionId' as keyof import('@shared/types').AppConfig, value: '' as never }) window.electronAPI.config.set({ key: 'activeInstructionId' as keyof import('@d3ro/core/types').AppConfig, value: '' as never })
window.electronAPI.config.set({ key: 'defaultLLMAction', value: 'none' }) window.electronAPI.config.set({ key: 'defaultLLMAction', value: 'none' })
} }
} }

View file

@ -10,7 +10,7 @@ import { d3roPalette, d3roTypo } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import { formatRecordingTime, formatRecordingTimeUnit, formatNumber, getDateKey } from '../utils/formatters' import { formatRecordingTime, formatRecordingTimeUnit, formatNumber, getDateKey } from '../utils/formatters'
import { FileDropZone } from '../components/FileDropZone' import { FileDropZone } from '../components/FileDropZone'
import type { StatsSummary, HistoryEntry, HotkeyBinding, CaptionState, LicenseTier, UsageQuota } from '@shared/types' import type { StatsSummary, HistoryEntry, HotkeyBinding, CaptionState, LicenseTier, UsageQuota } from '@d3ro/core/types'
// ── 메인 컴포넌트 ───────────────────────────────────── // ── 메인 컴포넌트 ─────────────────────────────────────

View file

@ -10,7 +10,7 @@ import { MetalCard, PhosphorText } from '../components/ds'
import { PageHeader, SearchInput, EmptyStateCard } from '../components/shared' import { PageHeader, SearchInput, EmptyStateCard } from '../components/shared'
import { d3roPalette, d3roFontMono, d3roTypo } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { DictionaryEntry, DictionaryPage as DictPageData } from '@shared/types' import type { DictionaryEntry, DictionaryPage as DictPageData } from '@d3ro/core/types'
const PAGE_SIZE = 50 const PAGE_SIZE = 50

View file

@ -10,7 +10,7 @@ import { d3roPalette, d3roTypo, d3roFontMono, d3roRadius } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import { getDateKey } from '../utils/formatters' import { getDateKey } from '../utils/formatters'
import { EmptyStateCard, SearchInput, PageHeader, HistoryEntryCard } from '../components/shared' import { EmptyStateCard, SearchInput, PageHeader, HistoryEntryCard } from '../components/shared'
import type { HistoryEntry, HistoryPage as HistoryPageData, TagCount } from '@shared/types' import type { HistoryEntry, HistoryPage as HistoryPageData, TagCount } from '@d3ro/core/types'
const PAGE_SIZE = 50 const PAGE_SIZE = 50

View file

@ -14,7 +14,7 @@ import { MetalCard, PhosphorText, Led, PhysicalButton, ScreenPanel } from '../co
import { PageHeader, EmptyStateCard } from '../components/shared' import { PageHeader, EmptyStateCard } from '../components/shared'
import { d3roPalette, d3roFontMono, d3roTypo } from '../theme' import { d3roPalette, d3roFontMono, d3roTypo } from '../theme'
import { useI18n } from '../i18n' import { useI18n } from '../i18n'
import type { RAGDocument, RAGQueryResult, RAGIndexProgress } from '@shared/types' import type { RAGDocument, RAGQueryResult, RAGIndexProgress } from '@d3ro/core/types'
export function KnowledgeBasePage(): React.ReactElement { export function KnowledgeBasePage(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -25,7 +25,7 @@ import type {
MeetingProcessingProgress, MeetingProcessingProgress,
CaptionSegment, CaptionSegment,
MeetingMemo, MeetingMemo,
} from '@shared/types' } from '@d3ro/core/types'
type MeetingView = 'list' | 'recording' | 'detail' type MeetingView = 'list' | 'recording' | 'detail'

View file

@ -17,7 +17,7 @@ import type {
ConversationState, ConversationState,
ConversationMessage, ConversationMessage,
ConversationAssistantDelta, ConversationAssistantDelta,
} from '@shared/types' } from '@d3ro/core/types'
export function VoiceConversationPage(): React.ReactElement { export function VoiceConversationPage(): React.ReactElement {
const { t } = useI18n() const { t } = useI18n()

View file

@ -3,7 +3,7 @@
// CSS Custom Properties 기반: d3roPalette가 var()를 사용하여 테마 전환 시 자동 반응. // CSS Custom Properties 기반: d3roPalette가 var()를 사용하여 테마 전환 시 자동 반응.
import { createTheme, type Theme } from '@mui/material/styles' import { createTheme, type Theme } from '@mui/material/styles'
import type { ThemeMode } from '@shared/types' import type { ThemeMode } from '@d3ro/core/types'
// ── 테마 키 타입 ──────────────────────────────────────────── // ── 테마 키 타입 ────────────────────────────────────────────
type ThemeKey = 'dark' | 'light' | 'nord' | 'solarized' | 'catppuccin' | 'dracula' type ThemeKey = 'dark' | 'light' | 'nord' | 'solarized' | 'catppuccin' | 'dracula'

View file

@ -5,7 +5,9 @@
"outDir": "./out", "outDir": "./out",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@shared/*": ["src/shared/*"] "@shared/*": ["src/shared/*"],
"@d3ro/core": ["../../packages/core/src/index.ts"],
"@d3ro/core/*": ["../../packages/core/src/*"]
}, },
"strict": true, "strict": true,
"noImplicitAny": true, "noImplicitAny": true,

View file

@ -5,7 +5,9 @@
"outDir": "./out", "outDir": "./out",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@shared/*": ["src/shared/*"] "@shared/*": ["src/shared/*"],
"@d3ro/core": ["../../packages/core/src/index.ts"],
"@d3ro/core/*": ["../../packages/core/src/*"]
}, },
"jsx": "react-jsx", "jsx": "react-jsx",
"strict": true, "strict": true,

View file

@ -17,7 +17,8 @@ export default defineConfig({
}, },
resolve: { resolve: {
alias: { alias: {
'@shared': resolve(__dirname, 'src/shared') '@shared': resolve(__dirname, 'src/shared'),
'@d3ro/core': resolve(__dirname, '../../packages/core/src')
} }
} }
}) })

View file

@ -7,7 +7,8 @@
**V1 (Electron) 완료** → **V2 (Monorepo) 진행 중** **V1 (Electron) 완료** → **V2 (Monorepo) 진행 중**
- Phase V2-1a ✅ 완료 (Monorepo 구조 이동) - Phase V2-1a ✅ 완료 (Monorepo 구조 이동)
- 다음: Phase V2-1b (packages/core 추출) — 별도 세션 - Phase V2-1b ✅ 완료 (packages/core 추출)
- 다음: Phase V2-1c (packages/ui 추출) — 별도 세션
## V1 완료 페이즈 ## V1 완료 페이즈
@ -36,10 +37,34 @@
| Sub-phase | 범위 | 상태 | | Sub-phase | 범위 | 상태 |
|---|---|---| |---|---|---|
| V2-1a | npm workspaces + apps/desktop으로 V1 이동 | ✅ 완료 | | V2-1a | npm workspaces + apps/desktop으로 V1 이동 | ✅ 완료 |
| V2-1b | packages/core 추출 (types, errors, utils) | ⏸️ 대기 | | V2-1b | packages/core 추출 (types, errors, ipc-channels, constants, utils) | ✅ 완료 |
| V2-1c | packages/ui 추출 (DS 컴포넌트 + theme) | ⏸️ 대기 | | V2-1c | packages/ui 추출 (DS 컴포넌트 + theme + theme-vars) | ⏸️ 대기 |
| V2-1d | packages/i18n 추출 (locale JSON + 훅) | ⏸️ 대기 | | V2-1d | packages/i18n 추출 (locale JSON + 훅) | ⏸️ 대기 |
**V2-1b 완료 내역**
- `packages/core/` 패키지 신규: `@d3ro/core`, subpath exports (types/errors/ipc-channels/constants/utils/*), docx dep 포함
- 6개 파일 `git mv``packages/core/src/`로 이동:
- `apps/desktop/src/shared/{types,errors,ipc-channels,constants}.ts`
- `apps/desktop/src/main/utils/{meeting-markdown,markdown-to-docx}.ts`
- `packages/core/src/index.ts` barrel export 추가
- `apps/desktop/package.json``"@d3ro/core": "*"` dep 추가
- `apps/desktop/tsconfig.node.json`, `tsconfig.web.json``paths``@d3ro/core/*` 추가, `@shared/*`는 theme-vars용으로 유지
- `apps/desktop/electron.vite.config.ts` alias 3개 섹션에 `@d3ro/core` 추가 + **M1 수정**: `resolve('src/shared')``resolve(__dirname, 'src/shared')`
- `externalizeDepsPlugin` exclude에 `@d3ro/core` 추가 (main/preload 둘 다)
- `apps/desktop/vitest.config.ts``@d3ro/core` alias 추가
- **일괄 치환**: `@shared/{types,errors,ipc-channels,constants}``@d3ro/core/*` (사용자 79개 파일, 167건)
- static import (`from '@shared/...'`)
- dynamic import (`import('@shared/...')`)
- type expression import (`keyof import('@shared/...').AppConfig`)
- `MeetingModeService.ts`의 상대 경로 utils import (`../utils/meeting-markdown`, `../utils/markdown-to-docx`)를 `@d3ro/core/utils/*`로 교체
- `packages/core` 내부 자기 참조: `meeting-markdown.ts``@shared/types``../types` 상대 경로
**V2-1b 검증**
- `npm run typecheck`
- `npm run build` ✅ (main+preload+renderer)
- `npm run dev` 런타임 실행 ✅ (DB/핫키/Ollama 모두 정상)
- `apps/desktop/src/shared/`에는 `theme-vars.ts` 1개만 남음 (V2-1c에서 이동 예정)
**V2-1a 완료 내역** **V2-1a 완료 내역**
- 루트 `package.json`을 npm workspaces 루트로 재구성 (workspaces: apps/*, packages/*) - 루트 `package.json`을 npm workspaces 루트로 재구성 (workspaces: apps/*, packages/*)
- `turbo.json`, `tsconfig.base.json` 추가 (Turborepo 자체 설치는 뒤로 미룸) - `turbo.json`, `tsconfig.base.json` 추가 (Turborepo 자체 설치는 뒤로 미룸)

16
package-lock.json generated
View file

@ -26,6 +26,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@d3ro/core": "*",
"@electron-toolkit/preload": "^3.0.2", "@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/utils": "^4.0.0", "@electron-toolkit/utils": "^4.0.0",
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
@ -390,6 +391,10 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@d3ro/core": {
"resolved": "packages/core",
"link": true
},
"node_modules/@d3ro/desktop": { "node_modules/@d3ro/desktop": {
"resolved": "apps/desktop", "resolved": "apps/desktop",
"link": true "link": true
@ -12798,6 +12803,17 @@
"type": "github", "type": "github",
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
},
"packages/core": {
"name": "@d3ro/core",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"docx": "^9.6.1"
},
"devDependencies": {
"@types/node": "^22.13.0"
}
} }
} }
} }

View file

@ -0,0 +1,45 @@
{
"name": "@d3ro/core",
"version": "1.0.0",
"private": true,
"description": "D3RO Voice 공유 비즈니스 로직 — 타입, 에러, IPC 채널, 상수, 유틸",
"license": "MIT",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
},
"./types": {
"types": "./src/types.ts",
"default": "./src/types.ts"
},
"./errors": {
"types": "./src/errors.ts",
"default": "./src/errors.ts"
},
"./ipc-channels": {
"types": "./src/ipc-channels.ts",
"default": "./src/ipc-channels.ts"
},
"./constants": {
"types": "./src/constants.ts",
"default": "./src/constants.ts"
},
"./utils/meeting-markdown": {
"types": "./src/utils/meeting-markdown.ts",
"default": "./src/utils/meeting-markdown.ts"
},
"./utils/markdown-to-docx": {
"types": "./src/utils/markdown-to-docx.ts",
"default": "./src/utils/markdown-to-docx.ts"
}
},
"dependencies": {
"docx": "^9.6.1"
},
"devDependencies": {
"@types/node": "^22.13.0"
}
}

View file

@ -0,0 +1,8 @@
// packages/core — barrel export
// 개별 sub-path import 권장: '@d3ro/core/types', '@d3ro/core/errors' 등
// 본 파일은 편의를 위한 통합 re-export
export * from './types'
export * from './errors'
export * from './ipc-channels'
export * from './constants'

View file

@ -1,7 +1,7 @@
// src/main/utils/meeting-markdown.ts // packages/core/src/utils/meeting-markdown.ts
// Phase 14.5: MeetingModeService에서 추출한 마크다운 유틸리티 // Phase 14.5: MeetingModeService에서 추출한 마크다운 유틸리티
import type { MeetingMinutes, MeetingSessionDetail } from '@shared/types' import type { MeetingMinutes, MeetingSessionDetail } from '../types'
export function formatTime(ms: number): string { export function formatTime(ms: number): string {
const totalSeconds = Math.floor(ms / 1000) const totalSeconds = Math.floor(ms / 1000)

View file

@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noEmit": true,
"lib": ["ES2022", "DOM"]
},
"include": ["src/**/*"]
}