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>
This commit is contained in:
+66
-1
@@ -9,6 +9,14 @@ import type {
|
||||
CreateBookParams,
|
||||
GlobalSettings,
|
||||
InspirationEntry,
|
||||
AiContextBinding,
|
||||
AiContextBuildResult,
|
||||
AiConfig,
|
||||
AiMessage,
|
||||
AiSession,
|
||||
NamingConflict,
|
||||
AiStreamChunkEvent,
|
||||
AiNetworkStatusEvent,
|
||||
IpcResult,
|
||||
LandmarkType,
|
||||
OutlineItem,
|
||||
@@ -67,7 +75,16 @@ const electronAPI = {
|
||||
update: (params: UpdateChapterParams): Promise<IpcResult<Chapter>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_UPDATE, params),
|
||||
delete: (bookId: string, chapterId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_DELETE, { bookId, chapterId })
|
||||
ipcRenderer.invoke(IPC.CHAPTER_DELETE, { bookId, chapterId }),
|
||||
reorder: (bookId: string, volumeId: string, orderedIds: string[]): Promise<IpcResult<Chapter[]>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_REORDER, { bookId, volumeId, orderedIds }),
|
||||
moveToVolume: (
|
||||
bookId: string,
|
||||
chapterId: string,
|
||||
targetVolumeId: string,
|
||||
targetIndex: number
|
||||
): Promise<IpcResult<Chapter>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_MOVE_TO_VOLUME, { bookId, chapterId, targetVolumeId, targetIndex })
|
||||
},
|
||||
outline: {
|
||||
list: (bookId: string): Promise<IpcResult<OutlineItem[]>> =>
|
||||
@@ -213,6 +230,40 @@ const electronAPI = {
|
||||
saveHistory: (query: string): Promise<IpcResult<string[]>> =>
|
||||
ipcRenderer.invoke(IPC.SEARCH_SAVE_HISTORY, { query })
|
||||
},
|
||||
ai: {
|
||||
sessionList: (bookId: string, includeArchived?: boolean): Promise<IpcResult<AiSession[]>> =>
|
||||
ipcRenderer.invoke(IPC.AI_SESSION_LIST, { bookId, includeArchived }),
|
||||
sessionCreate: (bookId: string, title?: string, model?: string): Promise<IpcResult<AiSession>> =>
|
||||
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<IpcResult<AiSession>> =>
|
||||
ipcRenderer.invoke(IPC.AI_SESSION_UPDATE, { bookId, sessionId, patch }),
|
||||
sessionDelete: (bookId: string, sessionId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.AI_SESSION_DELETE, { bookId, sessionId }),
|
||||
messageList: (bookId: string, sessionId: string): Promise<IpcResult<AiMessage[]>> =>
|
||||
ipcRenderer.invoke(IPC.AI_MESSAGE_LIST, { bookId, sessionId }),
|
||||
chat: (
|
||||
bookId: string,
|
||||
sessionId: string,
|
||||
content: string,
|
||||
prompt?: string
|
||||
): Promise<IpcResult<{ messageId: string }>> =>
|
||||
ipcRenderer.invoke(IPC.AI_CHAT, { bookId, sessionId, content, prompt }),
|
||||
abort: (messageId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.AI_ABORT, { messageId }),
|
||||
buildContext: (
|
||||
bookId: string,
|
||||
binding: AiContextBinding
|
||||
): Promise<IpcResult<AiContextBuildResult>> =>
|
||||
ipcRenderer.invoke(IPC.AI_BUILD_CONTEXT, { bookId, binding }),
|
||||
testConnection: (config?: AiConfig): Promise<IpcResult<{ ok: true }>> =>
|
||||
ipcRenderer.invoke(IPC.AI_TEST_CONNECTION, { config }),
|
||||
namingCheck: (bookId: string): Promise<IpcResult<NamingConflict[]>> =>
|
||||
ipcRenderer.invoke(IPC.AI_NAMING_CHECK, { bookId })
|
||||
},
|
||||
wordfreq: {
|
||||
analyze: (
|
||||
bookId: string,
|
||||
@@ -232,6 +283,20 @@ const electronAPI = {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user