@whispering233/ai-editor-server 0.0.52 → 0.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/client-dist/assets/{index-Dim9IXQC.css → index-DBshOA8W.css} +1 -1
  2. package/client-dist/assets/index-DnBMudDZ.js +624 -0
  3. package/client-dist/index.html +2 -2
  4. package/dist/decompose/batching.d.ts +20 -0
  5. package/dist/decompose/batching.d.ts.map +1 -0
  6. package/dist/decompose/batching.js +29 -0
  7. package/dist/decompose/batching.js.map +1 -0
  8. package/dist/decompose/extract.d.ts +44 -0
  9. package/dist/decompose/extract.d.ts.map +1 -0
  10. package/dist/decompose/extract.js +246 -0
  11. package/dist/decompose/extract.js.map +1 -0
  12. package/dist/decompose/job.d.ts +91 -0
  13. package/dist/decompose/job.d.ts.map +1 -0
  14. package/dist/decompose/job.js +289 -0
  15. package/dist/decompose/job.js.map +1 -0
  16. package/dist/decompose/llm.d.ts +68 -0
  17. package/dist/decompose/llm.d.ts.map +1 -0
  18. package/dist/decompose/llm.js +180 -0
  19. package/dist/decompose/llm.js.map +1 -0
  20. package/dist/decompose/merge-write.d.ts +75 -0
  21. package/dist/decompose/merge-write.d.ts.map +1 -0
  22. package/dist/decompose/merge-write.js +670 -0
  23. package/dist/decompose/merge-write.js.map +1 -0
  24. package/dist/decompose/merge.d.ts +156 -0
  25. package/dist/decompose/merge.d.ts.map +1 -0
  26. package/dist/decompose/merge.js +266 -0
  27. package/dist/decompose/merge.js.map +1 -0
  28. package/dist/decompose/report.d.ts +57 -0
  29. package/dist/decompose/report.d.ts.map +1 -0
  30. package/dist/decompose/report.js +127 -0
  31. package/dist/decompose/report.js.map +1 -0
  32. package/dist/decompose/runner.d.ts +143 -0
  33. package/dist/decompose/runner.d.ts.map +1 -0
  34. package/dist/decompose/runner.js +520 -0
  35. package/dist/decompose/runner.js.map +1 -0
  36. package/dist/decompose/split.d.ts +89 -0
  37. package/dist/decompose/split.d.ts.map +1 -0
  38. package/dist/decompose/split.js +556 -0
  39. package/dist/decompose/split.js.map +1 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +4 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/middleware/error.d.ts +1 -1
  44. package/dist/middleware/error.d.ts.map +1 -1
  45. package/dist/middleware/error.js +9 -0
  46. package/dist/middleware/error.js.map +1 -1
  47. package/dist/middleware/project.d.ts.map +1 -1
  48. package/dist/middleware/project.js +14 -0
  49. package/dist/middleware/project.js.map +1 -1
  50. package/dist/routes/chat.d.ts.map +1 -1
  51. package/dist/routes/chat.js +28 -3
  52. package/dist/routes/chat.js.map +1 -1
  53. package/dist/routes/decompose.d.ts +26 -0
  54. package/dist/routes/decompose.d.ts.map +1 -0
  55. package/dist/routes/decompose.js +453 -0
  56. package/dist/routes/decompose.js.map +1 -0
  57. package/dist/routes/project.d.ts +2 -0
  58. package/dist/routes/project.d.ts.map +1 -1
  59. package/dist/routes/project.js +4 -0
  60. package/dist/routes/project.js.map +1 -1
  61. package/package.json +5 -5
  62. package/client-dist/assets/index-JrTZv8BF.js +0 -621
@@ -0,0 +1,520 @@
1
+ // 拆解 S2 批执行器(卡 21.6):串行批循环 + 项目数据快照 + 逐章对齐重试 + 取消通道(暂停 / 切书 / 重启归一)
2
+ // + job 收口(卡 21.7:批全部收口后跑 S3 归并与 S4 报告,随后 job 置 `done`)与单批重跑入口。
3
+ //
4
+ // 契约:docs/design/60-decompose.md §2(S3/S4 在全部批完成后各跑一次)、§4(批调度:组批 / 重试 / 串行 /
5
+ // 项目数据快照)、§4.1(两层快照:起始快照 + 本轮累积、预算与丢弃顺序、knownNames 全集)、
6
+ // §5(抽取 schema 口径)、§7(状态机、续拆、单批重跑);docs/api/120-api-decompose.md
7
+ // §pause / §resume / §rerun;状态不变式见 docs/db/schema.md「decompose 两表」(状态归一**只归一 job 行**)。本模块的四条口径:
8
+ // - **续跑取「第一个未完成批」**:`done` 之外的批(`pending` / `running` / `failed`)都算未完成——
9
+ // 服务端重启残留的 `running` 批由这里承接,不单独归一;
10
+ // - **单批重跑只重跑该批**(§7):重新抽取该批 → S3 重算(`merge_written` 三路比对保幂等)→ S4 重建报告;
11
+ // - **S2 不写业务表**:批结果只落 `decompose_batches.result`(实体 / 关系 / 大纲 / 正文只由 S3/S4 写);
12
+ // - **批跑完时 job 留在 `running`**,全部批收口后才由 S3+S4 推到 `done`(job.ts 的 `deriveStage` 据
13
+ // 「批是否全部收口」推出 `merge` / `report`)。
14
+ //
15
+ // 调用路径:`start`(首次)/ `continue`(续拆)/ `resume`(续跑)/ 单批 `rerun` 各起一轮(路由**不 await**:长任务是后台跑);
16
+ // 建会话前先按 `DECOMPOSE_KEPT_SESSIONS` 清理超限的更早拆解会话(§7.2,告知不静默)。
17
+ // 暂停 / 切书 = 置 abort:**当前批跑完即停**,已发出的模型调用不 abort(结果不浪费,批级幂等靠 `done` 跳过)。
18
+ // 模型调用只经 pi 的 `ModelRuntime`(`getModelRuntime()` / `getSettingsManager()` 唯一入口)——
19
+ // 业务代码不自建 fetch / HTTP agent(出站行为统一由启动时装的全局 undici dispatcher 承担)。
20
+ // 阈值与提示词里的数字一律取自常量(提示词按常量插值生成,散文不复述数字)。
21
+ import { unlinkSync } from "node:fs";
22
+ import { findProjectSession } from "@whispering233/ai-editor-agent";
23
+ import { completeBatch, deriveChapterOrder, failBatch, findOutlineNode, getDecomposeJob, getDocumentTexts, listDecomposeBatches, listDecomposeJobs, listRelations, nowIso, readOutlineFile, setJobError, startBatchAttempt, updateJobStatus, } from "@whispering233/ai-editor-db";
24
+ import { DECOMPOSE_CHAPTER_MAX_CHARACTERS, DECOMPOSE_CHAPTER_MAX_LOCATIONS, DECOMPOSE_CHAPTER_MAX_RELATIONS, DECOMPOSE_CHAPTER_MAX_SETTINGS, DECOMPOSE_CHAPTER_SUMMARY_MAX_CHARS, DECOMPOSE_DESCRIPTION_MAX_CHARS, DECOMPOSE_MOTIVATION_MAX_CHARS, DECOMPOSE_PERSONALITY_MAX_ITEMS, DECOMPOSE_RELATION_TYPES, normalizeExtraction, } from "./extract.js";
25
+ import { doneBatchResults } from "./job.js";
26
+ import { decomposeSessionId, openDecomposeSession, parseModelJson, } from "./llm.js";
27
+ import { normalizeEntityName } from "./merge.js";
28
+ import { listAllLiveEntities, runDecomposeMerge } from "./merge-write.js";
29
+ /** 批并发度:串行是既定口径(§4——不在 pi 的重试链里,429 / 限流要自己兜,后台任务慢比失败好)。
30
+ * 单点可调:改成 N 即按 N 批一组并发跑;同组共用一份项目数据快照(组内后批看不到同组前批的产出)。 */
31
+ export const DECOMPOSE_CONCURRENCY = 1;
32
+ /** 单批尝试上限(含首次):缺章 → 整批重试;超上限标 `failed` 并继续后续批(不阻塞整个 job) */
33
+ export const DECOMPOSE_BATCH_MAX_ATTEMPTS = 3;
34
+ /** 起始快照回溯的章数(§4.1:只取紧邻范围起点的连续若干章——续拆 / 有范围时的前置连续性) */
35
+ export const DECOMPOSE_SNAPSHOT_PREV_CHAPTERS = 3;
36
+ /** 项目数据快照长度上限(§4.1:起始快照 + 本轮累积的总预算)——`routes/decompose.ts` 的每批固定开销
37
+ * 预估由它派生(改这里预估跟着变) */
38
+ export const DECOMPOSE_SNAPSHOT_MAX_CHARS = 2000;
39
+ /** 人物 `role` 的展示权重(§4.1:主角 → … → 龙套,词表外的 role 归末位)——同时是批提示词的建议词表 */
40
+ export const DECOMPOSE_ROLE_ORDER = ["主角", "主要配角", "配角", "反派", "龙套"];
41
+ /** 拆解会话保留上限(§7.2):按 job `created_at` 保留最近这么多枚,超出的在新一轮拆解创建会话之前清掉 */
42
+ export const DECOMPOSE_KEPT_SESSIONS = 5;
43
+ export function emptyStoryBible() {
44
+ return { names: [], relations: [], summaries: [] };
45
+ }
46
+ /**
47
+ * 归并一批抽取结果进本轮累积(纯函数,返回新对象):名字与关系累计去重,摘要整批替换。
48
+ * 名字集合同时是 `normalizeExtraction` 的 `knownNames`——跨批关系端点靠它才不被当成幻觉丢弃。
49
+ */
50
+ export function extendStoryBible(bible, result) {
51
+ const seenNames = new Set(bible.names.map(normalizeEntityName));
52
+ const names = [...bible.names];
53
+ for (const chapter of result.chapters) {
54
+ for (const entity of [...chapter.characters, ...chapter.settings, ...chapter.locations]) {
55
+ const key = normalizeEntityName(entity.name);
56
+ if (key === "" || seenNames.has(key))
57
+ continue;
58
+ seenNames.add(key);
59
+ names.push(entity.name);
60
+ }
61
+ }
62
+ const relations = [...bible.relations];
63
+ const seenRelations = new Set(relations);
64
+ for (const chapter of result.chapters) {
65
+ for (const relation of chapter.relations) {
66
+ const line = `${relation.source}→${relation.target}(${relation.type})`;
67
+ if (seenRelations.has(line))
68
+ continue;
69
+ seenRelations.add(line);
70
+ relations.push(line);
71
+ }
72
+ }
73
+ return { names, relations, summaries: result.chapters.map((chapter) => chapter.summary).filter((summary) => summary !== "") };
74
+ }
75
+ /**
76
+ * 起始快照读取(一轮一次,不随批刷新):实体 / 关系走 db 查询层(禁止绕过 `queryDb`),
77
+ * 前置章摘要走 `outline.json`(章序 = `deriveChapterOrder`,节点 `summary` = S3 回写的章摘要)。
78
+ */
79
+ export function readStartSnapshot(input) {
80
+ const { project, scopeStart, chapterOrder, tree } = input;
81
+ // 实体**分页取全**(`listAllLiveEntities`,与 S3 同名复用同一实现):实体列表每页上限
82
+ // `MAX_ENTITY_LIST_LIMIT`,早先按「单类型 ≤ 一页够用」这个刻度读首页——尺度失效点很明确:
83
+ // 一旦某类型实体超过一页,`snapshotKnownNames` 就不再是全集,超出的名字每轮被当成幻觉,
84
+ // 连带把引用它的关系整条丢掉(§4.1 / §9 不变式 13)。故该刻度被移除:取全,不按页猜。
85
+ // 关系无此问题:`listRelations` 不分页、单查询返回全部可见关系(不得为它另加 limit)。
86
+ const characters = listAllLiveEntities(project.db, "character")
87
+ .map((item) => ({ name: item.name, role: typeof item.summary.role === "string" ? item.summary.role : "" }))
88
+ .sort((a, b) => roleRank(a.role) - roleRank(b.role)); // 稳定排序:同权重保持查询顺序
89
+ const settings = listAllLiveEntities(project.db, "setting").map((item) => item.name);
90
+ const locations = listAllLiveEntities(project.db, "location").map((item) => item.name);
91
+ const relations = listRelations(project.db, {}, 1, project.root).relations.map((relation) => `${relation.sourceName ?? relation.sourceId}→${relation.targetName ?? relation.targetId}(${relation.relationType})`);
92
+ // 范围起点在章序里的位置:找不到(范围章被删 / 移出)⇒ 不猜前置章,留空
93
+ const scopeIndex = chapterOrder.findIndex((entry) => entry.chapterNumber === scopeStart);
94
+ const prevSummaries = (scopeIndex <= 0 ? [] : chapterOrder.slice(Math.max(0, scopeIndex - DECOMPOSE_SNAPSHOT_PREV_CHAPTERS), scopeIndex))
95
+ // 紧邻起点者在最前:预算不足时先丢最远的章(见 `snapshotBlocks`)
96
+ .reverse()
97
+ .flatMap((entry) => {
98
+ const summary = findOutlineNode(tree, entry.chapterId)?.summary?.trim();
99
+ return summary === undefined || summary === "" ? [] : [{ chapterNumber: entry.chapterNumber, summary }];
100
+ });
101
+ return { characters, settings, locations, relations, prevSummaries };
102
+ }
103
+ /** role 排序权重:词表内取下标,其余(含空串)排最后 */
104
+ function roleRank(role) {
105
+ const index = DECOMPOSE_ROLE_ORDER.indexOf(role.trim());
106
+ return index === -1 ? DECOMPOSE_ROLE_ORDER.length : index;
107
+ }
108
+ /**
109
+ * 快照里的全部名字(**校验用全集**:起始快照 + 本轮累积)——`normalizeExtraction` 的 `knownNames` 输入。
110
+ *
111
+ * **不变式(§4.1):这里必须是未裁剪的全集,预算只作用于提示词渲染。**
112
+ * 反向改(拿渲染后的文本当校验集合)会把「本批没重提、但库里 / 前几批已存在」的角色误判成幻觉,
113
+ * 连带把它的关系整条丢掉——名字数组与渲染文本是两套东西,不得合并。
114
+ */
115
+ export function snapshotKnownNames(start, bible) {
116
+ return [
117
+ ...start.characters.map((character) => character.name),
118
+ ...start.settings,
119
+ ...start.locations,
120
+ ...bible.names,
121
+ ];
122
+ }
123
+ /**
124
+ * 快照块(**定义顺序 = 填充优先级**:靠前先占预算、最后被丢)= §4.1 丢弃顺序的逆序
125
+ * (设定 / 地点名 → 关系 → 前置摘要 → 人物名,人物最后丢——它同时是关系端点的关键)。
126
+ * 两层合进同一批块:本轮累积的名字接在人物名之后(同在最后被丢的块)、上批摘要接在前置摘要之前
127
+ * (同在摘要块;预算紧时先丢离本轮最远的上下文)。
128
+ */
129
+ function snapshotBlocks(start, bible) {
130
+ const rendered = new Set([...start.characters.map((character) => character.name), ...start.settings, ...start.locations].map(normalizeEntityName));
131
+ return [
132
+ {
133
+ key: "names",
134
+ prefix: "名字:",
135
+ separator: "、",
136
+ dropLabel: "名字",
137
+ items: [
138
+ // 起始快照的人物带 role;本轮累积只知道名字(起始快照里已渲染过的去重:续拆时两边必然重叠)
139
+ ...start.characters.map((character) => character.role === "" ? character.name : `${character.name}(${character.role})`),
140
+ ...bible.names.filter((name) => !rendered.has(normalizeEntityName(name))),
141
+ ],
142
+ },
143
+ {
144
+ key: "summaries",
145
+ prefix: "",
146
+ separator: "\n",
147
+ dropLabel: "摘要",
148
+ items: [
149
+ ...bible.summaries.map((summary) => `上一批摘要:${summary}`),
150
+ ...start.prevSummaries.map((entry) => `第${entry.chapterNumber}章摘要:${entry.summary}`),
151
+ ],
152
+ },
153
+ {
154
+ key: "relations",
155
+ prefix: "已有关系:",
156
+ separator: "、",
157
+ dropLabel: "关系",
158
+ items: [...new Set([...start.relations, ...bible.relations])],
159
+ },
160
+ { key: "places", prefix: "设定 / 地点:", separator: "、", dropLabel: "设定 / 地点名", items: [...start.settings, ...start.locations] },
161
+ ];
162
+ }
163
+ /**
164
+ * 项目数据快照文本(§4.1:起始快照 + 本轮累积合并成一份;受 `DECOMPOSE_SNAPSHOT_MAX_CHARS` 约束)。
165
+ * 超预算按块丢弃(顺序见 `snapshotBlocks`),**每次丢弃都在文本里显式告知**——
166
+ * 静默截断会让模型以为自己看到了全部。空快照 → 空文本(提示词走「尚无上文」)。
167
+ */
168
+ export function snapshotText(start, bible) {
169
+ const blocks = snapshotBlocks(start, bible);
170
+ return renderSnapshot(blocks, fitSnapshot(blocks));
171
+ }
172
+ /** 预算裁剪:返回各块保留数(尾部先丢;块顺序 = `snapshotBlocks` 定义顺序) */
173
+ function fitSnapshot(blocks) {
174
+ const keep = blocks.map((block) => block.items.length);
175
+ let text = renderSnapshot(blocks, keep);
176
+ for (let index = blocks.length - 1; index >= 0 && text.length > DECOMPOSE_SNAPSHOT_MAX_CHARS; index--) {
177
+ while (keep[index] > 0 && text.length > DECOMPOSE_SNAPSHOT_MAX_CHARS) {
178
+ keep[index]--;
179
+ text = renderSnapshot(blocks, keep);
180
+ }
181
+ }
182
+ return keep;
183
+ }
184
+ /**
185
+ * 快照组成**与 `snapshotText` 共用同一份分块 + 预算**(`fitSnapshot`)——所以条目里的「已省略」
186
+ * 与提示词里模型看到的告知逐字一致;两处各算一遍必然漂移(数值单源)。
187
+ */
188
+ export function snapshotComposition(start, bible) {
189
+ const blocks = snapshotBlocks(start, bible);
190
+ const keep = fitSnapshot(blocks);
191
+ const itemsOf = (key) => blocks.find((block) => block.key === key)?.items.length ?? 0;
192
+ return {
193
+ start: {
194
+ characters: start.characters.length,
195
+ settings: start.settings.length,
196
+ locations: start.locations.length,
197
+ relations: start.relations.length,
198
+ prevSummaries: start.prevSummaries.length,
199
+ },
200
+ merged: { names: itemsOf("names"), relations: itemsOf("relations") },
201
+ omitted: blocks.flatMap((block, index) => {
202
+ const dropped = block.items.length - keep[index];
203
+ return dropped === 0 ? [] : [`${dropped} 个${block.dropLabel}`];
204
+ }),
205
+ };
206
+ }
207
+ /** 快照组成条目文案(§8;调用方不拼字符串,避免两处各写一份格式) */
208
+ function snapshotLogText(composition) {
209
+ const { characters, settings, locations, relations, prevSummaries } = composition.start;
210
+ const head = `快照:人物 ${characters} / 设定 ${settings} / 地点 ${locations} / 关系 ${relations} / 前置摘要 ${prevSummaries} 条`;
211
+ return composition.omitted.length === 0 ? head : `${head}(已省略 ${composition.omitted.join("、")})`;
212
+ }
213
+ /** 渲染快照(`keep[index]` = 保留块 index 的前 N 项;被丢条目换成一行告知文案) */
214
+ function renderSnapshot(blocks, keep) {
215
+ return blocks
216
+ .flatMap((block, index) => {
217
+ const kept = block.items.slice(0, keep[index]);
218
+ const dropped = block.items.length - kept.length;
219
+ return [
220
+ ...(kept.length === 0 ? [] : [block.prefix + kept.join(block.separator)]),
221
+ ...(dropped === 0 ? [] : [`(已省略 ${dropped} 个${block.dropLabel})`]),
222
+ ];
223
+ })
224
+ .join("\n");
225
+ }
226
+ // ============ 提示词(数值一律由常量插值,不在散文里复述) ============
227
+ /**
228
+ * 批提示词:系统提示 = 角色 + 输出契约 + 各上限;用户消息 = 项目数据快照 + 本批各章正文。
229
+ * 输出契约即 `normalizeExtraction` 的输入形状(逐章对齐;缺章 → 整批重试)。
230
+ */
231
+ function buildBatchPrompt(input) {
232
+ const snapshot = input.snapshotText === "" ? "(本批是首批,尚无上文)" : input.snapshotText;
233
+ const body = input.chapters.map((chapter) => `### 第${chapter.index}章 ${chapter.title}\n${chapter.text}`).join("\n\n");
234
+ return {
235
+ system: [
236
+ "你是小说拆解流水线的逐章抽取员。输入是长篇小说的其中若干章,输出必须是 JSON。",
237
+ "每章产出一个条目(chapterIndex = 输入里的章序),不得合并章节、不得遗漏——漏章会让整批重跑。",
238
+ "只输出 JSON(可以放 ```json 围栏),不要写解释文字。",
239
+ "",
240
+ '输出结构:{"chapters":[{"chapterIndex":1,"chapterTitle":"…","summary":"…","characters":[…],"settings":[…],"locations":[…],"relations":[…]}]}',
241
+ "",
242
+ "字段口径:",
243
+ `- summary:本章剧情摘要,不超过 ${DECOMPOSE_CHAPTER_SUMMARY_MAX_CHARS} 字;`,
244
+ "- characters[]:{name, role, description, alias, gender, age, race, personality, motivation}",
245
+ `- name 必填;role 建议用:${DECOMPOSE_ROLE_ORDER.join(" / ")};`,
246
+ `- description 必填且不超过 ${DECOMPOSE_DESCRIPTION_MAX_CHARS} 字;alias 只填一个最常用的别称,其余别名写进 description 的「(又称:X、Y)」;`,
247
+ `- gender / age / race 只在文中明确时填;personality 不超过 ${DECOMPOSE_PERSONALITY_MAX_ITEMS} 条;motivation 不超过 ${DECOMPOSE_MOTIVATION_MAX_CHARS} 字;`,
248
+ `- 不要输出 ability_panel 与 custom_fields;每章人物不超过 ${DECOMPOSE_CHAPTER_MAX_CHARACTERS} 条;`,
249
+ `- settings[]:{name, description, tags, rules}——只抽对剧情有影响的设定;tags 写短标签、rules 写短句、description 不超过 ${DECOMPOSE_DESCRIPTION_MAX_CHARS} 字;每章不超过 ${DECOMPOSE_CHAPTER_MAX_SETTINGS} 条;`,
250
+ `- locations[]:{name, type, description}——不输出上级地点;description 不超过 ${DECOMPOSE_DESCRIPTION_MAX_CHARS} 字;每章不超过 ${DECOMPOSE_CHAPTER_MAX_LOCATIONS} 条;`,
251
+ `- relations[]:{source, target, type, evidence}——type 只能取 ${DECOMPOSE_RELATION_TYPES.join(" / ")};source / target 必须是本章或上文出现过的名字;每章不超过 ${DECOMPOSE_CHAPTER_MAX_RELATIONS} 条。`,
252
+ ].join("\n"),
253
+ user: [`【项目数据快照】${snapshot}`, "", "【本批正文】", body].join("\n"),
254
+ };
255
+ }
256
+ /**
257
+ * 一批的执行:整批重试(≤ `DECOMPOSE_BATCH_MAX_ATTEMPTS`,含首次)——缺章是最常见的败因,
258
+ * 重试代价 = 一批 token,而缺章的产出本来就不完整;超上限 → 标 `failed` 并继续后续批。
259
+ * 取消(暂停 / 切书)时不再重试:批留在未完成状态,由续拆承接(`schema.md`「状态归一」不变式)。
260
+ */
261
+ async function runBatch(input) {
262
+ let lastError = "批未完成";
263
+ input.session.log({
264
+ kind: "batch_start",
265
+ batchSeq: input.batch.seq,
266
+ text: `批 ${input.batch.seq} 开始(${input.chapters.length} 章;快照 ${input.snapshotSize})`,
267
+ });
268
+ for (let attempt = 1; attempt <= DECOMPOSE_BATCH_MAX_ATTEMPTS; attempt++) {
269
+ if (input.signal.aborted)
270
+ return { result: null, failed: false };
271
+ if (startBatchAttempt(input.project.db, input.jobId, input.batch.seq, nowIso()) === null) {
272
+ throw new Error(`拆解批不存在:job ${input.jobId} 批 ${input.batch.seq}`);
273
+ }
274
+ try {
275
+ const completion = await input.session.complete(buildBatchPrompt({ chapters: input.chapters, snapshotText: input.snapshotText }));
276
+ const normalized = normalizeExtraction(parseModelJson(completion.text), input.chapters.map((chapter) => chapter.index), input.knownNames);
277
+ if (normalized.discarded.length > 0) {
278
+ console.warn(`[decompose] job ${input.jobId} 批 ${input.batch.seq} 归一丢弃:${normalized.discarded.join(";")}`);
279
+ }
280
+ completeBatch(input.project.db, { jobId: input.jobId, seq: input.batch.seq, result: normalized.result, now: nowIso() });
281
+ input.session.log({
282
+ kind: "batch_done",
283
+ batchSeq: input.batch.seq,
284
+ text: `批 ${input.batch.seq} 完成:${batchCountsText(normalized.result)};本次用量 输入 ${completion.usage.input} token / 输出 ${completion.usage.output} token`,
285
+ });
286
+ return { result: normalized.result, failed: false };
287
+ }
288
+ catch (err) {
289
+ lastError = errorMessage(err);
290
+ input.session.log({
291
+ kind: "attempt_failed",
292
+ batchSeq: input.batch.seq,
293
+ text: `批 ${input.batch.seq} 第 ${attempt} 次尝试失败:${lastError}`,
294
+ });
295
+ console.warn(`[decompose] job ${input.jobId} 批 ${input.batch.seq} 第 ${attempt} 次尝试失败:${lastError}`);
296
+ }
297
+ }
298
+ failBatch(input.project.db, { jobId: input.jobId, seq: input.batch.seq, error: lastError, now: nowIso() });
299
+ return { result: null, failed: true };
300
+ }
301
+ /** 一批的抽取计数(过程条目的「批完成」文案:各分组条数,不含原文与批结果本身) */
302
+ function batchCountsText(result) {
303
+ const totals = result.chapters.reduce((sum, chapter) => ({
304
+ characters: sum.characters + chapter.characters.length,
305
+ settings: sum.settings + chapter.settings.length,
306
+ locations: sum.locations + chapter.locations.length,
307
+ relations: sum.relations + chapter.relations.length,
308
+ }), { characters: 0, settings: 0, locations: 0, relations: 0 });
309
+ return `人物 ${totals.characters} / 设定 ${totals.settings} / 地点 ${totals.locations} / 关系 ${totals.relations}`;
310
+ }
311
+ /** 一批的素材:章序 / 标题来自大纲(章序 = 文件位置序),正文一次批量取投影(勿逐章查) */
312
+ function batchChapters(project, batch, tree, chapterNumberById) {
313
+ const texts = getDocumentTexts(project.db, "chapter", batch.chapter_ids);
314
+ return batch.chapter_ids.flatMap((chapterId) => {
315
+ const index = chapterNumberById.get(chapterId);
316
+ // 章被物理删(回收站清除)后批行仍留旧 id:正文与章序都没了 ⇒ 从本批素材剔除,
317
+ // 否则「缺章」判据会把整批判死(进度页同样跳过这些 id,见 job.ts 的 buildJobResponse)
318
+ if (index === undefined)
319
+ return [];
320
+ return [{ index, title: findOutlineNode(tree, chapterId)?.title ?? "", text: texts.get(chapterId) ?? "" }];
321
+ });
322
+ }
323
+ /** 一轮批执行(S2):串行逐批调模型,结果只写 `decompose_batches.result` */
324
+ async function executeRun(input) {
325
+ const { project, job, session, signal } = input;
326
+ const batches = listDecomposeBatches(project.db, job.id);
327
+ const pending = batches.filter((batch) => batch.status !== "done" || batch.seq === input.rerunSeq);
328
+ const tree = readOutlineFile(project.root); // 一轮一份大纲快照(长任务里用户可能改标题)
329
+ const chapterOrder = deriveChapterOrder(project.root);
330
+ const chapterNumberById = new Map(chapterOrder.map((entry) => [entry.chapterId, entry.chapterNumber]));
331
+ // 起始快照:一轮开头读库一次(不随批刷新);前置章摘要取本 job 范围起点之前的连续若干章
332
+ const startSnapshot = readStartSnapshot({ project, scopeStart: job.scope_start, chapterOrder, tree });
333
+ let bible = doneBatchResults(project.db, job.id, batches
334
+ .filter((batch) => batch.status === "done" && batch.seq !== input.rerunSeq)
335
+ .map((batch) => batch.seq)).reduce(extendStoryBible, emptyStoryBible());
336
+ // 快照组成条目(§8):一轮一条,报本次读库的规模与预算省略(不塞全文;模型看不到这行)
337
+ session.log({ kind: "snapshot", text: snapshotLogText(snapshotComposition(startSnapshot, bible)) });
338
+ let executed = 0;
339
+ let failed = 0;
340
+ for (let start = 0; start < pending.length && !signal.aborted; start += DECOMPOSE_CONCURRENCY) {
341
+ const outcomes = await Promise.all(pending.slice(start, start + DECOMPOSE_CONCURRENCY).map((batch) => {
342
+ const composition = snapshotComposition(startSnapshot, bible); // 每批重算:本轮累积随批增长
343
+ return runBatch({
344
+ project,
345
+ jobId: job.id,
346
+ batch,
347
+ chapters: batchChapters(project, batch, tree, chapterNumberById),
348
+ // 提示词受预算裁剪,校验用全集不裁(两套东西,见 `snapshotKnownNames`)
349
+ snapshotText: snapshotText(startSnapshot, bible),
350
+ snapshotSize: `名字 ${composition.merged.names} / 关系 ${composition.merged.relations}`,
351
+ knownNames: snapshotKnownNames(startSnapshot, bible),
352
+ session,
353
+ signal,
354
+ });
355
+ }));
356
+ for (const outcome of outcomes) {
357
+ executed++;
358
+ if (outcome.failed)
359
+ failed++;
360
+ if (outcome.result !== null)
361
+ bible = extendStoryBible(bible, outcome.result);
362
+ }
363
+ }
364
+ console.log(`[decompose] job ${job.id} 批执行收尾:执行 ${executed} 批 / 失败 ${failed} 批${signal.aborted ? "(已暂停)" : ""}`);
365
+ }
366
+ const activeRuns = new Map();
367
+ /**
368
+ * 中止一个 job 的在跑轮次(pause 路由用):当前批跑完即停,**已发出的模型调用不 abort**。
369
+ * 状态写入归调用方(pause 路由 / `setCurrentProject` 的归一)。
370
+ * @returns 是否有在跑的一轮
371
+ */
372
+ export function pauseDecomposeJob(jobId) {
373
+ const run = activeRuns.get(jobId);
374
+ run?.controller.abort();
375
+ return run !== undefined;
376
+ }
377
+ /** 中止全部在跑轮次(切书 / 关项目挂点:不做跨书后台跑) */
378
+ export function cancelRunningDecomposeJobs() {
379
+ for (const run of activeRuns.values())
380
+ run.controller.abort();
381
+ }
382
+ /**
383
+ * 该 job 是否有在跑(或排队)的一轮(chat 侧的删除守卫用):
384
+ * **暂停后当前批仍在飞**——job 行已是 `paused`,但会话文件还会被这轮原地重建,同样不能删(§7.2)。
385
+ */
386
+ export function isDecomposeJobActive(jobId) {
387
+ return activeRuns.has(jobId);
388
+ }
389
+ /**
390
+ * 清理超出保留上限的拆解会话(§7.2):按 job `created_at` 保留最近 `DECOMPOSE_KEPT_SESSIONS` 枚
391
+ * (`job-<nanoid>` 里没有可解析时间 ⇒ 排序依据只能是 job 行,不是文件名),更早的会话文件物理删除
392
+ * (与 `DELETE /chat/sessions/:id` 同款:pi 磁盘发现拿路径 → `unlinkSync`)。
393
+ *
394
+ * - **只碰会话 id 为 `decompose-` 前缀的记录**:候选集 = 历史 job 行,会话 id 由 `decomposeSessionId`
395
+ * 组装、查找走 pi 的磁盘发现 + 会话 id 命中(文件名带时间戳前缀,**不得**按文件名 glob)
396
+ * ⇒ chat 会话结构上不可能参与(用户资产);
397
+ * - **在跑的一律不删**:job 行 `pending` / `running`,或进程内有在跑轮次(暂停后当前批仍在飞,
398
+ * 删了会被这轮原地重建);
399
+ * - 单个文件删不掉只记日志(同 `pruneBackups` 口径),整段失败也不阻塞拆解。
400
+ *
401
+ * @returns 实际删除的会话枚数(无需清理 / 失败 → 0)
402
+ */
403
+ export async function pruneDecomposeSessions(project) {
404
+ try {
405
+ const jobs = listDecomposeJobs(project.db); // created_at 升序
406
+ const extras = jobs.slice(0, Math.max(0, jobs.length - DECOMPOSE_KEPT_SESSIONS));
407
+ let pruned = 0;
408
+ for (const job of extras) {
409
+ if (job.status === "pending" || job.status === "running" || isDecomposeJobActive(job.id))
410
+ continue;
411
+ const sessionId = decomposeSessionId(job.id);
412
+ const info = await findProjectSession(project.root, sessionId);
413
+ if (info === null)
414
+ continue; // 从未落盘 / 已被删 ⇒ 无事可做(清理幂等)
415
+ try {
416
+ unlinkSync(info.path);
417
+ pruned++;
418
+ }
419
+ catch (err) {
420
+ console.error(`[decompose] 清理旧拆解会话失败(跳过,不阻塞): ${sessionId}`, err);
421
+ }
422
+ }
423
+ return pruned;
424
+ }
425
+ catch (err) {
426
+ console.error("[decompose] 清理旧拆解会话失败(跳过,不阻塞):", err);
427
+ return 0;
428
+ }
429
+ }
430
+ /**
431
+ * 启动 job 的批执行(**调用方不 await**:长任务)。状态前置校验归调用方(start / resume / rerun 各自置 `running`)。
432
+ * 同一 job 已有在跑或排队的一轮时,本轮排在它后面(见上方「排队」);批全部收口后接 S3 + S4 并把 job 置 `done`。
433
+ * @returns 本轮收尾的 promise(调用方不 await;测试可 await)
434
+ */
435
+ export function startDecomposeJob(project, deps = {}, options = {}) {
436
+ const job = getDecomposeJob(project.db); // 一项目一 job:取最新一行(db helper 口径)
437
+ if (job === null || job.status !== "running")
438
+ return Promise.resolve();
439
+ const controller = new AbortController();
440
+ const previous = activeRuns.get(job.id);
441
+ const run = { controller, done: Promise.resolve() };
442
+ activeRuns.set(job.id, run);
443
+ run.done = (async () => {
444
+ try {
445
+ await previous?.done; // 上一轮先收尾(含它正在飞的批落库)
446
+ if (controller.signal.aborted)
447
+ return;
448
+ // §7.2:清理超限的更早拆解会话——**必须在创建本轮会话之前**(幂等;失败只记日志,不阻塞拆解)
449
+ const pruned = await pruneDecomposeSessions(project);
450
+ if (pruned > 0) {
451
+ // 删除不静默(§9 不变式 9):日志必须赶在开会话**之前**——开会话抛错(缺模型 / 凭据 / 会话目录不可写)
452
+ // 时只有这条落得下;下面的过程条目依赖新会话,只能留在原地。枚数由常量插值,散文不复述数字
453
+ console.log(`[decompose] 已清理 ${pruned} 份更早的拆解会话(保留最近 ${DECOMPOSE_KEPT_SESSIONS} 份)`);
454
+ }
455
+ // 会话(落盘 + 过程条目)一轮一枚:S2 各批 + S3 归并 + S4 报告都写进它(deps 缺模型/凭据 → 抛错 → job 标失败)
456
+ const session = await openDecomposeSession(deps, {
457
+ projectRoot: project.root,
458
+ jobId: job.id,
459
+ bookName: project.config.name,
460
+ });
461
+ if (pruned > 0) {
462
+ // 删除不静默:本轮会话的过程条目(`#/decompose` 时间线可见)
463
+ session.log({
464
+ kind: "session_pruned",
465
+ text: `已清理 ${pruned} 份更早的拆解记录(保留最近 ${DECOMPOSE_KEPT_SESSIONS} 份)`,
466
+ });
467
+ }
468
+ await executeRun({ project, job, session, signal: controller.signal, rerunSeq: options.rerunSeq });
469
+ if (controller.signal.aborted)
470
+ return; // 暂停 / 切书:不跑 S3/S4(状态归暂停与续拆路径)
471
+ await finishJob(project, job, session);
472
+ }
473
+ catch (err) {
474
+ failJob(project, job, controller.signal, err);
475
+ }
476
+ finally {
477
+ if (activeRuns.get(job.id) === run)
478
+ activeRuns.delete(job.id);
479
+ }
480
+ })();
481
+ return run.done;
482
+ }
483
+ /**
484
+ * job 收口(§2「S3 只在全部批完成后跑一次」):批全部收口 → S3 归并 + S4 报告 → job 置 `done`。
485
+ * 有未收口批(暂停 / 崩溃残留)→ 什么都不做(状态归暂停与续拆路径)。
486
+ * 状态回写前重读 job 行:S3/S4 期间可能被暂停 / 切书(长调用),不能盖掉那次状态。
487
+ */
488
+ async function finishJob(project, job, session) {
489
+ const settled = listDecomposeBatches(project.db, job.id).every((batch) => batch.status === "done" || batch.status === "failed");
490
+ if (!settled)
491
+ return;
492
+ const summary = await runDecomposeMerge({ project, jobId: job.id, session, now: nowIso() });
493
+ console.log(`[decompose] job ${job.id} 归并与报告收尾:实体 ${summary.entities} / 关系 ${summary.relations} / 别名组 ${summary.aliasGroups} / 报告 ${summary.reportId}`);
494
+ if (getDecomposeJob(project.db)?.status !== "running")
495
+ return;
496
+ updateJobStatus(project.db, job.id, "done", nowIso());
497
+ }
498
+ /**
499
+ * job 级失败(批级失败不阻塞整个 job,故只在此处把 job 标 `failed`):写错误摘要 + 状态。
500
+ * 已取消(暂停 / 切书,含被 resume 顶替的旧轮)时不改状态——状态归暂停与续拆路径,
501
+ * 否则旧轮的 `failed` 会盖掉新一轮刚写的 `running`。
502
+ */
503
+ function failJob(project, job, signal, err) {
504
+ const message = errorMessage(err);
505
+ console.error(`[decompose] job ${job.id} 执行失败:${message}`, err);
506
+ try {
507
+ setJobError(project.db, job.id, message, nowIso());
508
+ if (!signal.aborted)
509
+ updateJobStatus(project.db, job.id, "failed", nowIso());
510
+ }
511
+ catch (writeErr) {
512
+ // 切书会先关旧库连接(start / open 路由的切换顺序)⇒ 写不进去是预期形态:
513
+ // 该 job 行由「下次打开这本书时的归一」接管
514
+ console.error(`[decompose] job ${job.id} 失败状态写入失败(库可能已关闭)`, writeErr);
515
+ }
516
+ }
517
+ function errorMessage(err) {
518
+ return err instanceof Error ? err.message : String(err);
519
+ }
520
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/decompose/runner.ts"],"names":[],"mappings":"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"}