fe6e411d2c
Wire .novel/.novel-all export-import through modals, settings backup, and home bulk export with progress IPC. Co-authored-by: Cursor <cursoragent@cursor.com>
496 lines
18 KiB
TypeScript
496 lines
18 KiB
TypeScript
import type {
|
|
ActionId,
|
|
Bookmark,
|
|
BookMeta,
|
|
BookOpenResult,
|
|
Chapter,
|
|
CreateBookParams,
|
|
GlobalSettings,
|
|
InspirationEntry,
|
|
AiContextBinding,
|
|
AiContextBuildResult,
|
|
AiConfig,
|
|
AiMessage,
|
|
AiSession,
|
|
NamingConflict,
|
|
AiStreamChunkEvent,
|
|
AiNetworkStatusEvent,
|
|
InteractiveFlow,
|
|
InteractiveGateResult,
|
|
InteractiveStreamChunkEvent,
|
|
AutoRhythm,
|
|
AutoWritingConfig,
|
|
PlotOption,
|
|
PlotSelection,
|
|
IpcResult,
|
|
LandmarkType,
|
|
OutlineItem,
|
|
OutlineStatus,
|
|
SearchResult,
|
|
SettingEntry,
|
|
SettingType,
|
|
Snapshot,
|
|
SnapshotType,
|
|
UpdateChapterParams,
|
|
UpdateBookMetaParams,
|
|
ChapterTag,
|
|
Volume,
|
|
WordFreqResult,
|
|
KnowledgeEntry,
|
|
KnowledgeSuggestOptions,
|
|
ScoredKnowledge,
|
|
CreateKnowledgeInput,
|
|
KnowledgeStatus,
|
|
KnowledgeType,
|
|
CockpitSummary,
|
|
ChapterBridgeResult,
|
|
PublishStatus,
|
|
WritingStats,
|
|
KnowledgeExtractionResult,
|
|
PomodoroState,
|
|
GoalNotificationPayload,
|
|
KnowledgeInjectionLog,
|
|
WritingAchievement,
|
|
PomodoroDuration,
|
|
CharacterGraphData,
|
|
CharacterRelationship,
|
|
WritingAnalyticsSummary,
|
|
ImportPreviewResult,
|
|
ImportExecuteParams,
|
|
ImportSplitMode
|
|
} from './types'
|
|
import type { PackImportStrategy, PackImportReport, PackProgressEvent } from './novel-pack'
|
|
|
|
export interface ElectronAPI {
|
|
window: {
|
|
minimize: () => Promise<void>
|
|
maximize: () => Promise<void>
|
|
close: () => Promise<void>
|
|
}
|
|
settings: {
|
|
get: () => Promise<IpcResult<GlobalSettings>>
|
|
update: (partial: Partial<GlobalSettings>) => Promise<IpcResult<GlobalSettings>>
|
|
}
|
|
book: {
|
|
list: () => Promise<IpcResult<BookMeta[]>>
|
|
create: (params: CreateBookParams) => Promise<IpcResult<BookMeta>>
|
|
delete: (bookId: string) => Promise<IpcResult<void>>
|
|
open: (bookId: string) => Promise<IpcResult<BookOpenResult>>
|
|
updateMeta: (bookId: string, patch: UpdateBookMetaParams) => Promise<IpcResult<BookMeta>>
|
|
pickCover: (bookId: string) => Promise<IpcResult<BookMeta | null>>
|
|
}
|
|
bookPrefs: {
|
|
get: (bookId: string, key: string) => Promise<IpcResult<string | null>>
|
|
set: (bookId: string, key: string, value: string) => Promise<IpcResult<void>>
|
|
}
|
|
volume: {
|
|
create: (bookId: string, name: string) => Promise<IpcResult<Volume>>
|
|
update: (
|
|
bookId: string,
|
|
volumeId: string,
|
|
patch: { name?: string; description?: string }
|
|
) => Promise<IpcResult<Volume>>
|
|
delete: (bookId: string, volumeId: string) => Promise<IpcResult<void>>
|
|
}
|
|
chapter: {
|
|
create: (bookId: string, volumeId: string, title: string) => Promise<IpcResult<Chapter>>
|
|
get: (bookId: string, chapterId: string) => Promise<IpcResult<Chapter>>
|
|
update: (params: UpdateChapterParams) => Promise<IpcResult<Chapter>>
|
|
delete: (bookId: string, chapterId: string) => Promise<IpcResult<void>>
|
|
reorder: (bookId: string, volumeId: string, orderedIds: string[]) => Promise<IpcResult<Chapter[]>>
|
|
moveToVolume: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
targetVolumeId: string,
|
|
targetIndex: number
|
|
) => Promise<IpcResult<Chapter>>
|
|
setPublishStatus: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
publishStatus: PublishStatus
|
|
) => Promise<IpcResult<Chapter>>
|
|
}
|
|
chapterTag: {
|
|
list: (bookId: string, chapterId: string) => Promise<IpcResult<ChapterTag[]>>
|
|
set: (bookId: string, chapterId: string, tag: string, color?: string) => Promise<IpcResult<void>>
|
|
remove: (bookId: string, chapterId: string, tag: string) => Promise<IpcResult<void>>
|
|
}
|
|
outline: {
|
|
list: (bookId: string) => Promise<IpcResult<OutlineItem[]>>
|
|
create: (
|
|
bookId: string,
|
|
title: string,
|
|
parentId?: string | null,
|
|
sortOrder?: number
|
|
) => Promise<IpcResult<OutlineItem>>
|
|
update: (
|
|
bookId: string,
|
|
id: string,
|
|
patch: Partial<{
|
|
title: string
|
|
description: string
|
|
status: OutlineStatus
|
|
expectedWordCount: number | null
|
|
chapterId: string | null
|
|
sortOrder: number
|
|
}>
|
|
) => Promise<IpcResult<OutlineItem>>
|
|
delete: (bookId: string, id: string) => Promise<IpcResult<void>>
|
|
move: (
|
|
bookId: string,
|
|
id: string,
|
|
parentId: string | null,
|
|
sortOrder: number
|
|
) => Promise<IpcResult<OutlineItem>>
|
|
}
|
|
setting: {
|
|
list: (bookId: string, type?: SettingType) => Promise<IpcResult<SettingEntry[]>>
|
|
create: (bookId: string, type: SettingType, name: string) => Promise<IpcResult<SettingEntry>>
|
|
update: (
|
|
bookId: string,
|
|
id: string,
|
|
patch: Partial<{ name: string; description: string; type: SettingType; properties: Record<string, unknown> }>
|
|
) => Promise<IpcResult<SettingEntry>>
|
|
delete: (bookId: string, id: string) => Promise<IpcResult<void>>
|
|
syncRefs: (bookId: string, id: string, chapterIds: string[]) => Promise<IpcResult<SettingEntry>>
|
|
}
|
|
inspiration: {
|
|
list: (bookId: string) => Promise<IpcResult<InspirationEntry[]>>
|
|
create: (
|
|
bookId: string,
|
|
title?: string,
|
|
content?: string,
|
|
tags?: string[]
|
|
) => Promise<IpcResult<InspirationEntry>>
|
|
update: (
|
|
bookId: string,
|
|
id: string,
|
|
patch: Partial<{ title: string; content: string; tags: string[] }>
|
|
) => Promise<IpcResult<InspirationEntry>>
|
|
delete: (bookId: string, id: string) => Promise<IpcResult<void>>
|
|
convert: (
|
|
bookId: string,
|
|
id: string,
|
|
targetKind: 'outline' | 'setting',
|
|
settingType?: SettingType
|
|
) => Promise<IpcResult<OutlineItem | SettingEntry>>
|
|
}
|
|
snapshot: {
|
|
list: (bookId: string, chapterId: string) => Promise<IpcResult<Snapshot[]>>
|
|
create: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
type: SnapshotType,
|
|
name?: string,
|
|
content?: string
|
|
) => Promise<IpcResult<Snapshot>>
|
|
restore: (bookId: string, chapterId: string, snapshotId: string) => Promise<IpcResult<Chapter>>
|
|
delete: (bookId: string, snapshotId: string) => Promise<IpcResult<void>>
|
|
startAutoSave: (bookId: string, chapterId: string) => Promise<IpcResult<void>>
|
|
stopAutoSave: (bookId: string, chapterId: string) => Promise<IpcResult<void>>
|
|
}
|
|
bookmark: {
|
|
list: (bookId: string, chapterId?: string, resolved?: boolean) => Promise<IpcResult<Bookmark[]>>
|
|
create: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
position: number,
|
|
label: string,
|
|
landmarkType?: LandmarkType
|
|
) => Promise<IpcResult<Bookmark>>
|
|
update: (
|
|
bookId: string,
|
|
id: string,
|
|
patch: Partial<{ label: string; position: number; landmarkType: LandmarkType }>
|
|
) => Promise<IpcResult<Bookmark>>
|
|
resolve: (bookId: string, id: string, resolved: boolean) => Promise<IpcResult<Bookmark>>
|
|
delete: (bookId: string, id: string) => Promise<IpcResult<void>>
|
|
}
|
|
search: {
|
|
query: (
|
|
bookId: string,
|
|
query: string,
|
|
options?: { regex?: boolean; caseSensitive?: boolean; matchWholeWord?: boolean }
|
|
) => Promise<IpcResult<SearchResult[]>>
|
|
replace: (
|
|
bookId: string,
|
|
query: string,
|
|
replacement: string,
|
|
dryRun: boolean,
|
|
options?: { regex?: boolean; caseSensitive?: boolean }
|
|
) => Promise<IpcResult<{ count: number; previews: SearchResult[] }>>
|
|
getHistory: () => Promise<IpcResult<string[]>>
|
|
saveHistory: (query: string) => Promise<IpcResult<string[]>>
|
|
}
|
|
ai: {
|
|
sessionList: (bookId: string, includeArchived?: boolean) => Promise<IpcResult<AiSession[]>>
|
|
sessionCreate: (bookId: string, title?: string, model?: string) => Promise<IpcResult<AiSession>>
|
|
sessionUpdate: (
|
|
bookId: string,
|
|
sessionId: string,
|
|
patch: Partial<{ title: string; model: string; archived: boolean; context: AiContextBinding }>
|
|
) => Promise<IpcResult<AiSession>>
|
|
sessionDelete: (bookId: string, sessionId: string) => Promise<IpcResult<void>>
|
|
sessionExport: (
|
|
bookId: string,
|
|
sessionId: string,
|
|
format?: 'markdown' | 'txt'
|
|
) => Promise<IpcResult<string | null>>
|
|
messageList: (bookId: string, sessionId: string) => Promise<IpcResult<AiMessage[]>>
|
|
chat: (
|
|
bookId: string,
|
|
sessionId: string,
|
|
content: string,
|
|
prompt?: string
|
|
) => Promise<IpcResult<{ messageId: string }>>
|
|
abort: (messageId: string) => Promise<IpcResult<void>>
|
|
buildContext: (bookId: string, binding: AiContextBinding) => Promise<IpcResult<AiContextBuildResult>>
|
|
testConnection: (config?: AiConfig) => Promise<IpcResult<{ ok: true }>>
|
|
namingCheck: (bookId: string) => Promise<IpcResult<NamingConflict[]>>
|
|
}
|
|
interactive: {
|
|
checkGate: (bookId: string) => Promise<IpcResult<InteractiveGateResult>>
|
|
getFlow: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow | null>>
|
|
start: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
confirmContext: (
|
|
bookId: string,
|
|
flowId: string,
|
|
binding: AiContextBinding
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
suggestPlots: (bookId: string, flowId: string) => Promise<IpcResult<PlotOption[]>>
|
|
selectPlot: (
|
|
bookId: string,
|
|
flowId: string,
|
|
selection: PlotSelection
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
generateScene: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
resolveNaming: (
|
|
bookId: string,
|
|
flowId: string,
|
|
chosenName: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
refineScene: (
|
|
bookId: string,
|
|
flowId: string,
|
|
instruction: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
acceptScene: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
finishChapter: (
|
|
bookId: string,
|
|
flowId: string,
|
|
volumeId: string,
|
|
title?: string
|
|
) => Promise<IpcResult<{ chapterId: string }>>
|
|
abort: (flowId: string) => Promise<IpcResult<void>>
|
|
getSceneDraft: (bookId: string, flowId: string) => Promise<IpcResult<string>>
|
|
}
|
|
auto: {
|
|
checkGate: (bookId: string) => Promise<IpcResult<InteractiveGateResult>>
|
|
getFlow: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow | null>>
|
|
start: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
setGoal: (
|
|
bookId: string,
|
|
flowId: string,
|
|
config: Partial<AutoWritingConfig>
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
confirmContext: (
|
|
bookId: string,
|
|
flowId: string,
|
|
binding: AiContextBinding
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
planScenes: (
|
|
bookId: string,
|
|
flowId: string,
|
|
contextSummary?: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
generate: (
|
|
bookId: string,
|
|
flowId: string,
|
|
contextSummary?: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
resolveNaming: (
|
|
bookId: string,
|
|
flowId: string,
|
|
chosenName: string,
|
|
contextSummary?: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
pause: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
resume: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
handoffInteractive: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
finishChapter: (
|
|
bookId: string,
|
|
flowId: string,
|
|
volumeId: string,
|
|
title?: string
|
|
) => Promise<IpcResult<{ chapterId: string }>>
|
|
abort: (flowId: string) => Promise<IpcResult<void>>
|
|
getSceneDraft: (bookId: string, flowId: string) => Promise<IpcResult<string>>
|
|
}
|
|
wizard: {
|
|
getFlow: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow | null>>
|
|
start: (bookId: string, sessionId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
setGoal: (
|
|
bookId: string,
|
|
flowId: string,
|
|
config: Partial<AutoWritingConfig>
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
setRhythm: (
|
|
bookId: string,
|
|
flowId: string,
|
|
rhythm: AutoRhythm,
|
|
styleNote?: string
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
setPov: (bookId: string, flowId: string, povSettingId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
confirmContext: (
|
|
bookId: string,
|
|
flowId: string,
|
|
binding: AiContextBinding
|
|
) => Promise<IpcResult<InteractiveFlow>>
|
|
buildPreview: (
|
|
bookId: string,
|
|
flowId: string
|
|
) => Promise<IpcResult<{ preview: string; flow: InteractiveFlow }>>
|
|
startGenerate: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
handoffInteractive: (bookId: string, flowId: string) => Promise<IpcResult<InteractiveFlow>>
|
|
abort: (flowId: string) => Promise<IpcResult<void>>
|
|
}
|
|
knowledge: {
|
|
list: (
|
|
bookId: string,
|
|
filter?: { status?: KnowledgeStatus; type?: KnowledgeType; forgottenOnly?: boolean }
|
|
) => Promise<IpcResult<KnowledgeEntry[]>>
|
|
create: (bookId: string, input: CreateKnowledgeInput) => Promise<IpcResult<KnowledgeEntry>>
|
|
update: (
|
|
bookId: string,
|
|
id: string,
|
|
patch: Partial<CreateKnowledgeInput & { status: KnowledgeStatus }>
|
|
) => Promise<IpcResult<KnowledgeEntry>>
|
|
delete: (bookId: string, id: string) => Promise<IpcResult<void>>
|
|
approve: (bookId: string, id: string) => Promise<IpcResult<KnowledgeEntry>>
|
|
reject: (bookId: string, id: string) => Promise<IpcResult<KnowledgeEntry>>
|
|
batchApprove: (bookId: string, ids: string[]) => Promise<IpcResult<number>>
|
|
createFromBookmark: (bookId: string, bookmarkId: string) => Promise<IpcResult<KnowledgeEntry>>
|
|
stats: (
|
|
bookId: string
|
|
) => Promise<IpcResult<{ buried: number; resolved: number; forgotten: number }>>
|
|
suggestContext: (
|
|
bookId: string,
|
|
opts?: KnowledgeSuggestOptions
|
|
) => Promise<IpcResult<ScoredKnowledge[]>>
|
|
extractChapter: (
|
|
bookId: string,
|
|
chapterId: string
|
|
) => Promise<IpcResult<KnowledgeExtractionResult>>
|
|
approveMerge: (bookId: string, pendingId: string) => Promise<IpcResult<KnowledgeEntry>>
|
|
saveMergeAsNew: (bookId: string, pendingId: string) => Promise<IpcResult<KnowledgeEntry>>
|
|
batchApproveHighConfidence: (bookId: string, threshold?: number) => Promise<IpcResult<number>>
|
|
listInjections: (
|
|
bookId: string,
|
|
entryId: string,
|
|
limit?: number
|
|
) => Promise<IpcResult<KnowledgeInjectionLog[]>>
|
|
}
|
|
writing: {
|
|
getStats: (bookId: string) => Promise<IpcResult<WritingStats>>
|
|
}
|
|
pomodoro: {
|
|
start: (bookId: string) => Promise<IpcResult<PomodoroState>>
|
|
pause: () => Promise<IpcResult<PomodoroState>>
|
|
resume: () => Promise<IpcResult<PomodoroState>>
|
|
cancel: () => Promise<IpcResult<PomodoroState>>
|
|
getState: () => Promise<IpcResult<PomodoroState>>
|
|
}
|
|
achievement: {
|
|
list: (bookId: string) => Promise<IpcResult<WritingAchievement[]>>
|
|
}
|
|
cockpit: {
|
|
getSummary: (bookId: string, volumeId?: string) => Promise<IpcResult<CockpitSummary>>
|
|
markSeen: (bookId: string) => Promise<IpcResult<void>>
|
|
shouldShowOnOpen: (bookId: string) => Promise<IpcResult<boolean>>
|
|
}
|
|
graph: {
|
|
getData: (bookId: string, filter?: 'all' | 'connected') => Promise<IpcResult<CharacterGraphData>>
|
|
upsertRelationship: (
|
|
bookId: string,
|
|
sourceId: string,
|
|
relationship: Partial<CharacterRelationship> & {
|
|
targetId: string
|
|
label: string
|
|
intimacy: number
|
|
}
|
|
) => Promise<IpcResult<CharacterRelationship>>
|
|
deleteRelationship: (
|
|
bookId: string,
|
|
sourceId: string,
|
|
relationshipId: string
|
|
) => Promise<IpcResult<void>>
|
|
}
|
|
analytics: {
|
|
getSummary: (bookId: string) => Promise<IpcResult<WritingAnalyticsSummary>>
|
|
}
|
|
import: {
|
|
pickFile: () => Promise<IpcResult<{ canceled: boolean; filePath?: string }>>
|
|
preview: (
|
|
filePath: string,
|
|
splitMode: ImportSplitMode,
|
|
customRegex?: string
|
|
) => Promise<IpcResult<ImportPreviewResult>>
|
|
execute: (params: ImportExecuteParams) => Promise<IpcResult<string>>
|
|
}
|
|
export: {
|
|
formatChapter: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
presetId: string
|
|
) => Promise<IpcResult<string>>
|
|
copyClipboard: (text: string) => Promise<IpcResult<void>>
|
|
saveTxt: (text: string, defaultName: string) => Promise<IpcResult<string | null>>
|
|
}
|
|
pack: {
|
|
pickFile: (
|
|
mode: 'novel' | 'novel-all' | 'save-novel' | 'save-all' | 'import'
|
|
) => Promise<IpcResult<string | null>>
|
|
exportBook: (bookId: string, destPath: string) => Promise<IpcResult<void>>
|
|
importBook: (filePath: string) => Promise<IpcResult<string>>
|
|
exportAll: (destPath: string) => Promise<IpcResult<void>>
|
|
importAll: (filePath: string, strategy: PackImportStrategy) => Promise<IpcResult<PackImportReport>>
|
|
estimateExportAll: () => Promise<IpcResult<{ bytes: number; needsConfirm: boolean }>>
|
|
cancel: () => Promise<IpcResult<void>>
|
|
}
|
|
bridge: {
|
|
get: (
|
|
bookId: string,
|
|
chapterId: string,
|
|
withAi?: boolean
|
|
) => Promise<IpcResult<ChapterBridgeResult>>
|
|
dismiss: (bookId: string, chapterId: string) => Promise<IpcResult<void>>
|
|
shouldPrompt: (bookId: string, chapterId: string) => Promise<IpcResult<boolean>>
|
|
}
|
|
wordfreq: {
|
|
analyze: (
|
|
bookId: string,
|
|
scope: { kind: 'book' | 'volume' | 'chapter'; chapterId?: string; volumeId?: string }
|
|
) => Promise<IpcResult<WordFreqResult>>
|
|
}
|
|
shortcut: {
|
|
getAll: () => Promise<IpcResult<Record<ActionId, string>>>
|
|
register: (action: ActionId, accelerator: string) => Promise<IpcResult<void>>
|
|
}
|
|
onShortcutTriggered: (callback: (action: ActionId) => void) => () => void
|
|
onAiStreamChunk: (callback: (payload: AiStreamChunkEvent) => void) => () => void
|
|
onAiNetworkStatus: (callback: (payload: AiNetworkStatusEvent) => void) => () => void
|
|
onInteractiveStreamChunk: (callback: (payload: InteractiveStreamChunkEvent) => void) => () => void
|
|
onPomodoroTick: (callback: (state: PomodoroState) => void) => () => void
|
|
onGoalNotification: (callback: (payload: GoalNotificationPayload) => void) => () => void
|
|
onImportProgress: (callback: (payload: { current: number; total: number }) => void) => () => void
|
|
onPackProgress: (callback: (payload: PackProgressEvent) => void) => () => void
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI
|
|
}
|
|
}
|
|
|
|
export {}
|