Files
bilin/src/shared/types.ts
T
bing 8ce35a1e8e feat: ship v0.3.0 with P2.1 editor polish and P3 AI collaboration
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>
2026-07-06 16:33:56 +08:00

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[]
}