import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron' import { IPC } from '../shared/ipc-channels' import type { KnowledgeSuggestOptions, ScoredKnowledge, ActionId, Bookmark, BookMeta, BookOpenResult, Chapter, CreateBookParams, GlobalSettings, InspirationEntry, AiContextBinding, AiContextBuildResult, AiConfig, AiMessage, AiSession, NamingConflict, AiStreamChunkEvent, AiNetworkStatusEvent, AutoRhythm, AutoWritingConfig, InteractiveFlow, InteractiveGateResult, InteractiveStreamChunkEvent, PlotOption, PlotSelection, IpcResult, LandmarkType, OutlineItem, OutlineStatus, SearchResult, SettingEntry, SettingType, Snapshot, SnapshotType, UpdateChapterParams, Volume, WordFreqResult, KnowledgeEntry, CreateKnowledgeInput, KnowledgeStatus, KnowledgeType, CockpitSummary, ChapterBridgeResult, PublishStatus, WritingStats, KnowledgeExtractionResult } from '../shared/types' const electronAPI = { window: { minimize: (): Promise => ipcRenderer.invoke(IPC.WINDOW_MINIMIZE), maximize: (): Promise => ipcRenderer.invoke(IPC.WINDOW_MAXIMIZE), close: (): Promise => ipcRenderer.invoke(IPC.WINDOW_CLOSE) }, settings: { get: (): Promise> => ipcRenderer.invoke(IPC.SETTINGS_GET), update: (partial: Partial): Promise> => ipcRenderer.invoke(IPC.SETTINGS_UPDATE, partial) }, book: { list: (): Promise> => ipcRenderer.invoke(IPC.BOOK_LIST), create: (params: CreateBookParams): Promise> => ipcRenderer.invoke(IPC.BOOK_CREATE, params), delete: (bookId: string): Promise> => ipcRenderer.invoke(IPC.BOOK_DELETE, { bookId }), open: (bookId: string): Promise> => ipcRenderer.invoke(IPC.BOOK_OPEN, { bookId }), updateMeta: ( bookId: string, patch: { lastChapterId?: string | null; status?: BookMeta['status'] } ): Promise> => ipcRenderer.invoke(IPC.BOOK_UPDATE_META, { bookId, ...patch }) }, volume: { create: (bookId: string, name: string): Promise> => ipcRenderer.invoke(IPC.VOLUME_CREATE, { bookId, name }), update: ( bookId: string, volumeId: string, patch: { name?: string; description?: string } ): Promise> => ipcRenderer.invoke(IPC.VOLUME_UPDATE, { bookId, volumeId, ...patch }), delete: (bookId: string, volumeId: string): Promise> => ipcRenderer.invoke(IPC.VOLUME_DELETE, { bookId, volumeId }) }, chapter: { create: (bookId: string, volumeId: string, title: string): Promise> => ipcRenderer.invoke(IPC.CHAPTER_CREATE, { bookId, volumeId, title }), get: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.CHAPTER_GET, { bookId, chapterId }), update: (params: UpdateChapterParams): Promise> => ipcRenderer.invoke(IPC.CHAPTER_UPDATE, params), delete: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.CHAPTER_DELETE, { bookId, chapterId }), reorder: (bookId: string, volumeId: string, orderedIds: string[]): Promise> => ipcRenderer.invoke(IPC.CHAPTER_REORDER, { bookId, volumeId, orderedIds }), moveToVolume: ( bookId: string, chapterId: string, targetVolumeId: string, targetIndex: number ): Promise> => ipcRenderer.invoke(IPC.CHAPTER_MOVE_TO_VOLUME, { bookId, chapterId, targetVolumeId, targetIndex }), setPublishStatus: ( bookId: string, chapterId: string, publishStatus: PublishStatus ): Promise> => ipcRenderer.invoke(IPC.CHAPTER_SET_PUBLISH_STATUS, { bookId, chapterId, publishStatus }) }, outline: { list: (bookId: string): Promise> => ipcRenderer.invoke(IPC.OUTLINE_LIST, { bookId }), create: ( bookId: string, title: string, parentId?: string | null, sortOrder?: number ): Promise> => ipcRenderer.invoke(IPC.OUTLINE_CREATE, { bookId, parentId, title, sortOrder }), update: ( bookId: string, id: string, patch: Partial<{ title: string description: string status: OutlineStatus expectedWordCount: number | null chapterId: string | null sortOrder: number }> ): Promise> => ipcRenderer.invoke(IPC.OUTLINE_UPDATE, { bookId, id, patch }), delete: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.OUTLINE_DELETE, { bookId, id }), move: ( bookId: string, id: string, parentId: string | null, sortOrder: number ): Promise> => ipcRenderer.invoke(IPC.OUTLINE_MOVE, { bookId, id, parentId, sortOrder }) }, setting: { list: (bookId: string, type?: SettingType): Promise> => ipcRenderer.invoke(IPC.SETTING_LIST, { bookId, type }), create: (bookId: string, type: SettingType, name: string): Promise> => ipcRenderer.invoke(IPC.SETTING_CREATE, { bookId, type, name }), update: ( bookId: string, id: string, patch: Partial<{ name: string; description: string; type: SettingType; properties: Record }> ): Promise> => ipcRenderer.invoke(IPC.SETTING_UPDATE, { bookId, id, patch }), delete: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.SETTING_DELETE, { bookId, id }), syncRefs: (bookId: string, id: string, chapterIds: string[]): Promise> => ipcRenderer.invoke(IPC.SETTING_SYNC_REFS, { bookId, id, chapterIds }) }, inspiration: { list: (bookId: string): Promise> => ipcRenderer.invoke(IPC.INSPIRATION_LIST, { bookId }), create: ( bookId: string, title?: string, content?: string, tags?: string[] ): Promise> => ipcRenderer.invoke(IPC.INSPIRATION_CREATE, { bookId, title, content, tags }), update: ( bookId: string, id: string, patch: Partial<{ title: string; content: string; tags: string[] }> ): Promise> => ipcRenderer.invoke(IPC.INSPIRATION_UPDATE, { bookId, id, patch }), delete: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.INSPIRATION_DELETE, { bookId, id }), convert: ( bookId: string, id: string, targetKind: 'outline' | 'setting', settingType?: SettingType ): Promise> => ipcRenderer.invoke(IPC.INSPIRATION_CONVERT, { bookId, id, targetKind, settingType }) }, snapshot: { list: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_LIST, { bookId, chapterId }), create: ( bookId: string, chapterId: string, type: SnapshotType, name?: string, content?: string ): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_CREATE, { bookId, chapterId, type, name, content }), restore: ( bookId: string, chapterId: string, snapshotId: string ): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_RESTORE, { bookId, chapterId, snapshotId }), delete: (bookId: string, snapshotId: string): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_DELETE, { bookId, snapshotId }), startAutoSave: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_START_AUTO, { bookId, chapterId }), stopAutoSave: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.SNAPSHOT_STOP_AUTO, { bookId, chapterId }) }, bookmark: { list: ( bookId: string, chapterId?: string, resolved?: boolean ): Promise> => ipcRenderer.invoke(IPC.BOOKMARK_LIST, { bookId, chapterId, resolved }), create: ( bookId: string, chapterId: string, position: number, label: string, landmarkType?: LandmarkType ): Promise> => ipcRenderer.invoke(IPC.BOOKMARK_CREATE, { bookId, chapterId, position, label, landmarkType }), update: ( bookId: string, id: string, patch: Partial<{ label: string; position: number; landmarkType: LandmarkType }> ): Promise> => ipcRenderer.invoke(IPC.BOOKMARK_UPDATE, { bookId, id, patch }), resolve: (bookId: string, id: string, resolved: boolean): Promise> => ipcRenderer.invoke(IPC.BOOKMARK_RESOLVE, { bookId, id, resolved }), delete: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.BOOKMARK_DELETE, { bookId, id }) }, search: { query: ( bookId: string, query: string, options?: { regex?: boolean; caseSensitive?: boolean; matchWholeWord?: boolean } ): Promise> => ipcRenderer.invoke(IPC.SEARCH_QUERY, { bookId, query, options }), replace: ( bookId: string, query: string, replacement: string, dryRun: boolean, options?: { regex?: boolean; caseSensitive?: boolean } ): Promise> => ipcRenderer.invoke(IPC.SEARCH_REPLACE, { bookId, query, replacement, dryRun, options }), getHistory: (): Promise> => ipcRenderer.invoke(IPC.SEARCH_GET_HISTORY), saveHistory: (query: string): Promise> => ipcRenderer.invoke(IPC.SEARCH_SAVE_HISTORY, { query }) }, ai: { sessionList: (bookId: string, includeArchived?: boolean): Promise> => ipcRenderer.invoke(IPC.AI_SESSION_LIST, { bookId, includeArchived }), sessionCreate: (bookId: string, title?: string, model?: string): Promise> => ipcRenderer.invoke(IPC.AI_SESSION_CREATE, { bookId, title, model }), sessionUpdate: ( bookId: string, sessionId: string, patch: Partial<{ title: string; model: string; archived: boolean; context: AiContextBinding }> ): Promise> => ipcRenderer.invoke(IPC.AI_SESSION_UPDATE, { bookId, sessionId, patch }), sessionDelete: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.AI_SESSION_DELETE, { bookId, sessionId }), messageList: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.AI_MESSAGE_LIST, { bookId, sessionId }), chat: ( bookId: string, sessionId: string, content: string, prompt?: string ): Promise> => ipcRenderer.invoke(IPC.AI_CHAT, { bookId, sessionId, content, prompt }), abort: (messageId: string): Promise> => ipcRenderer.invoke(IPC.AI_ABORT, { messageId }), buildContext: ( bookId: string, binding: AiContextBinding ): Promise> => ipcRenderer.invoke(IPC.AI_BUILD_CONTEXT, { bookId, binding }), testConnection: (config?: AiConfig): Promise> => ipcRenderer.invoke(IPC.AI_TEST_CONNECTION, { config }), namingCheck: (bookId: string): Promise> => ipcRenderer.invoke(IPC.AI_NAMING_CHECK, { bookId }) }, interactive: { checkGate: (bookId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_CHECK_GATE, { bookId }), getFlow: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_GET_FLOW, { bookId, sessionId }), start: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_START, { bookId, sessionId }), confirmContext: ( bookId: string, flowId: string, binding: AiContextBinding ): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_CONFIRM_CONTEXT, { bookId, flowId, binding }), suggestPlots: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_SUGGEST_PLOTS, { bookId, flowId }), selectPlot: ( bookId: string, flowId: string, selection: PlotSelection ): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_SELECT_PLOT, { bookId, flowId, selection }), generateScene: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_GENERATE_SCENE, { bookId, flowId }), resolveNaming: ( bookId: string, flowId: string, chosenName: string ): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_RESOLVE_NAMING, { bookId, flowId, chosenName }), refineScene: ( bookId: string, flowId: string, instruction: string ): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_REFINE_SCENE, { bookId, flowId, instruction }), acceptScene: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_ACCEPT_SCENE, { bookId, flowId }), finishChapter: ( bookId: string, flowId: string, volumeId: string, title?: string ): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_FINISH_CHAPTER, { bookId, flowId, volumeId, title }), abort: (flowId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_ABORT, { flowId }), getSceneDraft: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.INTERACTIVE_GET_SCENE_DRAFT, { bookId, flowId }) }, auto: { checkGate: (bookId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_CHECK_GATE, { bookId }), getFlow: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_GET_FLOW, { bookId, sessionId }), start: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_START, { bookId, sessionId }), setGoal: ( bookId: string, flowId: string, config: Partial ): Promise> => ipcRenderer.invoke(IPC.AUTO_SET_GOAL, { bookId, flowId, config }), confirmContext: ( bookId: string, flowId: string, binding: AiContextBinding ): Promise> => ipcRenderer.invoke(IPC.AUTO_CONFIRM_CONTEXT, { bookId, flowId, binding }), planScenes: ( bookId: string, flowId: string, contextSummary?: string ): Promise> => ipcRenderer.invoke(IPC.AUTO_PLAN_SCENES, { bookId, flowId, contextSummary }), generate: ( bookId: string, flowId: string, contextSummary?: string ): Promise> => ipcRenderer.invoke(IPC.AUTO_GENERATE, { bookId, flowId, contextSummary }), resolveNaming: ( bookId: string, flowId: string, chosenName: string, contextSummary?: string ): Promise> => ipcRenderer.invoke(IPC.AUTO_RESOLVE_NAMING, { bookId, flowId, chosenName, contextSummary }), pause: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_PAUSE, { bookId, flowId }), resume: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_RESUME, { bookId, flowId }), handoffInteractive: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_HANDOFF_INTERACTIVE, { bookId, flowId }), finishChapter: ( bookId: string, flowId: string, volumeId: string, title?: string ): Promise> => ipcRenderer.invoke(IPC.AUTO_FINISH_CHAPTER, { bookId, flowId, volumeId, title }), abort: (flowId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_ABORT, { flowId }), getSceneDraft: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.AUTO_GET_SCENE_DRAFT, { bookId, flowId }) }, wizard: { getFlow: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_GET_FLOW, { bookId, sessionId }), start: (bookId: string, sessionId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_START, { bookId, sessionId }), setGoal: ( bookId: string, flowId: string, config: Partial ): Promise> => ipcRenderer.invoke(IPC.WIZARD_SET_GOAL, { bookId, flowId, config }), setRhythm: ( bookId: string, flowId: string, rhythm: AutoRhythm, styleNote?: string ): Promise> => ipcRenderer.invoke(IPC.WIZARD_SET_RHYTHM, { bookId, flowId, rhythm, styleNote }), setPov: (bookId: string, flowId: string, povSettingId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_SET_POV, { bookId, flowId, povSettingId }), confirmContext: ( bookId: string, flowId: string, binding: AiContextBinding ): Promise> => ipcRenderer.invoke(IPC.WIZARD_CONFIRM_CONTEXT, { bookId, flowId, binding }), buildPreview: ( bookId: string, flowId: string ): Promise> => ipcRenderer.invoke(IPC.WIZARD_BUILD_PREVIEW, { bookId, flowId }), startGenerate: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_START_GENERATE, { bookId, flowId }), handoffInteractive: (bookId: string, flowId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_HANDOFF_INTERACTIVE, { bookId, flowId }), abort: (flowId: string): Promise> => ipcRenderer.invoke(IPC.WIZARD_ABORT, { flowId }) }, knowledge: { list: ( bookId: string, filter?: { status?: KnowledgeStatus; type?: KnowledgeType; forgottenOnly?: boolean } ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_LIST, { bookId, filter }), create: (bookId: string, input: CreateKnowledgeInput): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_CREATE, { bookId, input }), update: ( bookId: string, id: string, patch: Partial ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_UPDATE, { bookId, id, patch }), delete: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_DELETE, { bookId, id }), approve: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_APPROVE, { bookId, id }), reject: (bookId: string, id: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_REJECT, { bookId, id }), batchApprove: (bookId: string, ids: string[]): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_BATCH_APPROVE, { bookId, ids }), createFromBookmark: (bookId: string, bookmarkId: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_CREATE_FROM_BOOKMARK, { bookId, bookmarkId }), stats: ( bookId: string ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_STATS, { bookId }), suggestContext: ( bookId: string, opts?: KnowledgeSuggestOptions ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_SUGGEST_CONTEXT, { bookId, opts }), extractChapter: ( bookId: string, chapterId: string ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_EXTRACT_CHAPTER, { bookId, chapterId }), approveMerge: (bookId: string, pendingId: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_APPROVE_MERGE, { bookId, pendingId }), saveMergeAsNew: (bookId: string, pendingId: string): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_SAVE_MERGE_AS_NEW, { bookId, pendingId }), batchApproveHighConfidence: ( bookId: string, threshold?: number ): Promise> => ipcRenderer.invoke(IPC.KNOWLEDGE_BATCH_APPROVE_HIGH_CONFIDENCE, { bookId, threshold }) }, writing: { getStats: (bookId: string): Promise> => ipcRenderer.invoke(IPC.WRITING_GET_STATS, { bookId }) }, cockpit: { getSummary: (bookId: string, volumeId?: string): Promise> => ipcRenderer.invoke(IPC.COCKPIT_SUMMARY, { bookId, volumeId }), markSeen: (bookId: string): Promise> => ipcRenderer.invoke(IPC.COCKPIT_MARK_SEEN, { bookId }), shouldShowOnOpen: (bookId: string): Promise> => ipcRenderer.invoke(IPC.COCKPIT_SHOULD_SHOW, { bookId }) }, bridge: { get: ( bookId: string, chapterId: string, withAi?: boolean ): Promise> => ipcRenderer.invoke(IPC.BRIDGE_GET, { bookId, chapterId, withAi }), dismiss: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.BRIDGE_DISMISS, { bookId, chapterId }), shouldPrompt: (bookId: string, chapterId: string): Promise> => ipcRenderer.invoke(IPC.BRIDGE_SHOULD_PROMPT, { bookId, chapterId }) }, wordfreq: { analyze: ( bookId: string, scope: { kind: 'book' | 'volume' | 'chapter'; chapterId?: string; volumeId?: string } ): Promise> => ipcRenderer.invoke(IPC.WORDFREQ_ANALYZE, { bookId, scope }) }, shortcut: { getAll: (): Promise>> => ipcRenderer.invoke(IPC.SHORTCUT_GET_ALL), register: (action: ActionId, accelerator: string): Promise> => ipcRenderer.invoke(IPC.SHORTCUT_REGISTER, { action, accelerator }) }, onShortcutTriggered: (callback: (action: ActionId) => void): (() => void) => { const handler = (_event: IpcRendererEvent, payload: { action: ActionId }) => { callback(payload.action) } ipcRenderer.on(IPC.SHORTCUT_TRIGGERED, handler) return () => ipcRenderer.removeListener(IPC.SHORTCUT_TRIGGERED, handler) }, onAiStreamChunk: (callback: (payload: AiStreamChunkEvent) => void): (() => void) => { const handler = (_event: IpcRendererEvent, payload: AiStreamChunkEvent) => { callback(payload) } ipcRenderer.on(IPC.AI_STREAM_CHUNK, handler) return () => ipcRenderer.removeListener(IPC.AI_STREAM_CHUNK, handler) }, onAiNetworkStatus: (callback: (payload: AiNetworkStatusEvent) => void): (() => void) => { const handler = (_event: IpcRendererEvent, payload: AiNetworkStatusEvent) => { callback(payload) } ipcRenderer.on(IPC.AI_NETWORK_STATUS, handler) return () => ipcRenderer.removeListener(IPC.AI_NETWORK_STATUS, handler) }, onInteractiveStreamChunk: (callback: (payload: InteractiveStreamChunkEvent) => void): (() => void) => { const handler = (_event: IpcRendererEvent, payload: InteractiveStreamChunkEvent) => { callback(payload) } ipcRenderer.on(IPC.INTERACTIVE_STREAM_CHUNK, handler) return () => ipcRenderer.removeListener(IPC.INTERACTIVE_STREAM_CHUNK, handler) } } contextBridge.exposeInMainWorld('electronAPI', electronAPI) export type ElectronAPI = typeof electronAPI