8ce35a1e8e
Add chapter reorder, search replace, inspiration capture, and AI chat with context editing, settings, offline handling, and naming checks. Fix dev black screen by keeping process.env reads in the main process only. Co-authored-by: Cursor <cursoragent@cursor.com>
276 lines
5.7 KiB
TypeScript
276 lines
5.7 KiB
TypeScript
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<T> = { ok: true; data: T } | { ok: false; error: IpcError }
|
|
|
|
export interface GlobalSettings {
|
|
penName: string
|
|
onboardingCompleted: boolean
|
|
theme: ThemeId
|
|
language: Language
|
|
dailyWordGoal: number
|
|
shortcuts: Record<ActionId, string>
|
|
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<string, unknown>
|
|
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[]
|
|
}
|