aa2c7dfed3
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>
89 lines
3.6 KiB
TypeScript
89 lines
3.6 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { DatabaseSync } from 'node:sqlite'
|
|
import { migrate } from '../../src/main/db/migrate'
|
|
import { AiSessionRepository } from '../../src/main/db/repositories/ai-session.repo'
|
|
import { KnowledgeRepository } from '../../src/main/db/repositories/knowledge.repo'
|
|
import { KnowledgeRetrievalService } from '../../src/main/services/knowledge-retrieval.service'
|
|
import { InteractiveWritingService } from '../../src/main/services/interactive-writing.service'
|
|
import { AiClientService } from '../../src/main/services/ai-client.service'
|
|
import { BookRegistryService } from '../../src/main/services/book-registry'
|
|
import { aiContextBuilder } from '../../src/main/services/ai-context-builder.service'
|
|
import { DEFAULT_AI_CONFIG, type AiContextBinding } from '../../src/shared/types'
|
|
import { mkdtempSync, rmSync } from 'fs'
|
|
import { join } from 'path'
|
|
import { tmpdir } from 'os'
|
|
|
|
const AI_TEST_CONFIG = { ...DEFAULT_AI_CONFIG, timeoutMs: 240_000, maxTokens: 4096 }
|
|
|
|
const EMPTY_BINDING: AiContextBinding = {
|
|
chapterIds: [],
|
|
outlineIds: [],
|
|
settingIds: [],
|
|
inspirationIds: [],
|
|
knowledgeIds: []
|
|
}
|
|
|
|
describe('AI context integration', () => {
|
|
it('IT-CTX-01: suggestContext returns entries when approved exist', () => {
|
|
const db = new DatabaseSync(':memory:')
|
|
migrate(db)
|
|
new KnowledgeRepository(db).create({
|
|
type: 'fact',
|
|
title: '测灵石异常',
|
|
content: '石头发热',
|
|
status: 'approved',
|
|
importance: 4
|
|
})
|
|
const result = new KnowledgeRetrievalService(db).suggest({ topN: 5 })
|
|
expect(result.length).toBeGreaterThanOrEqual(1)
|
|
expect(result[0].entry.title).toBe('测灵石异常')
|
|
db.close()
|
|
})
|
|
|
|
it('IT-CTX-02: build with knowledgeIds includes knowledge block in systemPrompt', () => {
|
|
const userDir = mkdtempSync(join(tmpdir(), 'bilin-ctx-it-'))
|
|
const registry = new BookRegistryService(userDir)
|
|
const meta = registry.create({ name: '测试书', category: '玄幻' })
|
|
const bookDb = registry.getDb(meta.id)
|
|
const entry = new KnowledgeRepository(bookDb).create({
|
|
type: 'foreshadow',
|
|
title: '测灵石',
|
|
content: '石头发热',
|
|
status: 'approved'
|
|
})
|
|
const result = aiContextBuilder.build(
|
|
{ ...EMPTY_BINDING, knowledgeIds: [entry.id] },
|
|
registry,
|
|
meta.id,
|
|
'作者'
|
|
)
|
|
expect(result.preview.some((p) => p.kind === 'knowledge')).toBe(true)
|
|
expect(result.systemPrompt).toContain('【知识·')
|
|
bookDb.close()
|
|
rmSync(userDir, { recursive: true, force: true })
|
|
})
|
|
|
|
it('IT-CTX-03: interactive confirm then suggestPlots uses knowledge context', async () => {
|
|
const db = new DatabaseSync(':memory:')
|
|
migrate(db)
|
|
const session = new AiSessionRepository(db).create('t', AI_TEST_CONFIG.model)
|
|
const know = new KnowledgeRepository(db).create({
|
|
type: 'foreshadow',
|
|
title: '测灵石异常',
|
|
content: '入门考核时测灵石发热,暗示主角特殊灵根',
|
|
status: 'approved',
|
|
importance: 5
|
|
})
|
|
const service = new InteractiveWritingService(db, new AiClientService(() => AI_TEST_CONFIG))
|
|
const flow = service.start(session.id)
|
|
service.confirmContext(flow.id, {
|
|
binding: { ...EMPTY_BINDING, knowledgeIds: [know.id] },
|
|
systemPrompt: `【知识·伏笔·测灵石异常】入门考核时测灵石发热,暗示主角特殊灵根\n\n林远参加宗门入门考核,演武场测灵石前众人围观。`,
|
|
contextSummary: '0章·0纲·0设·0感·1知'
|
|
})
|
|
const plots = await service.suggestPlots(flow.id)
|
|
expect(plots).toHaveLength(3)
|
|
db.close()
|
|
}, 240_000)
|
|
})
|