@waterwx/dsh-novel-forge 1.1.9 → 1.2.0
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.
- package/lib/client.js +1874 -1267
- package/lib/client.js.map +1 -1
- package/lib/index.js +59 -8
- package/lib/index.js.map +1 -1
- package/lib/types/client/locales.d.ts +8 -0
- package/lib/types/client/panel/NovelPanel.d.ts +1 -1
- package/lib/types/engine.d.ts +1 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/protocol.d.ts +25 -0
- package/package.json +1 -1
- package/src/client/locales.ts +16 -0
- package/src/client/panel/AssetsTab.tsx +19 -0
- package/src/client/panel/NovelPanel.tsx +522 -225
- package/src/client/panel/ShelfView.tsx +13 -12
- package/src/client/panel/panel.module.css +192 -68
- package/src/engine.ts +9 -1
- package/src/index.ts +6 -0
- package/src/protocol.ts +26 -0
- package/src/routes.ts +31 -4
package/lib/index.js
CHANGED
|
@@ -1116,7 +1116,8 @@ async function complete(ctx, config, options) {
|
|
|
1116
1116
|
messages,
|
|
1117
1117
|
system: options.system,
|
|
1118
1118
|
maxTokens: options.maxTokens ?? config.maxTokens,
|
|
1119
|
-
temperature: options.temperature ?? .7
|
|
1119
|
+
temperature: options.temperature ?? .7,
|
|
1120
|
+
reasoningEffort: ReasoningEffortId(config.reasoningEffort ?? "off")
|
|
1120
1121
|
};
|
|
1121
1122
|
const assembler = new BlockAssembler();
|
|
1122
1123
|
for await (const chunk of ctx.llm.stream(request)) assembler.push(chunk);
|
|
@@ -2747,15 +2748,21 @@ async function auditBatch(ctx, config, project, outputDir, batch) {
|
|
|
2747
2748
|
return issues;
|
|
2748
2749
|
}
|
|
2749
2750
|
/** 全书一致性质检:LLM 分批扫描已生成章节 + 设定 + 事实库,聚合矛盾清单。 */
|
|
2750
|
-
async function auditBook(ctx, config, project, outputDir) {
|
|
2751
|
+
async function auditBook(ctx, config, project, outputDir, onProgress) {
|
|
2751
2752
|
const written = project.chapters.filter((c) => c.status !== "pending" && c.status !== "generating");
|
|
2752
|
-
if (written.length === 0)
|
|
2753
|
+
if (written.length === 0) {
|
|
2754
|
+
onProgress?.(0, 0);
|
|
2755
|
+
return [];
|
|
2756
|
+
}
|
|
2757
|
+
const totalBatches = Math.ceil(written.length / AUDIT_BATCH_SIZE);
|
|
2753
2758
|
const all = [];
|
|
2759
|
+
onProgress?.(0, totalBatches);
|
|
2754
2760
|
for (let i = 0; i < written.length; i += AUDIT_BATCH_SIZE) {
|
|
2755
2761
|
const batch = written.slice(i, i + AUDIT_BATCH_SIZE);
|
|
2756
2762
|
try {
|
|
2757
2763
|
all.push(...await auditBatch(ctx, config, project, outputDir, batch));
|
|
2758
2764
|
} catch {}
|
|
2765
|
+
onProgress?.(Math.min(Math.ceil((i + AUDIT_BATCH_SIZE) / AUDIT_BATCH_SIZE), totalBatches), totalBatches);
|
|
2759
2766
|
}
|
|
2760
2767
|
return all.slice(0, 50);
|
|
2761
2768
|
}
|
|
@@ -4522,6 +4529,12 @@ const DEFAULT_PLAN_COUNT = 30;
|
|
|
4522
4529
|
*/
|
|
4523
4530
|
function makeRoutes(deps) {
|
|
4524
4531
|
const { ctx, getConfig, patchConfig } = deps;
|
|
4532
|
+
/** 全书质检实时状态(内存态,重启后回到 idle;用于 /status 暴露进度)。 */
|
|
4533
|
+
let auditState = {
|
|
4534
|
+
status: "idle",
|
|
4535
|
+
totalBatches: 0,
|
|
4536
|
+
completedBatches: 0
|
|
4537
|
+
};
|
|
4525
4538
|
/** Guard helper: fence + method check. */
|
|
4526
4539
|
const guard = (req, res, method) => {
|
|
4527
4540
|
if (!isLoopbackRequest(req)) {
|
|
@@ -4573,7 +4586,8 @@ function makeRoutes(deps) {
|
|
|
4573
4586
|
...project,
|
|
4574
4587
|
facts: (project.facts ?? []).slice(-80)
|
|
4575
4588
|
} : void 0,
|
|
4576
|
-
generatedFiles: listChapterFiles(config.outputDir)
|
|
4589
|
+
generatedFiles: listChapterFiles(config.outputDir),
|
|
4590
|
+
audit: auditState
|
|
4577
4591
|
});
|
|
4578
4592
|
}
|
|
4579
4593
|
};
|
|
@@ -5478,13 +5492,41 @@ function makeRoutes(deps) {
|
|
|
5478
5492
|
const config = getConfig();
|
|
5479
5493
|
const project = requireProject(res);
|
|
5480
5494
|
if (project === void 0) return;
|
|
5495
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5496
|
+
auditState = {
|
|
5497
|
+
status: "running",
|
|
5498
|
+
startedAt,
|
|
5499
|
+
totalBatches: 0,
|
|
5500
|
+
completedBatches: 0
|
|
5501
|
+
};
|
|
5481
5502
|
try {
|
|
5503
|
+
const issues = await auditBook(ctx, config, project, config.outputDir, (completed, total) => {
|
|
5504
|
+
auditState.totalBatches = total;
|
|
5505
|
+
auditState.completedBatches = completed;
|
|
5506
|
+
});
|
|
5507
|
+
const auditedChapters = project.chapters.filter((c) => c.status !== "pending" && c.status !== "generating").length;
|
|
5508
|
+
auditState = {
|
|
5509
|
+
status: "done",
|
|
5510
|
+
startedAt,
|
|
5511
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5512
|
+
totalBatches: auditState.totalBatches,
|
|
5513
|
+
completedBatches: auditState.totalBatches,
|
|
5514
|
+
auditedChapters,
|
|
5515
|
+
issuesCount: issues.length,
|
|
5516
|
+
issues
|
|
5517
|
+
};
|
|
5482
5518
|
writeJson(res, 200, {
|
|
5483
|
-
issues
|
|
5484
|
-
auditedChapters
|
|
5485
|
-
auditedAt:
|
|
5519
|
+
issues,
|
|
5520
|
+
auditedChapters,
|
|
5521
|
+
auditedAt: auditState.finishedAt
|
|
5486
5522
|
});
|
|
5487
5523
|
} catch (error) {
|
|
5524
|
+
auditState = {
|
|
5525
|
+
...auditState,
|
|
5526
|
+
status: "error",
|
|
5527
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5528
|
+
error: error.message
|
|
5529
|
+
};
|
|
5488
5530
|
writeJson(res, 500, { error: error.message });
|
|
5489
5531
|
}
|
|
5490
5532
|
}
|
|
@@ -6042,7 +6084,7 @@ function makeRoutes(deps) {
|
|
|
6042
6084
|
return;
|
|
6043
6085
|
}
|
|
6044
6086
|
}
|
|
6045
|
-
const missing = project.chapters.filter((c) => c.status !== "pending" && c.status !== "generating" && c.authorReview === void 0);
|
|
6087
|
+
const missing = project.chapters.filter((c) => c.status !== "pending" && c.status !== "generating" && c.status !== "error" && c.authorReview === void 0);
|
|
6046
6088
|
if (missing.length === 0) {
|
|
6047
6089
|
writeJson(res, 200, { count: 0 });
|
|
6048
6090
|
return;
|
|
@@ -6324,6 +6366,12 @@ const Config = z.object({
|
|
|
6324
6366
|
outputDir: z.string().default("D:\\ryan work\\harness\\novels\\归墟玉主"),
|
|
6325
6367
|
provider: z.string().default("deepseek-official"),
|
|
6326
6368
|
model: z.string().default("deepseek-v4-flash"),
|
|
6369
|
+
reasoningEffort: z.union([
|
|
6370
|
+
"off",
|
|
6371
|
+
"low",
|
|
6372
|
+
"high",
|
|
6373
|
+
"max"
|
|
6374
|
+
]).default("off"),
|
|
6327
6375
|
chapterChars: z.number().default(3500),
|
|
6328
6376
|
maxTokens: z.number().default(12e3),
|
|
6329
6377
|
reviewPassScore: z.number().default(70),
|
|
@@ -6337,6 +6385,7 @@ const DEFAULT_OUTLINE_PATH = "D:\\ryan work\\harness\\novels\\归墟玉主\\《
|
|
|
6337
6385
|
const DEFAULT_OUTPUT_DIR = "D:\\ryan work\\harness\\novels\\归墟玉主";
|
|
6338
6386
|
const DEFAULT_PROVIDER = "deepseek-official";
|
|
6339
6387
|
const DEFAULT_MODEL = "deepseek-v4-flash";
|
|
6388
|
+
const DEFAULT_REASONING_EFFORT = "off";
|
|
6340
6389
|
const DEFAULT_CHAPTER_CHARS = 3500;
|
|
6341
6390
|
const DEFAULT_MAX_TOKENS = 12e3;
|
|
6342
6391
|
const DEFAULT_REVIEW_PASS_SCORE = 70;
|
|
@@ -6354,6 +6403,7 @@ function resolveConfig(value) {
|
|
|
6354
6403
|
outputDir: value?.outputDir ?? DEFAULT_OUTPUT_DIR,
|
|
6355
6404
|
provider: value?.provider ?? DEFAULT_PROVIDER,
|
|
6356
6405
|
model: value?.model ?? DEFAULT_MODEL,
|
|
6406
|
+
reasoningEffort: value?.reasoningEffort ?? DEFAULT_REASONING_EFFORT,
|
|
6357
6407
|
chapterChars: value?.chapterChars ?? DEFAULT_CHAPTER_CHARS,
|
|
6358
6408
|
maxTokens: value?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
6359
6409
|
reviewPassScore: value?.reviewPassScore ?? DEFAULT_REVIEW_PASS_SCORE,
|
|
@@ -6384,6 +6434,7 @@ function apply(ctx, config) {
|
|
|
6384
6434
|
if (patch.outputDir !== void 0) next.outputDir = patch.outputDir;
|
|
6385
6435
|
if (patch.provider !== void 0) next.provider = patch.provider;
|
|
6386
6436
|
if (patch.model !== void 0) next.model = patch.model;
|
|
6437
|
+
if (patch.reasoningEffort !== void 0) next.reasoningEffort = patch.reasoningEffort;
|
|
6387
6438
|
if (patch.chapterChars !== void 0) next.chapterChars = patch.chapterChars;
|
|
6388
6439
|
if (patch.maxTokens !== void 0) next.maxTokens = patch.maxTokens;
|
|
6389
6440
|
if (patch.reviewPassScore !== void 0) next.reviewPassScore = patch.reviewPassScore;
|