|
|
@@ -0,0 +1,175 @@
|
|
|
+import type { BookConfig } from "../models/book.js";
|
|
|
+import type { GenreProfile } from "../models/genre-profile.js";
|
|
|
+import type { BookRules } from "../models/book-rules.js";
|
|
|
+
|
|
|
+export function buildSettlerSystemPrompt(
|
|
|
+ book: BookConfig,
|
|
|
+ genreProfile: GenreProfile,
|
|
|
+ bookRules: BookRules | null,
|
|
|
+): string {
|
|
|
+ const numericalBlock = genreProfile.numericalSystem
|
|
|
+ ? `\n- 本题材有数值/资源体系,你必须在 UPDATED_LEDGER 中追踪正文中出现的所有资源变动
|
|
|
+- 数值验算铁律:期初 + 增量 = 期末,三项必须可验算`
|
|
|
+ : `\n- 本题材无数值系统,UPDATED_LEDGER 留空`;
|
|
|
+
|
|
|
+ const hookRules = `
|
|
|
+## 伏笔追踪规则
|
|
|
+
|
|
|
+- 新伏笔:正文中出现的暗示、悬念、未解之谜 → 新增 hook_id,标注起始章、类型、状态=待定
|
|
|
+- 推进伏笔:已有伏笔在本章有新进展 → 更新"最近推进"列和状态
|
|
|
+- 回收伏笔:伏笔在本章明确揭示/解决 → 状态改为"已回收"
|
|
|
+- 延后伏笔:超过5章未推进 → 标注"延后",备注原因`;
|
|
|
+
|
|
|
+ const fullCastBlock = bookRules?.enableFullCastTracking
|
|
|
+ ? `\n## 全员追踪\nPOST_SETTLEMENT 必须额外包含:本章出场角色清单、角色间关系变动、未出场但被提及的角色。`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ return `你是状态追踪分析师。给定新章节正文和当前 truth 文件,你的任务是产出更新后的 truth 文件。
|
|
|
+
|
|
|
+## 工作模式
|
|
|
+
|
|
|
+你不是在写作。你的任务是:
|
|
|
+1. 仔细阅读正文,提取所有状态变化
|
|
|
+2. 基于"当前追踪文件"做增量更新
|
|
|
+3. 严格按照 === TAG === 格式输出
|
|
|
+
|
|
|
+## 分析维度
|
|
|
+
|
|
|
+从正文中提取以下信息:
|
|
|
+- 角色出场、退场、状态变化(受伤/突破/死亡等)
|
|
|
+- 位置移动、场景转换
|
|
|
+- 物品/资源的获得与消耗
|
|
|
+- 伏笔的埋设、推进、回收
|
|
|
+- 情感弧线变化
|
|
|
+- 支线进展
|
|
|
+- 角色间关系变化、新的信息边界
|
|
|
+
|
|
|
+## 书籍信息
|
|
|
+
|
|
|
+- 标题:${book.title}
|
|
|
+- 题材:${genreProfile.name}(${book.genre})
|
|
|
+- 平台:${book.platform}
|
|
|
+${numericalBlock}
|
|
|
+${hookRules}${fullCastBlock}
|
|
|
+
|
|
|
+## 输出格式(必须严格遵循)
|
|
|
+
|
|
|
+${buildSettlerOutputFormat(genreProfile)}
|
|
|
+
|
|
|
+## 关键规则
|
|
|
+
|
|
|
+1. 状态卡和伏笔池必须基于"当前追踪文件"做增量更新,不是从零开始
|
|
|
+2. 正文中的每一个事实性变化都必须反映在对应的追踪文件中
|
|
|
+3. 不要遗漏细节:数值变化、位置变化、关系变化、信息变化都要记录
|
|
|
+4. 角色交互矩阵中的"信息边界"要准确——角色只知道他在场时发生的事`;
|
|
|
+}
|
|
|
+
|
|
|
+function buildSettlerOutputFormat(gp: GenreProfile): string {
|
|
|
+ const postSettlement = gp.numericalSystem
|
|
|
+ ? `=== POST_SETTLEMENT ===
|
|
|
+(如有数值变动,必须输出Markdown表格)
|
|
|
+| 结算项 | 本章记录 | 备注 |
|
|
|
+|--------|----------|------|
|
|
|
+| 资源账本 | 期初X / 增量+Y / 期末Z | 无增量写+0 |
|
|
|
+| 重要资源 | 资源名 -> 贡献+Y(依据) | 无写"无" |
|
|
|
+| 伏笔变动 | 新增/回收/延后 Hook | 同步更新伏笔池 |`
|
|
|
+ : `=== POST_SETTLEMENT ===
|
|
|
+(如有伏笔变动,必须输出)
|
|
|
+| 结算项 | 本章记录 | 备注 |
|
|
|
+|--------|----------|------|
|
|
|
+| 伏笔变动 | 新增/回收/延后 Hook | 同步更新伏笔池 |`;
|
|
|
+
|
|
|
+ const updatedLedger = gp.numericalSystem
|
|
|
+ ? `\n=== UPDATED_LEDGER ===\n(更新后的完整资源账本,Markdown表格格式)`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ return `${postSettlement}
|
|
|
+
|
|
|
+=== UPDATED_STATE ===
|
|
|
+(更新后的完整状态卡,Markdown表格格式)
|
|
|
+${updatedLedger}
|
|
|
+=== UPDATED_HOOKS ===
|
|
|
+(更新后的完整伏笔池,Markdown表格格式)
|
|
|
+
|
|
|
+=== CHAPTER_SUMMARY ===
|
|
|
+(本章摘要,Markdown表格格式,必须包含以下列)
|
|
|
+| 章节 | 标题 | 出场人物 | 关键事件 | 状态变化 | 伏笔动态 | 情绪基调 | 章节类型 |
|
|
|
+|------|------|----------|----------|----------|----------|----------|----------|
|
|
|
+| N | 本章标题 | 角色1,角色2 | 一句话概括 | 关键变化 | H01埋设/H02推进 | 情绪走向 | ${gp.chapterTypes.length > 0 ? gp.chapterTypes.join("/") : "过渡/冲突/高潮/收束"} |
|
|
|
+
|
|
|
+=== UPDATED_SUBPLOTS ===
|
|
|
+(更新后的完整支线进度板,Markdown表格格式)
|
|
|
+| 支线ID | 支线名 | 相关角色 | 起始章 | 最近活跃章 | 距今章数 | 状态 | 进度概述 | 回收ETA |
|
|
|
+|--------|--------|----------|--------|------------|----------|------|----------|---------|
|
|
|
+
|
|
|
+=== UPDATED_EMOTIONAL_ARCS ===
|
|
|
+(更新后的完整情感弧线,Markdown表格格式)
|
|
|
+| 角色 | 章节 | 情绪状态 | 触发事件 | 强度(1-10) | 弧线方向 |
|
|
|
+|------|------|----------|----------|------------|----------|
|
|
|
+
|
|
|
+=== UPDATED_CHARACTER_MATRIX ===
|
|
|
+(更新后的角色交互矩阵,分三个子表)
|
|
|
+
|
|
|
+### 角色档案
|
|
|
+| 角色 | 核心标签 | 反差细节 | 说话风格 | 性格底色 | 与主角关系 | 核心动机 | 当前目标 |
|
|
|
+|------|----------|----------|----------|----------|------------|----------|----------|
|
|
|
+
|
|
|
+### 相遇记录
|
|
|
+| 角色A | 角色B | 首次相遇章 | 最近交互章 | 关系性质 | 关系变化 |
|
|
|
+|-------|-------|------------|------------|----------|----------|
|
|
|
+
|
|
|
+### 信息边界
|
|
|
+| 角色 | 已知信息 | 未知信息 | 信息来源章 |
|
|
|
+|------|----------|----------|------------|`;
|
|
|
+}
|
|
|
+
|
|
|
+export function buildSettlerUserPrompt(params: {
|
|
|
+ readonly chapterNumber: number;
|
|
|
+ readonly title: string;
|
|
|
+ readonly content: string;
|
|
|
+ readonly currentState: string;
|
|
|
+ readonly ledger: string;
|
|
|
+ readonly hooks: string;
|
|
|
+ readonly chapterSummaries: string;
|
|
|
+ readonly subplotBoard: string;
|
|
|
+ readonly emotionalArcs: string;
|
|
|
+ readonly characterMatrix: string;
|
|
|
+ readonly volumeOutline: string;
|
|
|
+}): string {
|
|
|
+ const ledgerBlock = params.ledger
|
|
|
+ ? `\n## 当前资源账本\n${params.ledger}\n`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ const summariesBlock = params.chapterSummaries !== "(文件尚未创建)"
|
|
|
+ ? `\n## 已有章节摘要\n${params.chapterSummaries}\n`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ const subplotBlock = params.subplotBoard !== "(文件尚未创建)"
|
|
|
+ ? `\n## 当前支线进度板\n${params.subplotBoard}\n`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ const emotionalBlock = params.emotionalArcs !== "(文件尚未创建)"
|
|
|
+ ? `\n## 当前情感弧线\n${params.emotionalArcs}\n`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ const matrixBlock = params.characterMatrix !== "(文件尚未创建)"
|
|
|
+ ? `\n## 当前角色交互矩阵\n${params.characterMatrix}\n`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ return `请分析第${params.chapterNumber}章「${params.title}」的正文,更新所有追踪文件。
|
|
|
+
|
|
|
+## 本章正文
|
|
|
+
|
|
|
+${params.content}
|
|
|
+
|
|
|
+## 当前状态卡
|
|
|
+${params.currentState}
|
|
|
+${ledgerBlock}
|
|
|
+## 当前伏笔池
|
|
|
+${params.hooks}
|
|
|
+${summariesBlock}${subplotBlock}${emotionalBlock}${matrixBlock}
|
|
|
+## 卷纲
|
|
|
+${params.volumeOutline}
|
|
|
+
|
|
|
+请严格按照 === TAG === 格式输出结算结果。`;
|
|
|
+}
|