export type ThemeId = | 'default' | 'bamboo' | 'moonlit' | 'ricepaper' | 'mist' | 'teagarden' | 'twilight' export type Language = 'zh-CN' | 'en' export type ChapterStatus = 'draft' | 'review' | 'done' export type BookStatus = 'draft' | 'ongoing' | 'done' export type PublishStatus = 'draft' | 'ready' | 'published' export type OutlineStatus = 'pending' | 'writing' | 'done' | 'abandoned' export type SettingType = 'character' | 'location' | 'item' | 'skill' | 'faction' | 'custom' export type SnapshotType = 'auto' | 'manual' | 'persist' | 'ai' export type LandmarkType = 'todo' | 'foreshadow' | 'research' | 'custom' export type EditTargetKind = 'chapter' | 'outline' | 'setting' | 'inspiration' export type EditTarget = { kind: EditTargetKind; id: string } export type SearchScope = 'all' | 'volume' | 'chapter' export type SearchSourceKind = 'chapter' | 'outline' | 'setting' | 'inspiration' | 'bookmark' export type ActionId = | 'saveChapter' | 'newChapter' | 'focusMode' | 'globalSearch' | 'closeTab' | 'openReference' | 'insertLandmark' | 'openLandmarks' | 'exportBook' | 'toggleTTS' | 'captureInspiration' export enum ErrorCode { DB_READ_FAILED = 'DB_READ_FAILED', DB_WRITE_FAILED = 'DB_WRITE_FAILED', FILE_NOT_FOUND = 'FILE_NOT_FOUND', IMPORT_INVALID = 'IMPORT_INVALID', UNKNOWN = 'UNKNOWN' } export interface IpcError { code: ErrorCode message: string recoverable: boolean } export type IpcResult = { ok: true; data: T } | { ok: false; error: IpcError } export interface GlobalSettings { penName: string onboardingCompleted: boolean theme: ThemeId language: Language dailyWordGoal: number shortcuts: Record snapshotIntervalMs: number snapshotMaxAuto: number snapshotMaxPersist: number searchHistory: string[] aiConfig: AiConfig namingIgnoreWords: string[] } export interface BookMeta { id: string name: string category: string targetWordCount: number | null dbPath: string status: BookStatus lastOpenedAt: string lastChapterId: string | null createdAt: string } export interface CreateBookParams { name: string category: string targetWordCount?: number | null createSampleChapter?: boolean } export interface Volume { id: string name: string description: string sortOrder: number } export interface Chapter { id: string volumeId: string | null title: string content: string status: ChapterStatus wordCount: number sortOrder: number cursorOffset: number publishStatus?: PublishStatus povCharacterId?: string | null summary?: string storyTime?: string | null } export interface OutlineItem { id: string parentId: string | null title: string description: string status: OutlineStatus expectedWordCount: number | null chapterId: string | null sortOrder: number createdAt: string updatedAt: string children?: OutlineItem[] } export interface SettingEntry { id: string type: SettingType name: string description: string properties: Record chapterIds?: string[] createdAt: string updatedAt: string } export interface InspirationEntry { id: string title: string content: string tags: string[] createdAt: string updatedAt: string } export interface Snapshot { id: string chapterId: string type: SnapshotType name: string content: string createdAt: string } export interface Bookmark { id: string chapterId: string position: number label: string landmarkType: LandmarkType resolved: boolean createdAt: string } export interface SearchOptions { regex?: boolean caseSensitive?: boolean matchWholeWord?: boolean } export interface SearchResult { kind: SearchSourceKind id: string title: string snippet: string chapterId?: string position?: number } export interface WordFreqResult { words: { token: string; count: number }[] } export interface BookOpenResult { meta: BookMeta volumes: Volume[] chapters: Chapter[] outlines: OutlineItem[] settings: SettingEntry[] inspirations: InspirationEntry[] } export interface UpdateChapterParams { bookId: string chapterId: string title?: string content?: string status?: ChapterStatus cursorOffset?: number } export type AiBackend = 'lmstudio' | 'openai' | 'anthropic' export type AiMessageRole = 'user' | 'assistant' | 'system' export type AiWritingMode = 'chat' | 'interactive' | 'auto' | 'wizard' export interface AiConfig { backend: AiBackend baseUrl: string model: string apiKey?: string timeoutMs: number maxTokens: number } export const DEFAULT_AI_CONFIG: AiConfig = { backend: 'lmstudio', baseUrl: 'http://127.0.0.1:1234', model: 'gemma-4-e4b-it', timeoutMs: 60_000, maxTokens: 2048 } export interface AiContextBinding { chapterIds: string[] outlineIds: string[] settingIds: string[] inspirationIds: string[] } export interface AiSession { id: string title: string model: string archived: boolean context: AiContextBinding createdAt: string updatedAt: string } export interface AiMessage { id: string sessionId: string role: AiMessageRole content: string createdAt: string } export interface NamingConflict { termA: string termB: string confidence: number reason: string suggestedCanonical?: string } export interface AiStreamChunkEvent { messageId: string delta: string done: boolean } export interface AiNetworkStatusEvent { online: boolean } export type ContextPreviewKind = 'chapter' | 'outline' | 'setting' | 'inspiration' export interface ContextPreviewItem { kind: ContextPreviewKind id: string title: string excerpt: string charCount: number } export interface AiContextBuildResult { systemPrompt: string preview: ContextPreviewItem[] }