refactor(main): IPC 채널 SSOT 일원화 + AppConfig 타입 강화 (WS2)
- ipc-channels.ts SSOT에 9개 그룹/키 추가: INSTRUCTION, SYSTEM_AUDIO, POPUP_RESULT/HISTORY/COMMAND/CAPTION, VOICE_PARTIAL, CLIPBOARD, APP, VOICE_CONVERSATION.FINISH_LISTENING - WindowManager/handlers/bootstrap 하드코딩 채널 -> IPC_CHANNELS 교체. 불일치 4건(result:* vs window:tip*)은 preload 재검증 후 SSOT로 통일. notifyRenderer channel: string -> IPCChannel 타입 좁힘. - AppConfig에 7개 누락 키 추가(customInstructions, llmChains, voiceCommandRules, voiceCommandsEnabled, activeInstructionId, activeChainId, captionAudioSource) -> as never 16건 제거. - ChainService/CustomInstructionService/WindowManager dynamic require -> static import. - services/index.ts 데드 레지스트리 제거 (import 0건). SKIP: ipcSuccess/ipcError 헬퍼 통일, catch 패턴(별도) 정책: docs/REFACTOR_POLICY.md DP2, DP9
This commit is contained in:
parent
b820c789bb
commit
aef44289a5
15 changed files with 161 additions and 126 deletions
|
|
@ -3,7 +3,7 @@
|
|||
// LLMChain을 electron-store에 저장하고, 체인을 순차 실행한다.
|
||||
|
||||
import { getLogger } from './LoggerService'
|
||||
import { configGet } from './ConfigService'
|
||||
import { configGet, configSet } from './ConfigService'
|
||||
import { getCustomInstructionService } from './CustomInstructionService'
|
||||
import { getLocalLLMService } from './LocalLLMService'
|
||||
import { getMainWindow } from '../windows/WindowManager'
|
||||
|
|
@ -29,7 +29,7 @@ let initialized = false
|
|||
|
||||
function loadChains(): LLMChain[] {
|
||||
try {
|
||||
const stored = configGet('llmChains' as never) as LLMChain[] | undefined
|
||||
const stored = configGet('llmChains') as LLMChain[] | undefined
|
||||
if (Array.isArray(stored) && stored.length > 0) {
|
||||
return stored
|
||||
}
|
||||
|
|
@ -41,11 +41,7 @@ function loadChains(): LLMChain[] {
|
|||
|
||||
function saveChains(): void {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { configSet } = require('./ConfigService') as {
|
||||
configSet: (key: never, value: never) => void
|
||||
}
|
||||
configSet('llmChains' as never, chains as never)
|
||||
configSet('llmChains', chains)
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Failed to save chains: ${error instanceof Error ? error.message : String(error)}`
|
||||
|
|
|
|||
|
|
@ -3,26 +3,11 @@
|
|||
// electron-store에 저장, 프리셋 5개 기본 제공.
|
||||
|
||||
import { getLogger } from './LoggerService'
|
||||
import { configGet } from './ConfigService'
|
||||
import { configGet, configSet } from './ConfigService'
|
||||
import type { CustomInstruction } from '@d3ro/core/types'
|
||||
|
||||
const logger = getLogger('CustomInstructionService')
|
||||
|
||||
// ============================================================
|
||||
// 타입
|
||||
// ============================================================
|
||||
|
||||
export interface CustomInstruction {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
prompt: string
|
||||
icon: string
|
||||
isBuiltin: boolean
|
||||
order: number
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
}
|
||||
|
||||
type CreateInput = Omit<CustomInstruction, 'id' | 'isBuiltin' | 'order' | 'createdAt' | 'updatedAt'>
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -91,7 +76,7 @@ let initialized = false
|
|||
function loadInstructions(): CustomInstruction[] {
|
||||
// electron-store에서 로드 시도
|
||||
try {
|
||||
const stored = configGet('customInstructions' as never) as CustomInstruction[] | undefined
|
||||
const stored = configGet('customInstructions') as CustomInstruction[] | undefined
|
||||
if (Array.isArray(stored) && stored.length > 0) {
|
||||
return stored
|
||||
}
|
||||
|
|
@ -110,8 +95,7 @@ function loadInstructions(): CustomInstruction[] {
|
|||
|
||||
function saveInstructions(): void {
|
||||
try {
|
||||
const { configSet } = require('./ConfigService')
|
||||
configSet('customInstructions' as never, instructions as never)
|
||||
configSet('customInstructions', instructions)
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to save instructions: ${error instanceof Error ? error.message : String(error)}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,9 +145,8 @@ class MeetingModeService extends EventEmitter {
|
|||
|
||||
// 회의 모드는 마이크 캡처 강제 — ConfigService 값도 임시 변경
|
||||
// (CaptionService.start()가 ConfigService에서 다시 읽기 때문)
|
||||
type AppConfigKey = keyof import('@d3ro/core/types').AppConfig
|
||||
const prevAudioSource = configGet('captionAudioSource' as AppConfigKey) as unknown as string
|
||||
configSet('captionAudioSource' as AppConfigKey, 'mic' as never)
|
||||
const prevAudioSource = configGet('captionAudioSource')
|
||||
configSet('captionAudioSource', 'mic')
|
||||
|
||||
try {
|
||||
await captionService.start()
|
||||
|
|
@ -156,12 +155,12 @@ class MeetingModeService extends EventEmitter {
|
|||
hideCaptionOverlay()
|
||||
// ConfigService 원래 값 복원
|
||||
if (prevAudioSource) {
|
||||
configSet('captionAudioSource' as AppConfigKey, prevAudioSource as never)
|
||||
configSet('captionAudioSource', prevAudioSource)
|
||||
}
|
||||
} catch (err) {
|
||||
// ConfigService 원래 값 복원
|
||||
if (prevAudioSource) {
|
||||
configSet('captionAudioSource' as AppConfigKey, prevAudioSource as never)
|
||||
configSet('captionAudioSource', prevAudioSource)
|
||||
}
|
||||
// 시작 실패 시 복원
|
||||
captionService.off('segment', this._segmentHandler)
|
||||
|
|
|
|||
|
|
@ -67,9 +67,8 @@ const DEFAULT_KEYWORDS: ReadonlyArray<DefaultKeywordEntry> = [
|
|||
// electron-store 키 (ConfigService와 별도 네임스페이스)
|
||||
// ============================================================
|
||||
|
||||
// configGet/configSet에 타입이 없는 키를 사용하므로 as never 캐스팅 필요
|
||||
const STORE_KEY_RULES = 'voiceCommandRules' as never
|
||||
const STORE_KEY_ENABLED = 'voiceCommandsEnabled' as never
|
||||
const STORE_KEY_RULES: keyof import('@d3ro/core/types').AppConfig = 'voiceCommandRules'
|
||||
const STORE_KEY_ENABLED: keyof import('@d3ro/core/types').AppConfig = 'voiceCommandsEnabled'
|
||||
|
||||
// ============================================================
|
||||
// 키워드 매칭 엔진
|
||||
|
|
@ -292,7 +291,7 @@ class VoiceCommandService {
|
|||
|
||||
private saveRules(): void {
|
||||
try {
|
||||
configSet(STORE_KEY_RULES, this.rules as never)
|
||||
configSet(STORE_KEY_RULES, this.rules)
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Failed to save voice command rules: ${error instanceof Error ? error.message : String(error)}`
|
||||
|
|
@ -311,7 +310,7 @@ class VoiceCommandService {
|
|||
|
||||
private saveEnabled(): void {
|
||||
try {
|
||||
configSet(STORE_KEY_ENABLED, this.enabled as never)
|
||||
configSet(STORE_KEY_ENABLED, this.enabled)
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Failed to save voice command enabled state: ${error instanceof Error ? error.message : String(error)}`
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ class VoiceModeService extends EventEmitter {
|
|||
if (action === 'chain') {
|
||||
try {
|
||||
const { getChainService } = await import('./ChainService')
|
||||
const activeChainId = configGet('activeChainId' as keyof import('@d3ro/core/types').AppConfig) as unknown as string
|
||||
const activeChainId = configGet('activeChainId')
|
||||
if (activeChainId) {
|
||||
const chainResult = await getChainService().execute(activeChainId, contextPrefix + transcribedText)
|
||||
if (this._isInTerminalState()) return
|
||||
|
|
@ -769,7 +769,7 @@ class VoiceModeService extends EventEmitter {
|
|||
|
||||
// 음성 단축키 오버라이드 또는 활성 명령어
|
||||
const effectiveInstructionId = overrideInstructionId
|
||||
?? (configGet('activeInstructionId' as keyof import('@d3ro/core/types').AppConfig) as unknown as string)
|
||||
?? configGet('activeInstructionId')
|
||||
|
||||
if (action === 'custom' || overrideInstructionId) {
|
||||
let customPrompt = contextPrefix + transcribedText
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
// src/main/services/index.ts — 서비스 레지스트리
|
||||
|
||||
export { initLoggerService, getLogger } from './LoggerService'
|
||||
export {
|
||||
initConfigService,
|
||||
getConfigService,
|
||||
configGet,
|
||||
configSet,
|
||||
configGetAll,
|
||||
configReset,
|
||||
onConfigChanged
|
||||
} from './ConfigService'
|
||||
export {
|
||||
getLocalSTTService,
|
||||
LocalSTTService,
|
||||
STTState
|
||||
} from './LocalSTTService'
|
||||
export type {
|
||||
TranscriptionResult,
|
||||
TranscriptionSegment,
|
||||
TranscribeOptions,
|
||||
LocalSTTEvents
|
||||
} from './LocalSTTService'
|
||||
export { getHotkeyService } from './HotkeyService'
|
||||
export { getVoiceModeService } from './VoiceModeService'
|
||||
export { getAudioCaptureService } from './AudioCaptureService'
|
||||
export { getTextInsertService } from './TextInsertService'
|
||||
export { getLocalLLMService } from './LocalLLMService'
|
||||
export { getHistoryService } from './HistoryService'
|
||||
export { getDictionaryService } from './DictionaryService'
|
||||
export { getCustomInstructionService } from './CustomInstructionService'
|
||||
Loading…
Add table
Add a link
Reference in a new issue