feat: ship v0.7.0 with AI knowledge context integration
Add semi-automatic knowledge suggestions and user-confirmed injection across chat, interactive, auto, and wizard modes; fix writing flows to persist full systemPrompt in contextJson. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { BrowserWindow, ipcMain } from 'electron'
|
||||
import { IPC } from '../../../shared/ipc-channels'
|
||||
import type { AutoWritingConfig } from '../../../shared/types'
|
||||
import type { AiContextBinding, AutoWritingConfig } from '../../../shared/types'
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { AiClientService } from '../../services/ai-client.service'
|
||||
import { buildFlowContextPayload, readFlowSystemPrompt } from '../../services/flow-context.util'
|
||||
import { checkInteractiveGate } from '../../services/interactive-gate.service'
|
||||
import { AutoWritingService } from '../../services/auto-writing.service'
|
||||
import { InteractiveRepository } from '../../db/repositories/interactive.repo'
|
||||
@@ -26,12 +27,7 @@ function readContextText(registry: BookRegistryService, bookId: string, flowId:
|
||||
.getDb(bookId)
|
||||
.prepare('SELECT context_json FROM interactive_flows WHERE id = ?')
|
||||
.get(flowId) as { context_json: string } | undefined
|
||||
try {
|
||||
const parsed = JSON.parse(row?.context_json ?? '{}') as { contextSummary?: string }
|
||||
return parsed.contextSummary ?? '(无上下文摘要)'
|
||||
} catch {
|
||||
return '(无上下文摘要)'
|
||||
}
|
||||
return readFlowSystemPrompt(row?.context_json ?? '{}')
|
||||
}
|
||||
|
||||
export function registerAutoHandlers(
|
||||
@@ -76,6 +72,24 @@ export function registerAutoHandlers(
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.AUTO_CONFIRM_CONTEXT,
|
||||
(
|
||||
_e,
|
||||
{ bookId, flowId, binding }: { bookId: string; flowId: string; binding: AiContextBinding }
|
||||
) =>
|
||||
wrap(() => {
|
||||
const svc = serviceFor(registry, bookId, aiClient)
|
||||
const payload = buildFlowContextPayload(
|
||||
binding,
|
||||
registry,
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
return svc.enrichFlow(svc.confirmContext(flowId, payload))
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.AUTO_PLAN_SCENES,
|
||||
(_e, { bookId, flowId, contextSummary }: { bookId: string; flowId: string; contextSummary?: string }) =>
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { AiContextBinding, PlotSelection } from '../../../shared/types'
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { AiClientService } from '../../services/ai-client.service'
|
||||
import { aiContextBuilder } from '../../services/ai-context-builder.service'
|
||||
import { buildFlowContextPayload, readFlowSystemPrompt } from '../../services/flow-context.util'
|
||||
import { checkInteractiveGate } from '../../services/interactive-gate.service'
|
||||
import { InteractiveWritingService } from '../../services/interactive-writing.service'
|
||||
import { wrap } from '../result'
|
||||
@@ -56,13 +56,13 @@ export function registerInteractiveHandlers(
|
||||
}: { bookId: string; flowId: string; binding: AiContextBinding }
|
||||
) =>
|
||||
wrap(() => {
|
||||
const built = aiContextBuilder.build(binding, registry, bookId, settings.get().penName)
|
||||
const summary = built.preview.map((p) => p.title).join('、') || '(空)'
|
||||
const flow = serviceFor(registry, bookId, aiClient).confirmContext(
|
||||
flowId,
|
||||
const payload = buildFlowContextPayload(
|
||||
binding,
|
||||
summary
|
||||
registry,
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
const flow = serviceFor(registry, bookId, aiClient).confirmContext(flowId, payload)
|
||||
return serviceFor(registry, bookId, aiClient).enrichFlow(flow)
|
||||
})
|
||||
)
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import { IPC } from '../../../shared/ipc-channels'
|
||||
import type { CreateKnowledgeInput, KnowledgeStatus, KnowledgeType } from '../../../shared/types'
|
||||
import type { CreateKnowledgeInput, KnowledgeStatus, KnowledgeType, KnowledgeSuggestOptions } from '../../../shared/types'
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { KnowledgeRetrievalService } from '../../services/knowledge-retrieval.service'
|
||||
import { KnowledgeService } from '../../services/knowledge.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
export function registerKnowledgeHandlers(registry: BookRegistryService): void {
|
||||
export function registerKnowledgeHandlers(
|
||||
registry: BookRegistryService,
|
||||
settings: GlobalSettingsService
|
||||
): void {
|
||||
ipcMain.handle(
|
||||
IPC.KNOWLEDGE_LIST,
|
||||
(
|
||||
@@ -65,4 +70,16 @@ export function registerKnowledgeHandlers(registry: BookRegistryService): void {
|
||||
ipcMain.handle(IPC.KNOWLEDGE_STATS, (_e, { bookId }: { bookId: string }) =>
|
||||
wrap(() => new KnowledgeService(registry.getDb(bookId)).getForeshadowStats())
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.KNOWLEDGE_SUGGEST_CONTEXT,
|
||||
(_e, { bookId, opts }: { bookId: string; opts?: KnowledgeSuggestOptions }) =>
|
||||
wrap(() => {
|
||||
const topN = opts?.topN ?? settings.get().knowledgeSuggestTopN ?? 8
|
||||
return new KnowledgeRetrievalService(registry.getDb(bookId)).suggest({
|
||||
...opts,
|
||||
topN
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { AiContextBinding, AutoRhythm, AutoWritingConfig, WizardWritingConf
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { GlobalSettingsService } from '../../services/global-settings'
|
||||
import { AiClientService } from '../../services/ai-client.service'
|
||||
import { aiContextBuilder } from '../../services/ai-context-builder.service'
|
||||
import { buildFlowContextPayload, readFlowSystemPrompt } from '../../services/flow-context.util'
|
||||
import { WizardWritingService } from '../../services/wizard-writing.service'
|
||||
import { InteractiveRepository } from '../../db/repositories/interactive.repo'
|
||||
import { wrap } from '../result'
|
||||
@@ -20,12 +20,7 @@ function readContextText(registry: BookRegistryService, bookId: string, flowId:
|
||||
.getDb(bookId)
|
||||
.prepare('SELECT context_json FROM interactive_flows WHERE id = ?')
|
||||
.get(flowId) as { context_json: string } | undefined
|
||||
try {
|
||||
const parsed = JSON.parse(row?.context_json ?? '{}') as { contextSummary?: string }
|
||||
return parsed.contextSummary ?? '(无上下文摘要)'
|
||||
} catch {
|
||||
return '(无上下文摘要)'
|
||||
}
|
||||
return readFlowSystemPrompt(row?.context_json ?? '{}')
|
||||
}
|
||||
|
||||
export function registerWizardHandlers(
|
||||
@@ -98,10 +93,14 @@ export function registerWizardHandlers(
|
||||
{ bookId, flowId, binding }: { bookId: string; flowId: string; binding: AiContextBinding }
|
||||
) =>
|
||||
wrap(() => {
|
||||
const built = aiContextBuilder.build(binding, registry, bookId, settings.get().penName)
|
||||
const summary = built.preview.map((p) => p.title).join('、') || '(空)'
|
||||
const payload = buildFlowContextPayload(
|
||||
binding,
|
||||
registry,
|
||||
bookId,
|
||||
settings.get().penName
|
||||
)
|
||||
const svc = serviceFor(registry, bookId, aiClient)
|
||||
return svc.enrichFlow(svc.confirmContext(flowId, binding, summary))
|
||||
return svc.enrichFlow(svc.confirmContext(flowId, payload))
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ export function registerIpc(): { settings: GlobalSettingsService; books: BookReg
|
||||
registerInteractiveHandlers(books, settings, aiClient)
|
||||
registerAutoHandlers(books, settings, aiClient)
|
||||
registerWizardHandlers(books, settings, aiClient)
|
||||
registerKnowledgeHandlers(books)
|
||||
registerKnowledgeHandlers(books, settings)
|
||||
registerCockpitHandlers(books, settings)
|
||||
registerBridgeHandlers(books, aiClient)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user