feat: ship v0.9.0 with pomodoro, achievements, and injection history
Add pomodoro timer with goal notifications, writing streak milestones, and knowledge injection logging with UI previews across AI writing flows. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import { IPC } from '../../../shared/ipc-channels'
|
||||
import type { AchievementService } from '../../services/achievement.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
export function registerAchievementHandlers(achievement: AchievementService): void {
|
||||
ipcMain.handle(IPC.ACHIEVEMENT_LIST, (_e, { bookId }: { bookId: string }) =>
|
||||
wrap(() => achievement.listAchievements(bookId))
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { checkInteractiveGate } from '../../services/interactive-gate.service'
|
||||
import { AutoWritingService } from '../../services/auto-writing.service'
|
||||
import { scheduleChapterExtraction } from '../../services/knowledge-extraction-runner'
|
||||
import { trackerFor } from '../../services/chapter-writing-tracker.service'
|
||||
import { recordKnowledgeInjection } from '../../services/knowledge-injection-runner'
|
||||
import type { WritingLogService } from '../../services/writing-log.service'
|
||||
import { InteractiveRepository } from '../../db/repositories/interactive.repo'
|
||||
import { wrap } from '../result'
|
||||
@@ -89,6 +90,12 @@ export function registerAutoHandlers(
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
recordKnowledgeInjection(registry, bookId, {
|
||||
knowledgeIds: binding.knowledgeIds,
|
||||
flowMode: 'auto',
|
||||
flowId,
|
||||
chapterId: registry.getMeta(bookId)?.lastChapterId ?? undefined
|
||||
})
|
||||
return svc.enrichFlow(svc.confirmContext(flowId, payload))
|
||||
})
|
||||
)
|
||||
|
||||
@@ -3,19 +3,29 @@ import { IPC } from '../../../shared/ipc-channels'
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { CockpitService } from '../../services/cockpit.service'
|
||||
import type { GlobalSettingsService } from '../../services/global-settings'
|
||||
import type { AchievementService } from '../../services/achievement.service'
|
||||
import type { PomodoroDailyRepository } from '../../db/repositories/pomodoro-daily.repo'
|
||||
import type { WritingLogService } from '../../services/writing-log.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
export function registerCockpitHandlers(
|
||||
registry: BookRegistryService,
|
||||
settings: GlobalSettingsService,
|
||||
writingLogs: WritingLogService
|
||||
writingLogs: WritingLogService,
|
||||
achievementService: AchievementService,
|
||||
pomodoroDaily: PomodoroDailyRepository
|
||||
): void {
|
||||
ipcMain.handle(
|
||||
IPC.COCKPIT_SUMMARY,
|
||||
(_e, { bookId, volumeId }: { bookId: string; volumeId?: string }) =>
|
||||
wrap(() =>
|
||||
new CockpitService(registry.getDb(bookId), settings, writingLogs).getSummary(volumeId, bookId)
|
||||
new CockpitService(
|
||||
registry.getDb(bookId),
|
||||
settings,
|
||||
writingLogs,
|
||||
achievementService,
|
||||
pomodoroDaily
|
||||
).getSummary(volumeId, bookId)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { checkInteractiveGate } from '../../services/interactive-gate.service'
|
||||
import { InteractiveWritingService } from '../../services/interactive-writing.service'
|
||||
import { scheduleChapterExtraction } from '../../services/knowledge-extraction-runner'
|
||||
import { trackerFor } from '../../services/chapter-writing-tracker.service'
|
||||
import { recordKnowledgeInjection } from '../../services/knowledge-injection-runner'
|
||||
import type { WritingLogService } from '../../services/writing-log.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
@@ -66,6 +67,12 @@ export function registerInteractiveHandlers(
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
recordKnowledgeInjection(registry, bookId, {
|
||||
knowledgeIds: binding.knowledgeIds,
|
||||
flowMode: 'interactive',
|
||||
flowId,
|
||||
chapterId: registry.getMeta(bookId)?.lastChapterId ?? undefined
|
||||
})
|
||||
const flow = serviceFor(registry, bookId, aiClient).confirmContext(flowId, payload)
|
||||
return serviceFor(registry, bookId, aiClient).enrichFlow(flow)
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { AiClientService } from '../../services/ai-client.service'
|
||||
import type { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { KnowledgeRepository } from '../../db/repositories/knowledge.repo'
|
||||
import { KnowledgeExtractionService } from '../../services/knowledge-extraction.service'
|
||||
import { KnowledgeInjectionService } from '../../services/knowledge-injection.service'
|
||||
import { KnowledgeRetrievalService } from '../../services/knowledge-retrieval.service'
|
||||
import { KnowledgeService } from '../../services/knowledge.service'
|
||||
import { wrap } from '../result'
|
||||
@@ -120,4 +121,15 @@ export function registerKnowledgeHandlers(
|
||||
return new KnowledgeService(registry.getDb(bookId)).batchApproveHighConfidence(t)
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.KNOWLEDGE_LIST_INJECTIONS,
|
||||
(
|
||||
_e,
|
||||
{ bookId, entryId, limit }: { bookId: string; entryId: string; limit?: number }
|
||||
) =>
|
||||
wrap(() =>
|
||||
new KnowledgeInjectionService(registry.getDb(bookId)).listForEntry(entryId, limit ?? 50)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import { IPC } from '../../../shared/ipc-channels'
|
||||
import type { PomodoroService } from '../../services/pomodoro.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
export function registerPomodoroHandlers(pomodoro: PomodoroService): void {
|
||||
ipcMain.handle(IPC.POMODORO_START, (_e, { bookId }: { bookId: string }) =>
|
||||
wrap(() => pomodoro.start(bookId))
|
||||
)
|
||||
ipcMain.handle(IPC.POMODORO_PAUSE, () => wrap(() => pomodoro.pause()))
|
||||
ipcMain.handle(IPC.POMODORO_RESUME, () => wrap(() => pomodoro.resume()))
|
||||
ipcMain.handle(IPC.POMODORO_CANCEL, () => wrap(() => pomodoro.cancel()))
|
||||
ipcMain.handle(IPC.POMODORO_GET_STATE, () => wrap(() => pomodoro.getState()))
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { AiClientService } from '../../services/ai-client.service'
|
||||
import { buildFlowContextPayload, readFlowSystemPrompt } from '../../services/flow-context.util'
|
||||
import { WizardWritingService } from '../../services/wizard-writing.service'
|
||||
import { recordKnowledgeInjection } from '../../services/knowledge-injection-runner'
|
||||
import { InteractiveRepository } from '../../db/repositories/interactive.repo'
|
||||
import { wrap } from '../result'
|
||||
|
||||
@@ -99,6 +100,12 @@ export function registerWizardHandlers(
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
recordKnowledgeInjection(registry, bookId, {
|
||||
knowledgeIds: binding.knowledgeIds,
|
||||
flowMode: 'wizard',
|
||||
flowId,
|
||||
chapterId: registry.getMeta(bookId)?.lastChapterId ?? undefined
|
||||
})
|
||||
const svc = serviceFor(registry, bookId, aiClient)
|
||||
return svc.enrichFlow(svc.confirmContext(flowId, payload))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user