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:
@@ -7,6 +7,7 @@ import { migrate } from '../../src/main/db/migrate'
|
||||
import { ChapterRepository } from '../../src/main/db/repositories/chapter.repo'
|
||||
import { VolumeRepository } from '../../src/main/db/repositories/volume.repo'
|
||||
import { SettingRepository } from '../../src/main/db/repositories/setting.repo'
|
||||
import { KnowledgeRepository } from '../../src/main/db/repositories/knowledge.repo'
|
||||
import { BookRegistryService } from '../../src/main/services/book-registry'
|
||||
import { aiContextBuilder } from '../../src/main/services/ai-context-builder.service'
|
||||
import type { SqliteDb } from '../../src/main/db/types'
|
||||
@@ -38,7 +39,7 @@ describe('AiContextBuilderService', () => {
|
||||
const chapter = chapters.create(volId, '长章节', 0, longHtml)
|
||||
|
||||
const result = aiContextBuilder.build(
|
||||
{ chapterIds: [chapter.id], outlineIds: [], settingIds: [], inspirationIds: [] },
|
||||
{ chapterIds: [chapter.id], outlineIds: [], settingIds: [], inspirationIds: [], knowledgeIds: [] },
|
||||
registry,
|
||||
bookId,
|
||||
'作者'
|
||||
@@ -58,7 +59,7 @@ describe('AiContextBuilderService', () => {
|
||||
}
|
||||
|
||||
const result = aiContextBuilder.build(
|
||||
{ chapterIds: ids, outlineIds: [], settingIds: [], inspirationIds: [] },
|
||||
{ chapterIds: ids, outlineIds: [], settingIds: [], inspirationIds: [], knowledgeIds: [] },
|
||||
registry,
|
||||
bookId,
|
||||
'作者'
|
||||
@@ -74,7 +75,7 @@ describe('AiContextBuilderService', () => {
|
||||
const setting = settings.create('character', '主角林远', '少年修士')
|
||||
|
||||
const result = aiContextBuilder.build(
|
||||
{ chapterIds: [], outlineIds: [], settingIds: [setting.id], inspirationIds: [] },
|
||||
{ chapterIds: [], outlineIds: [], settingIds: [setting.id], inspirationIds: [], knowledgeIds: [] },
|
||||
registry,
|
||||
bookId,
|
||||
'作者'
|
||||
@@ -83,4 +84,60 @@ describe('AiContextBuilderService', () => {
|
||||
expect(result.preview[0].title).toBe('主角林远')
|
||||
expect(result.systemPrompt).toContain('主角林远')
|
||||
})
|
||||
|
||||
it('UT-CTX-02: build includes knowledge preview items', () => {
|
||||
const know = new KnowledgeRepository(db)
|
||||
const entry = know.create({
|
||||
type: 'foreshadow',
|
||||
title: '测灵石',
|
||||
content: '石头发热',
|
||||
status: 'approved'
|
||||
})
|
||||
const result = aiContextBuilder.build(
|
||||
{
|
||||
chapterIds: [],
|
||||
outlineIds: [],
|
||||
settingIds: [],
|
||||
inspirationIds: [],
|
||||
knowledgeIds: [entry.id]
|
||||
},
|
||||
registry,
|
||||
bookId,
|
||||
'作者'
|
||||
)
|
||||
expect(result.preview.some((p) => p.kind === 'knowledge')).toBe(true)
|
||||
expect(result.systemPrompt).toContain('【知识·伏笔】')
|
||||
expect(result.systemPrompt).toContain('测灵石')
|
||||
})
|
||||
|
||||
it('UT-CTX-03: caps knowledge section at 4000 chars', () => {
|
||||
const know = new KnowledgeRepository(db)
|
||||
const ids: string[] = []
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const e = know.create({
|
||||
type: 'fact',
|
||||
title: `条目${i}`,
|
||||
content: '长'.repeat(400),
|
||||
importance: 5,
|
||||
status: 'approved'
|
||||
})
|
||||
ids.push(e.id)
|
||||
}
|
||||
const result = aiContextBuilder.build(
|
||||
{
|
||||
chapterIds: [],
|
||||
outlineIds: [],
|
||||
settingIds: [],
|
||||
inspirationIds: [],
|
||||
knowledgeIds: ids
|
||||
},
|
||||
registry,
|
||||
bookId,
|
||||
'作者'
|
||||
)
|
||||
const knowledgeChars = result.preview
|
||||
.filter((p) => p.kind === 'knowledge')
|
||||
.reduce((s, p) => s + p.charCount, 0)
|
||||
expect(knowledgeChars).toBeLessThanOrEqual(4000)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user