import type { ExtractedKnowledgeItem } from '../../shared/types' export function buildExtractionPrompt( chapterTitle: string, plainText: string, approvedTitles: Array<{ id: string; title: string }> ): string { const catalog = approvedTitles.length > 0 ? approvedTitles.map((e) => `- ${e.id}: ${e.title}`).join('\n') : '(无)' return `你是小说知识库助手。请从以下章节正文中抽取知识条目,输出 JSON 数组。 章节标题:${chapterTitle} 已有 approved 知识(id: 标题): ${catalog} 若某条抽取内容是对已有知识的更新,请设置 suggestedMergeId 为对应 id,并在 proposedPatch 中给出建议更新的字段。 每条必须包含:type(character|foreshadow|relationship|location|fact)、title、content、importance(1-5)、confidence(0-1)、foreshadowStatus(仅 foreshadow 类型:buried|partial|resolved)。 正文: ${plainText} 仅返回 JSON 数组,不要 markdown。` } export function parseExtractionJson(raw: string): ExtractedKnowledgeItem[] { const cleaned = raw.replace(/```json\n?|\n?```/g, '').trim() const arr = JSON.parse(cleaned) as ExtractedKnowledgeItem[] if (!Array.isArray(arr)) throw new Error('expected array') return arr .map((item) => ({ type: item.type, title: String(item.title).trim(), content: String(item.content ?? '').trim(), importance: item.importance ?? 3, confidence: Number(item.confidence) || 0.5, foreshadowStatus: item.foreshadowStatus, suggestedMergeId: item.suggestedMergeId ?? undefined, proposedPatch: item.proposedPatch })) .filter((x) => x.title.length > 0) }