@musnows/scriverse 1.1.2 → 1.1.4
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/README.en.md +3 -0
- package/README.md +3 -0
- package/dist/ai-response-limit.js +12 -0
- package/dist/ai-response-limit.js.map +1 -0
- package/dist/ai.js +18 -12
- package/dist/ai.js.map +1 -1
- package/dist/app.js +47 -4
- package/dist/app.js.map +1 -1
- package/dist/chapter-title-numbering.js +210 -0
- package/dist/chapter-title-numbering.js.map +1 -1
- package/dist/cli-contract.js +15 -6
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli-core.js +37 -1
- package/dist/cli-core.js.map +1 -1
- package/dist/database.js +21 -2
- package/dist/database.js.map +1 -1
- package/dist/public/app.js +374 -15
- package/dist/public/index.html +12 -2
- package/dist/public/styles.css +3 -2
- package/dist/store.js +190 -10
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +5 -1
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -14,6 +14,7 @@ import { AI_PROVIDER_PROTOCOL_OPTIONS, AI_PROVIDER_PROTOCOLS, AI_THINKING_TYPES,
|
|
|
14
14
|
import { MAX_AI_ANALYSIS_TIMEOUT_SECONDS, MIN_AI_ANALYSIS_TIMEOUT_SECONDS } from "./ai-analysis-timeout.js";
|
|
15
15
|
import { aiConversationExportContentDisposition, exportAiConversationMarkdown } from "./ai-conversation-export.js";
|
|
16
16
|
import { DEFAULT_AI_CHAT_TAB_LIMIT } from "./ai-chat-tab-limit.js";
|
|
17
|
+
import { resolveAiResponseMaxBytes } from "./ai-response-limit.js";
|
|
17
18
|
import { DEFAULT_CHAPTER_ANNOTATION_NOTE_MAX_LENGTH } from "./chapter-annotation-note.js";
|
|
18
19
|
import { MAX_AI_STREAM_IDLE_TIMEOUT_SECONDS, MIN_AI_STREAM_IDLE_TIMEOUT_SECONDS, normalizeAiStreamIdleTimeoutSeconds } from "./ai-stream-timeout.js";
|
|
19
20
|
import { AttachmentStorage } from "./attachment-storage.js";
|
|
@@ -35,7 +36,7 @@ import { isOfficialGoogleVertexBaseUrl, parseGoogleServiceAccount } from "./goog
|
|
|
35
36
|
import { HYBRID_SEARCH_TYPES, MAXIMUM_WORK_SEARCH_QUERY_LENGTH, readableHybridSearchTypes } from "./hybrid-search.js";
|
|
36
37
|
import { applyImportFileHints, parseNovelText } from "./parser.js";
|
|
37
38
|
import { MAX_CHAPTER_LINE_IDS } from "./chapter-annotation-anchor.js";
|
|
38
|
-
import { isChapterNumberTemplate } from "./chapter-title-numbering.js";
|
|
39
|
+
import { chapterTitlePreferences, isChapterNumberTemplate } from "./chapter-title-numbering.js";
|
|
39
40
|
import { aiConversationTaskTypes, attachmentPermissionModules, RECYCLE_BIN_RETENTION_DAYS, Store, versionedEntityTypes, WORK_AGENT_TOOL_IDS } from "./store.js";
|
|
40
41
|
import { composeRoleplayStoredUserContent } from "./roleplay-turn.js";
|
|
41
42
|
import { ROLEPLAY_MEMORY_CATEGORIES, ROLEPLAY_MEMORY_CERTAINTY, ROLEPLAY_MEMORY_IMPORTANCE, ROLEPLAY_MEMORY_STATUSES } from "./roleplay-memory.js";
|
|
@@ -256,7 +257,8 @@ const workSchema = z.object({
|
|
|
256
257
|
coverUrl: z.string().url().nullable().optional(),
|
|
257
258
|
tags: optionalStrings,
|
|
258
259
|
editorAutoIndentEnabled: z.boolean().optional(),
|
|
259
|
-
editorTypewriterModeEnabled: z.boolean().optional()
|
|
260
|
+
editorTypewriterModeEnabled: z.boolean().optional(),
|
|
261
|
+
chapterTitleFormat: z.enum(chapterTitlePreferences).optional()
|
|
260
262
|
});
|
|
261
263
|
const workOfflineAccessSchema = z.object({ enabled: z.boolean() }).strict();
|
|
262
264
|
const settingSchema = z.object({
|
|
@@ -760,7 +762,7 @@ const desktopLocalAiRunSchema = z.object({
|
|
|
760
762
|
const desktopLocalAiCompletionResponseSchema = z.object({
|
|
761
763
|
requestId: identifier,
|
|
762
764
|
status: z.number().int().min(100).max(599),
|
|
763
|
-
body: z.string()
|
|
765
|
+
body: z.string(),
|
|
764
766
|
retryAfter: z.string().max(500).optional()
|
|
765
767
|
}).strict();
|
|
766
768
|
/** 创建任务 API 的分析类型校验:仅允许可新建类型,历史类型在运行层保留防御性拒绝。 */
|
|
@@ -1520,6 +1522,14 @@ export function createRuntime(options) {
|
|
|
1520
1522
|
if (options.security?.enforceSameOrigin ?? true)
|
|
1521
1523
|
app.use(createSameOriginMiddleware());
|
|
1522
1524
|
app.use("/api/sync/works", express.json({ limit: "3mb" }));
|
|
1525
|
+
app.use("/api/works/:workId/desktop-local-ai/runs/:runId/responses", (request, response, next) => {
|
|
1526
|
+
const maximumResponseBytes = resolveAiResponseMaxBytes();
|
|
1527
|
+
// 外层 JSON 会转义响应文本;最终仍按响应字符串的 UTF-8 字节数校验。
|
|
1528
|
+
const requestBodyLimit = maximumResponseBytes === null
|
|
1529
|
+
? Number.MAX_SAFE_INTEGER
|
|
1530
|
+
: Math.min(Number.MAX_SAFE_INTEGER, maximumResponseBytes * 6 + 4_096);
|
|
1531
|
+
express.json({ limit: requestBodyLimit })(request, response, next);
|
|
1532
|
+
});
|
|
1523
1533
|
app.use(express.json({ limit: "2mb" }));
|
|
1524
1534
|
const registrationMode = resolveRegistrationMode(options.security);
|
|
1525
1535
|
const registrationEnabled = isRegistrationEnabled(registrationMode);
|
|
@@ -2427,6 +2437,9 @@ export function createRuntime(options) {
|
|
|
2427
2437
|
store.deleteVolume(request.params.volumeId, input.expectedVersionNo);
|
|
2428
2438
|
noContent(response);
|
|
2429
2439
|
});
|
|
2440
|
+
app.post("/api/volumes/:volumeId/renumber-titles", (request, response) => {
|
|
2441
|
+
data(response, store.renumberVolumeChapterTitles(request.params.volumeId));
|
|
2442
|
+
});
|
|
2430
2443
|
app.post("/api/volumes/:volumeId/restore", (request, response) => {
|
|
2431
2444
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
2432
2445
|
data(response, store.restoreVolume(request.params.volumeId, input.expectedVersionNo));
|
|
@@ -2437,8 +2450,32 @@ export function createRuntime(options) {
|
|
|
2437
2450
|
await cleanupAttachments();
|
|
2438
2451
|
noContent(response);
|
|
2439
2452
|
});
|
|
2453
|
+
app.get("/api/works/:workId/chapter-title-format", (request, response) => {
|
|
2454
|
+
data(response, store.describeChapterTitleFormat(request.params.workId));
|
|
2455
|
+
});
|
|
2456
|
+
app.patch("/api/works/:workId/chapter-title-format", (request, response) => {
|
|
2457
|
+
const input = parse(z.object({
|
|
2458
|
+
chapterTitleFormat: z.enum(chapterTitlePreferences),
|
|
2459
|
+
expectedVersionNo: expectedVersionNoSchema
|
|
2460
|
+
}).strict(), request.body);
|
|
2461
|
+
const work = store.updateWork(request.params.workId, { chapterTitleFormat: input.chapterTitleFormat }, input.expectedVersionNo, "manual", null, "更新章节标题编号格式");
|
|
2462
|
+
data(response, {
|
|
2463
|
+
...store.describeChapterTitleFormat(request.params.workId),
|
|
2464
|
+
versionNo: Number(work.versionNo)
|
|
2465
|
+
});
|
|
2466
|
+
});
|
|
2440
2467
|
app.post("/api/works/:workId/chapters", (request, response) => {
|
|
2441
|
-
const input = parse(z.object({
|
|
2468
|
+
const input = parse(z.object({
|
|
2469
|
+
volumeId: identifier,
|
|
2470
|
+
title: nonEmpty.max(300),
|
|
2471
|
+
content: z.string().max(2_000_000).optional(),
|
|
2472
|
+
chapterType: chapterTypeSchema.optional(),
|
|
2473
|
+
insertAfterChapterId: identifier.optional(),
|
|
2474
|
+
insertBeforeChapterId: identifier.optional(),
|
|
2475
|
+
numberTitle: z.boolean().optional()
|
|
2476
|
+
}).strict().refine((value) => value.insertAfterChapterId === undefined || value.insertBeforeChapterId === undefined, {
|
|
2477
|
+
message: "不能同时指定章节前后插入位置"
|
|
2478
|
+
}), request.body);
|
|
2442
2479
|
data(response, store.createChapter(request.params.workId, input), 201);
|
|
2443
2480
|
});
|
|
2444
2481
|
app.get("/api/works/:workId/deleted-chapters", (request, response) => {
|
|
@@ -2451,6 +2488,12 @@ export function createRuntime(options) {
|
|
|
2451
2488
|
data(response, store.getRecycleBin(request.params.workId));
|
|
2452
2489
|
});
|
|
2453
2490
|
app.get("/api/chapters/:chapterId", (request, response) => data(response, store.getChapter(request.params.chapterId)));
|
|
2491
|
+
app.post("/api/chapters/:chapterId/apply-title-number", (request, response) => {
|
|
2492
|
+
const input = parse(z.object({ title: nonEmpty.max(300), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
2493
|
+
const chapter = store.applyChapterTitleNumber(request.params.chapterId, input.title, input.expectedVersionNo);
|
|
2494
|
+
publishEditorChange(String(chapter.workId), String(chapter.id));
|
|
2495
|
+
data(response, chapter);
|
|
2496
|
+
});
|
|
2454
2497
|
app.patch("/api/chapters/:chapterId", (request, response) => {
|
|
2455
2498
|
const input = parse(z.object({ title: nonEmpty.max(300).optional(), content: z.string().max(2_000_000).optional(), lineIds: z.array(z.union([identifier, z.null()])).max(MAX_CHAPTER_LINE_IDS).optional(), excludedFromAnalysis: z.boolean().optional(), chapterType: chapterTypeSchema.optional(), source: z.enum(["manual", "auto"]).optional(), changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
2456
2499
|
const { source, changeNote, expectedVersionNo, ...chapterInput } = input;
|