@musnows/scriverse 0.5.4 → 0.5.6
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/dist/ai.js +837 -96
- package/dist/ai.js.map +1 -1
- package/dist/app.js +170 -58
- package/dist/app.js.map +1 -1
- package/dist/collaboration-presence.js +18 -7
- package/dist/collaboration-presence.js.map +1 -1
- package/dist/database.js +148 -0
- package/dist/database.js.map +1 -1
- package/dist/public/ai-usage.d.ts +20 -0
- package/dist/public/ai-usage.js +75 -0
- package/dist/public/app.js +1648 -116
- package/dist/public/background-task-center.d.ts +28 -0
- package/dist/public/background-task-center.js +30 -0
- package/dist/public/index.html +109 -5
- package/dist/public/page-route.js +2 -2
- package/dist/public/race-hierarchy.js +35 -0
- package/dist/public/styles.css +289 -10
- package/dist/public/theme-init.js +2 -2
- package/dist/relationship-search.js +8 -1
- package/dist/relationship-search.js.map +1 -1
- package/dist/store.js +560 -105
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +18 -3
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -27,7 +27,7 @@ import { accountReference, logger, sanitizeError } from "./logger.js";
|
|
|
27
27
|
import { currentRequestActor, runWithRequestActor } from "./request-context.js";
|
|
28
28
|
import { APP_VERSION } from "./version.js";
|
|
29
29
|
import { fullWorkModulePermissions, proseReplacementPermissionModules } from "./work-permissions.js";
|
|
30
|
-
import { CollaborationPresence,
|
|
30
|
+
import { CollaborationPresence, entityEditorPageKey, presencePageKinds } from "./collaboration-presence.js";
|
|
31
31
|
import { clearSessionCookie, createCliApiScopeMiddleware, createUserSessionMiddleware, createWorkAuthorizationMiddleware, relationshipAnalysisReadModules, setSessionCookie, UserAuthService } from "./user-auth.js";
|
|
32
32
|
const nonEmpty = z.string().trim().min(1);
|
|
33
33
|
const identifier = z.string().trim().min(1).max(200);
|
|
@@ -95,7 +95,7 @@ const presenceHeartbeatSchema = z.object({
|
|
|
95
95
|
z.object({ kind: z.literal(presencePageKinds[0]) }).strict(),
|
|
96
96
|
z.object({ kind: z.literal(presencePageKinds[1]), resourceId: identifier }).strict(),
|
|
97
97
|
z.object({ kind: z.literal(presencePageKinds[2]), module: z.enum(["settings", "characters", "races", "organizations", "timeline", "relationships", "outlines", "reviews", "tasks", "ai-settings"]) }).strict(),
|
|
98
|
-
z.object({ kind: z.literal(presencePageKinds[3]), module: z.enum(["setting", "character", "race", "organization"]), resourceId: identifier.optional() }).strict(),
|
|
98
|
+
z.object({ kind: z.literal(presencePageKinds[3]), module: z.enum(["setting", "character", "race", "organization", "relationship"]), resourceId: identifier.optional() }).strict(),
|
|
99
99
|
z.object({ kind: z.literal(presencePageKinds[4]) }).strict()
|
|
100
100
|
])
|
|
101
101
|
}).strict();
|
|
@@ -296,8 +296,18 @@ const modelSchema = z.object({
|
|
|
296
296
|
const aiPromptSchema = z.object({
|
|
297
297
|
systemPrompt: z.string().max(100_000).optional()
|
|
298
298
|
});
|
|
299
|
+
const aiUsageQuerySchema = z.object({
|
|
300
|
+
timezoneOffset: z.coerce.number().int().min(-840).max(840).default(0)
|
|
301
|
+
}).strict();
|
|
299
302
|
const platformPageSizesSchema = z.object({
|
|
303
|
+
settings: z.number().int().min(10).max(100).optional(),
|
|
300
304
|
characters: z.number().int().min(10).max(100).optional(),
|
|
305
|
+
races: z.number().int().min(10).max(100).optional(),
|
|
306
|
+
organizations: z.number().int().min(10).max(100).optional(),
|
|
307
|
+
timeline: z.number().int().min(10).max(100).optional(),
|
|
308
|
+
outlines: z.number().int().min(10).max(100).optional(),
|
|
309
|
+
relationships: z.number().int().min(10).max(100).optional(),
|
|
310
|
+
reviews: z.number().int().min(10).max(100).optional(),
|
|
301
311
|
analysisTasks: z.number().int().min(10).max(100).optional(),
|
|
302
312
|
fileVersions: z.number().int().min(10).max(100).optional()
|
|
303
313
|
}).strict();
|
|
@@ -358,12 +368,20 @@ const contextSchema = z.object({
|
|
|
358
368
|
includeBookSummary: z.boolean().optional()
|
|
359
369
|
});
|
|
360
370
|
const analysisTaskTypeSchema = z.enum(["structure", "chapter-analysis", "character-extraction", "character-summary", "character-identity-audit", "timeline-analysis", "worldview-analysis", "setting-extraction", "consistency-check", "report-update", "book-analysis"]);
|
|
371
|
+
const relationshipSourceRefSchema = z.object({
|
|
372
|
+
sourceType: z.string().trim().min(1).max(50).regex(/^[a-z][a-z-]*$/u),
|
|
373
|
+
sourceId: identifier,
|
|
374
|
+
sourceVersion: z.string().trim().min(1).max(200)
|
|
375
|
+
}).strict();
|
|
361
376
|
const relationshipAnalysisScopeSchema = z.object({
|
|
362
377
|
type: z.enum(["chapter", "book", "settings"]),
|
|
363
378
|
chapterId: identifier.optional(),
|
|
364
379
|
includeAllSettings: z.boolean().optional(),
|
|
365
380
|
additionalPrompt: z.string().trim().max(10_000).optional(),
|
|
366
381
|
characterIds: z.array(identifier).max(20).optional(),
|
|
382
|
+
preFilterRelationshipSources: z.boolean().optional(),
|
|
383
|
+
previewRelationshipChanges: z.boolean().optional(),
|
|
384
|
+
relationshipSourceRefs: z.array(relationshipSourceRefSchema).max(5_000).optional(),
|
|
367
385
|
replaceExistingRelationships: z.boolean().optional()
|
|
368
386
|
}).strict().superRefine((scope, context) => {
|
|
369
387
|
if (scope.type === "chapter" && !scope.chapterId) {
|
|
@@ -378,6 +396,18 @@ const relationshipAnalysisScopeSchema = z.object({
|
|
|
378
396
|
if (scope.replaceExistingRelationships && !scope.characterIds?.length) {
|
|
379
397
|
context.addIssue({ code: z.ZodIssueCode.custom, path: ["replaceExistingRelationships"], message: "覆盖已有关系前必须选择被分析角色" });
|
|
380
398
|
}
|
|
399
|
+
if (scope.preFilterRelationshipSources !== undefined && !scope.characterIds?.length) {
|
|
400
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["preFilterRelationshipSources"], message: "来源前置过滤仅支持定向人物关系分析" });
|
|
401
|
+
}
|
|
402
|
+
if (scope.relationshipSourceRefs !== undefined && !scope.characterIds?.length) {
|
|
403
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["relationshipSourceRefs"], message: "预检来源仅支持定向人物关系分析" });
|
|
404
|
+
}
|
|
405
|
+
if (scope.relationshipSourceRefs) {
|
|
406
|
+
const keys = scope.relationshipSourceRefs.map((ref) => `${ref.sourceType}:${ref.sourceId}`);
|
|
407
|
+
if (new Set(keys).size !== keys.length) {
|
|
408
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["relationshipSourceRefs"], message: "预检来源不能重复" });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
381
411
|
});
|
|
382
412
|
const analysisTaskSchema = z.union([
|
|
383
413
|
z.object({ taskType: z.literal("relationship-analysis"), scope: relationshipAnalysisScopeSchema.optional(), modelId: identifier.optional() }).strict(),
|
|
@@ -388,6 +418,15 @@ const analysisTaskSchema = z.union([
|
|
|
388
418
|
if (input.scope?.additionalPrompt !== undefined) {
|
|
389
419
|
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "additionalPrompt"], message: "额外分析提示仅支持人物关系分析" });
|
|
390
420
|
}
|
|
421
|
+
if (input.scope?.preFilterRelationshipSources !== undefined) {
|
|
422
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "preFilterRelationshipSources"], message: "来源前置过滤仅支持人物关系分析" });
|
|
423
|
+
}
|
|
424
|
+
if (input.scope?.previewRelationshipChanges !== undefined) {
|
|
425
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "previewRelationshipChanges"], message: "变更预览仅支持人物关系分析" });
|
|
426
|
+
}
|
|
427
|
+
if (input.scope?.relationshipSourceRefs !== undefined) {
|
|
428
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "relationshipSourceRefs"], message: "预检来源仅支持人物关系分析" });
|
|
429
|
+
}
|
|
391
430
|
if (input.scope?.characterIds !== undefined || input.scope?.replaceExistingRelationships !== undefined) {
|
|
392
431
|
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "characterIds"], message: "被分析角色仅支持人物关系分析" });
|
|
393
432
|
}
|
|
@@ -492,6 +531,11 @@ function redactTaskCharacterNames(record, permissions) {
|
|
|
492
531
|
return redactedRelationship;
|
|
493
532
|
});
|
|
494
533
|
}
|
|
534
|
+
const changePreview = recordValue(taskResult.relationshipChangePreview);
|
|
535
|
+
if (changePreview) {
|
|
536
|
+
const { operations: _operations, ...redactedChangePreview } = changePreview;
|
|
537
|
+
redactedTaskResult.relationshipChangePreview = redactedChangePreview;
|
|
538
|
+
}
|
|
495
539
|
const analysisTarget = recordValue(taskResult.analysisTarget);
|
|
496
540
|
if (analysisTarget) {
|
|
497
541
|
const { characterNames: _characterNames, ...redactedAnalysisTarget } = analysisTarget;
|
|
@@ -500,6 +544,14 @@ function redactTaskCharacterNames(record, permissions) {
|
|
|
500
544
|
result.result = redactedTaskResult;
|
|
501
545
|
}
|
|
502
546
|
}
|
|
547
|
+
if (permissions.relationships === "none") {
|
|
548
|
+
const taskResult = recordValue(result.result);
|
|
549
|
+
const changePreview = recordValue(taskResult?.relationshipChangePreview);
|
|
550
|
+
if (taskResult && changePreview) {
|
|
551
|
+
const { operations: _operations, ...redactedChangePreview } = changePreview;
|
|
552
|
+
result.result = { ...taskResult, relationshipChangePreview: redactedChangePreview };
|
|
553
|
+
}
|
|
554
|
+
}
|
|
503
555
|
const resultSummary = recordValue(result.resultSummary);
|
|
504
556
|
const characterSensitiveTask = ["character-extraction", "character-summary", "character-identity-audit", "relationship-analysis"]
|
|
505
557
|
.includes(String(result.taskType));
|
|
@@ -549,14 +601,14 @@ export function createRuntime(options) {
|
|
|
549
601
|
mkdirSync(attachmentStorage.temporaryDirectory, { recursive: true, mode: 0o700 });
|
|
550
602
|
const auth = new UserAuthService(database);
|
|
551
603
|
const collaborationPresence = new CollaborationPresence();
|
|
552
|
-
const
|
|
604
|
+
const publishRelationshipChange = (workId, relationshipId) => {
|
|
553
605
|
const actor = currentRequestActor();
|
|
554
|
-
if (!actor || !workId || !
|
|
606
|
+
if (!actor || !workId || !relationshipId)
|
|
555
607
|
return;
|
|
556
|
-
collaborationPresence.publishChange(workId,
|
|
608
|
+
collaborationPresence.publishChange(workId, entityEditorPageKey("relationship", relationshipId), {
|
|
557
609
|
userId: actor.userId,
|
|
558
610
|
displayName: actor.displayName
|
|
559
|
-
}
|
|
611
|
+
});
|
|
560
612
|
};
|
|
561
613
|
const getDevelopmentUser = () => options.devAuthBypass
|
|
562
614
|
? auth.listUsers().find((user) => user.status === "active") ?? null
|
|
@@ -941,19 +993,22 @@ export function createRuntime(options) {
|
|
|
941
993
|
const input = parse(z.object({ volumeId: identifier, title: nonEmpty.max(300), content: z.string().max(2_000_000).optional(), chapterType: chapterTypeSchema.optional() }), request.body);
|
|
942
994
|
data(response, store.createChapter(request.params.workId, input), 201);
|
|
943
995
|
});
|
|
996
|
+
app.get("/api/works/:workId/deleted-chapters", (request, response) => {
|
|
997
|
+
const pagination = parsePagination(request.query);
|
|
998
|
+
data(response, pagination
|
|
999
|
+
? store.listDeletedChaptersPage(request.params.workId, pagination)
|
|
1000
|
+
: store.listDeletedChapters(request.params.workId));
|
|
1001
|
+
});
|
|
944
1002
|
app.get("/api/chapters/:chapterId", (request, response) => data(response, store.getChapter(request.params.chapterId)));
|
|
945
1003
|
app.patch("/api/chapters/:chapterId", (request, response) => {
|
|
946
1004
|
const input = parse(z.object({ title: nonEmpty.max(300).optional(), content: z.string().max(2_000_000).optional(), excludedFromAnalysis: z.boolean().optional(), chapterType: chapterTypeSchema.optional(), source: z.enum(["manual", "auto"]).optional(), changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
947
1005
|
const { source, changeNote, expectedVersionNo, ...chapterInput } = input;
|
|
948
1006
|
const chapter = store.saveChapter(request.params.chapterId, chapterInput, source ?? "manual", null, changeNote, expectedVersionNo);
|
|
949
|
-
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
950
1007
|
data(response, chapter);
|
|
951
1008
|
});
|
|
952
1009
|
app.delete("/api/chapters/:chapterId", (request, response) => {
|
|
953
1010
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
954
|
-
const chapter = store.getChapter(request.params.chapterId);
|
|
955
1011
|
store.deleteChapter(request.params.chapterId, input.expectedVersionNo);
|
|
956
|
-
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
957
1012
|
noContent(response);
|
|
958
1013
|
});
|
|
959
1014
|
app.get("/api/chapters/:chapterId/versions", (request, response) => {
|
|
@@ -964,10 +1019,29 @@ export function createRuntime(options) {
|
|
|
964
1019
|
const pagination = parsePagination(request.query);
|
|
965
1020
|
data(response, pagination ? store.listChapterInsightsPage(request.params.chapterId, pagination) : store.listChapterInsights(request.params.chapterId));
|
|
966
1021
|
});
|
|
1022
|
+
app.get("/api/chapters/:chapterId/annotations", (request, response) => data(response, store.listChapterAnnotations(request.params.chapterId)));
|
|
1023
|
+
app.post("/api/chapters/:chapterId/annotations", (request, response) => {
|
|
1024
|
+
const input = parse(z.object({
|
|
1025
|
+
kind: z.enum(["note", "todo"]),
|
|
1026
|
+
startLine: z.number().int().positive(),
|
|
1027
|
+
endLine: z.number().int().positive(),
|
|
1028
|
+
note: z.string().trim().min(1).max(2000)
|
|
1029
|
+
}).strict().refine((value) => value.endLine >= value.startLine, { message: "结束行不能早于开始行", path: ["endLine"] }), request.body);
|
|
1030
|
+
data(response, store.createChapterAnnotation(request.params.chapterId, input), 201);
|
|
1031
|
+
});
|
|
1032
|
+
app.patch("/api/chapter-annotations/:annotationId", (request, response) => {
|
|
1033
|
+
const input = parse(z.object({ note: z.string().trim().min(1).max(2000).optional(), status: z.enum(["open", "resolved"]).optional(), expectedVersionNo: expectedVersionNoSchema }).strict().refine((value) => value.note !== undefined || value.status !== undefined, { message: "至少需要修改一项" }), request.body);
|
|
1034
|
+
const { expectedVersionNo, ...update } = input;
|
|
1035
|
+
data(response, store.updateChapterAnnotation(request.params.annotationId, update, expectedVersionNo));
|
|
1036
|
+
});
|
|
1037
|
+
app.delete("/api/chapter-annotations/:annotationId", (request, response) => {
|
|
1038
|
+
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1039
|
+
store.deleteChapterAnnotation(request.params.annotationId, input.expectedVersionNo);
|
|
1040
|
+
noContent(response);
|
|
1041
|
+
});
|
|
967
1042
|
app.post("/api/chapters/:chapterId/restore", (request, response) => {
|
|
968
1043
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
969
1044
|
const chapter = store.restoreChapter(request.params.chapterId, input.versionNo, input.expectedVersionNo);
|
|
970
|
-
publishCollaborativeChange(String(chapter.workId), editorPageKey(String(chapter.id)));
|
|
971
1045
|
data(response, chapter);
|
|
972
1046
|
});
|
|
973
1047
|
app.post("/api/chapters/:chapterId/move", (request, response) => {
|
|
@@ -975,6 +1049,17 @@ export function createRuntime(options) {
|
|
|
975
1049
|
const { expectedVersionNo, ...moveInput } = input;
|
|
976
1050
|
data(response, store.moveChapter(request.params.chapterId, moveInput, expectedVersionNo));
|
|
977
1051
|
});
|
|
1052
|
+
app.post("/api/works/:workId/chapters/batch", (request, response) => {
|
|
1053
|
+
const selectedChapters = z.array(z.object({ id: identifier, expectedVersionNo: z.number().int().positive() }).strict()).min(1).max(200);
|
|
1054
|
+
const action = z.discriminatedUnion("type", [
|
|
1055
|
+
z.object({ type: z.literal("move"), volumeId: identifier }).strict(),
|
|
1056
|
+
z.object({ type: z.literal("setType"), chapterType: chapterTypeSchema }).strict(),
|
|
1057
|
+
z.object({ type: z.literal("setAnalysisExclusion"), excludedFromAnalysis: z.boolean() }).strict(),
|
|
1058
|
+
z.object({ type: z.literal("delete") }).strict()
|
|
1059
|
+
]);
|
|
1060
|
+
const input = parse(z.object({ chapters: selectedChapters, action }).strict(), request.body);
|
|
1061
|
+
data(response, store.batchManageChapters(request.params.workId, input.chapters, input.action));
|
|
1062
|
+
});
|
|
978
1063
|
app.get("/api/works/:workId/outlines", (request, response) => {
|
|
979
1064
|
const pagination = parsePagination(request.query);
|
|
980
1065
|
data(response, pagination ? store.listChapterOutlinesPage(request.params.workId, pagination) : store.listChapterOutlines(request.params.workId));
|
|
@@ -983,14 +1068,11 @@ export function createRuntime(options) {
|
|
|
983
1068
|
app.put("/api/chapters/:chapterId/outline", (request, response) => {
|
|
984
1069
|
const { changeNote, expectedVersionNo, ...input } = parse(chapterOutlineSchema.extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
985
1070
|
const outline = store.upsertChapterOutline(request.params.chapterId, input, "manual", null, changeNote, expectedVersionNo);
|
|
986
|
-
publishCollaborativeChange(String(outline.workId), modulePageKey("outlines"));
|
|
987
1071
|
data(response, outline);
|
|
988
1072
|
});
|
|
989
1073
|
app.delete("/api/chapters/:chapterId/outline", (request, response) => {
|
|
990
1074
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
991
|
-
const chapter = store.getChapter(request.params.chapterId);
|
|
992
1075
|
store.deleteChapterOutline(request.params.chapterId, input.expectedVersionNo);
|
|
993
|
-
publishCollaborativeChange(String(chapter.workId), modulePageKey("outlines"));
|
|
994
1076
|
noContent(response);
|
|
995
1077
|
});
|
|
996
1078
|
app.get("/api/works/:workId/foreshadows", (request, response) => {
|
|
@@ -1005,42 +1087,34 @@ export function createRuntime(options) {
|
|
|
1005
1087
|
});
|
|
1006
1088
|
app.post("/api/works/:workId/foreshadows", (request, response) => {
|
|
1007
1089
|
const foreshadow = store.createForeshadow(request.params.workId, parse(foreshadowSchema, request.body));
|
|
1008
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("outlines"));
|
|
1009
1090
|
data(response, foreshadow, 201);
|
|
1010
1091
|
});
|
|
1011
1092
|
app.get("/api/foreshadows/:foreshadowId", (request, response) => data(response, store.getForeshadow(request.params.foreshadowId)));
|
|
1012
1093
|
app.patch("/api/foreshadows/:foreshadowId", (request, response) => {
|
|
1013
1094
|
const { changeNote, expectedVersionNo, ...input } = parse(foreshadowSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1014
1095
|
const foreshadow = store.updateForeshadow(request.params.foreshadowId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1015
|
-
publishCollaborativeChange(String(foreshadow.workId), modulePageKey("outlines"));
|
|
1016
1096
|
data(response, foreshadow);
|
|
1017
1097
|
});
|
|
1018
1098
|
app.delete("/api/foreshadows/:foreshadowId", (request, response) => {
|
|
1019
1099
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1020
|
-
const foreshadow = store.getForeshadow(request.params.foreshadowId);
|
|
1021
1100
|
store.deleteForeshadow(request.params.foreshadowId, input.expectedVersionNo);
|
|
1022
|
-
publishCollaborativeChange(String(foreshadow.workId), modulePageKey("outlines"));
|
|
1023
1101
|
noContent(response);
|
|
1024
1102
|
});
|
|
1025
1103
|
app.post("/api/foreshadows/:foreshadowId/occurrences", (request, response) => {
|
|
1026
1104
|
const input = parse(foreshadowOccurrenceSchema.extend({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1027
1105
|
const { expectedVersionNo, ...occurrenceInput } = input;
|
|
1028
1106
|
const occurrence = store.createForeshadowOccurrence(request.params.foreshadowId, occurrenceInput, expectedVersionNo);
|
|
1029
|
-
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
1030
1107
|
data(response, occurrence, 201);
|
|
1031
1108
|
});
|
|
1032
1109
|
app.patch("/api/foreshadow-occurrences/:occurrenceId", (request, response) => {
|
|
1033
1110
|
const input = parse(foreshadowOccurrenceSchema.partial().extend({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1034
1111
|
const { expectedVersionNo, ...occurrenceInput } = input;
|
|
1035
1112
|
const occurrence = store.updateForeshadowOccurrence(request.params.occurrenceId, occurrenceInput, expectedVersionNo);
|
|
1036
|
-
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
1037
1113
|
data(response, occurrence);
|
|
1038
1114
|
});
|
|
1039
1115
|
app.delete("/api/foreshadow-occurrences/:occurrenceId", (request, response) => {
|
|
1040
1116
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1041
|
-
const occurrence = store.getForeshadowOccurrence(request.params.occurrenceId);
|
|
1042
1117
|
store.deleteForeshadowOccurrence(request.params.occurrenceId, input.expectedVersionNo);
|
|
1043
|
-
publishCollaborativeChange(String(occurrence.workId), modulePageKey("outlines"));
|
|
1044
1118
|
noContent(response);
|
|
1045
1119
|
});
|
|
1046
1120
|
app.get("/api/works/:workId/settings", (request, response) => {
|
|
@@ -1050,7 +1124,6 @@ export function createRuntime(options) {
|
|
|
1050
1124
|
});
|
|
1051
1125
|
app.post("/api/works/:workId/settings", (request, response) => {
|
|
1052
1126
|
const setting = store.createSetting(request.params.workId, parse(settingSchema, request.body));
|
|
1053
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("settings"));
|
|
1054
1127
|
data(response, setting, 201);
|
|
1055
1128
|
});
|
|
1056
1129
|
app.get("/api/works/:workId/settings/context", (request, response) => data(response, store.listSettings(request.params.workId, true)));
|
|
@@ -1058,14 +1131,11 @@ export function createRuntime(options) {
|
|
|
1058
1131
|
app.patch("/api/settings/:settingId", (request, response) => {
|
|
1059
1132
|
const { changeNote, expectedVersionNo, ...input } = parse(settingSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1060
1133
|
const setting = store.updateSetting(request.params.settingId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1061
|
-
publishCollaborativeChange(String(setting.workId), entityEditorPageKey("setting", String(setting.id)));
|
|
1062
1134
|
data(response, setting);
|
|
1063
1135
|
});
|
|
1064
1136
|
app.delete("/api/settings/:settingId", (request, response) => {
|
|
1065
1137
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1066
|
-
const setting = store.getSetting(request.params.settingId);
|
|
1067
1138
|
store.deleteSetting(request.params.settingId, input.expectedVersionNo);
|
|
1068
|
-
publishCollaborativeChange(String(setting.workId), entityEditorPageKey("setting", String(setting.id)));
|
|
1069
1139
|
noContent(response);
|
|
1070
1140
|
});
|
|
1071
1141
|
app.get("/api/works/:workId/characters", (request, response) => {
|
|
@@ -1083,7 +1153,6 @@ export function createRuntime(options) {
|
|
|
1083
1153
|
});
|
|
1084
1154
|
app.post("/api/works/:workId/characters", (request, response) => {
|
|
1085
1155
|
const character = store.createCharacter(request.params.workId, parse(characterSchema, request.body));
|
|
1086
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("characters"));
|
|
1087
1156
|
data(response, redactCharacterLinks(character, requestPermissions(request, request.params.workId)), 201);
|
|
1088
1157
|
});
|
|
1089
1158
|
app.get("/api/characters/:characterId", (request, response) => {
|
|
@@ -1092,7 +1161,6 @@ export function createRuntime(options) {
|
|
|
1092
1161
|
app.patch("/api/characters/:characterId", (request, response) => {
|
|
1093
1162
|
const { changeNote, expectedVersionNo, ...input } = parse(characterUpdateSchema.extend({ expectedVersionNo: expectedVersionNoSchema }), request.body);
|
|
1094
1163
|
const character = store.updateCharacter(request.params.characterId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1095
|
-
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
1096
1164
|
data(response, redactCharacterLinks(character, requestPermissions(request)));
|
|
1097
1165
|
});
|
|
1098
1166
|
app.get("/api/characters/:characterId/versions", (request, response) => {
|
|
@@ -1104,14 +1172,11 @@ export function createRuntime(options) {
|
|
|
1104
1172
|
app.post("/api/characters/:characterId/restore", (request, response) => {
|
|
1105
1173
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1106
1174
|
const character = store.restoreCharacter(request.params.characterId, input.versionNo, input.expectedVersionNo);
|
|
1107
|
-
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
1108
1175
|
data(response, redactCharacterLinks(character, requestPermissions(request)));
|
|
1109
1176
|
});
|
|
1110
1177
|
app.delete("/api/characters/:characterId", (request, response) => {
|
|
1111
1178
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1112
|
-
const character = store.getCharacter(request.params.characterId);
|
|
1113
1179
|
store.deleteCharacter(request.params.characterId, input.expectedVersionNo);
|
|
1114
|
-
publishCollaborativeChange(String(character.workId), entityEditorPageKey("character", String(character.id)));
|
|
1115
1180
|
noContent(response);
|
|
1116
1181
|
});
|
|
1117
1182
|
app.post("/api/characters/:characterId/merge", (request, response) => {
|
|
@@ -1136,7 +1201,6 @@ export function createRuntime(options) {
|
|
|
1136
1201
|
});
|
|
1137
1202
|
app.post("/api/characters/:characterId/sections", (request, response) => {
|
|
1138
1203
|
const section = store.createCharacterProfileSection(request.params.characterId, parse(characterProfileSectionSchema, request.body));
|
|
1139
|
-
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1140
1204
|
data(response, section, 201);
|
|
1141
1205
|
});
|
|
1142
1206
|
app.get("/api/character-sections/:sectionId", (request, response) => {
|
|
@@ -1145,14 +1209,11 @@ export function createRuntime(options) {
|
|
|
1145
1209
|
app.patch("/api/character-sections/:sectionId", (request, response) => {
|
|
1146
1210
|
const { changeNote, expectedVersionNo, ...input } = parse(characterProfileSectionSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1147
1211
|
const section = store.updateCharacterProfileSection(request.params.sectionId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1148
|
-
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1149
1212
|
data(response, section);
|
|
1150
1213
|
});
|
|
1151
1214
|
app.delete("/api/character-sections/:sectionId", (request, response) => {
|
|
1152
1215
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1153
|
-
const section = store.getCharacterProfileSection(request.params.sectionId);
|
|
1154
1216
|
store.deleteCharacterProfileSection(request.params.sectionId, input.expectedVersionNo);
|
|
1155
|
-
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1156
1217
|
noContent(response);
|
|
1157
1218
|
});
|
|
1158
1219
|
app.get("/api/character-sections/:sectionId/versions", (request, response) => {
|
|
@@ -1164,7 +1225,6 @@ export function createRuntime(options) {
|
|
|
1164
1225
|
app.post("/api/character-sections/:sectionId/restore", (request, response) => {
|
|
1165
1226
|
const input = parse(z.object({ versionNo: z.number().int().positive(), expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1166
1227
|
const section = store.restoreCharacterProfileSection(request.params.sectionId, input.versionNo, input.expectedVersionNo);
|
|
1167
|
-
publishCollaborativeChange(String(section.workId), entityEditorPageKey("character", String(section.characterId)));
|
|
1168
1228
|
data(response, section);
|
|
1169
1229
|
});
|
|
1170
1230
|
app.get("/api/works/:workId/attachments", (request, response) => {
|
|
@@ -1221,7 +1281,6 @@ export function createRuntime(options) {
|
|
|
1221
1281
|
});
|
|
1222
1282
|
app.post("/api/works/:workId/races", (request, response) => {
|
|
1223
1283
|
const race = store.createRace(request.params.workId, parse(raceSchema, request.body));
|
|
1224
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("races"));
|
|
1225
1284
|
data(response, redactRaceMembers(race, requestPermissions(request, request.params.workId)), 201);
|
|
1226
1285
|
});
|
|
1227
1286
|
app.get("/api/races/:raceId", (request, response) => {
|
|
@@ -1230,14 +1289,11 @@ export function createRuntime(options) {
|
|
|
1230
1289
|
app.patch("/api/races/:raceId", (request, response) => {
|
|
1231
1290
|
const { changeNote, expectedVersionNo, ...input } = parse(raceSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1232
1291
|
const race = store.updateRace(request.params.raceId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1233
|
-
publishCollaborativeChange(String(race.workId), entityEditorPageKey("race", String(race.id)));
|
|
1234
1292
|
data(response, redactRaceMembers(race, requestPermissions(request)));
|
|
1235
1293
|
});
|
|
1236
1294
|
app.delete("/api/races/:raceId", (request, response) => {
|
|
1237
1295
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1238
|
-
const race = store.getRace(request.params.raceId);
|
|
1239
1296
|
store.deleteRace(request.params.raceId, input.expectedVersionNo);
|
|
1240
|
-
publishCollaborativeChange(String(race.workId), entityEditorPageKey("race", String(race.id)));
|
|
1241
1297
|
noContent(response);
|
|
1242
1298
|
});
|
|
1243
1299
|
app.post("/api/races/:raceId/merge", (request, response) => {
|
|
@@ -1255,7 +1311,6 @@ export function createRuntime(options) {
|
|
|
1255
1311
|
});
|
|
1256
1312
|
app.post("/api/works/:workId/organizations", (request, response) => {
|
|
1257
1313
|
const organization = store.createOrganization(request.params.workId, parse(organizationSchema, request.body));
|
|
1258
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("organizations"));
|
|
1259
1314
|
data(response, redactOrganizationMembers(organization, requestPermissions(request, request.params.workId)), 201);
|
|
1260
1315
|
});
|
|
1261
1316
|
app.get("/api/organizations/:organizationId", (request, response) => {
|
|
@@ -1264,14 +1319,11 @@ export function createRuntime(options) {
|
|
|
1264
1319
|
app.patch("/api/organizations/:organizationId", (request, response) => {
|
|
1265
1320
|
const { changeNote, expectedVersionNo, ...input } = parse(organizationSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1266
1321
|
const organization = store.updateOrganization(request.params.organizationId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1267
|
-
publishCollaborativeChange(String(organization.workId), entityEditorPageKey("organization", String(organization.id)));
|
|
1268
1322
|
data(response, redactOrganizationMembers(organization, requestPermissions(request)));
|
|
1269
1323
|
});
|
|
1270
1324
|
app.delete("/api/organizations/:organizationId", (request, response) => {
|
|
1271
1325
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1272
|
-
const organization = store.getOrganization(request.params.organizationId);
|
|
1273
1326
|
store.deleteOrganization(request.params.organizationId, input.expectedVersionNo);
|
|
1274
|
-
publishCollaborativeChange(String(organization.workId), entityEditorPageKey("organization", String(organization.id)));
|
|
1275
1327
|
noContent(response);
|
|
1276
1328
|
});
|
|
1277
1329
|
app.post("/api/organizations/:organizationId/merge", (request, response) => {
|
|
@@ -1286,21 +1338,17 @@ export function createRuntime(options) {
|
|
|
1286
1338
|
});
|
|
1287
1339
|
app.post("/api/works/:workId/timeline-tracks", (request, response) => {
|
|
1288
1340
|
const track = store.createTimelineTrack(request.params.workId, parse(timelineTrackSchema, request.body));
|
|
1289
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1290
1341
|
data(response, track, 201);
|
|
1291
1342
|
});
|
|
1292
1343
|
app.get("/api/timeline-tracks/:trackId", (request, response) => data(response, store.getTimelineTrack(request.params.trackId)));
|
|
1293
1344
|
app.patch("/api/timeline-tracks/:trackId", (request, response) => {
|
|
1294
1345
|
const { changeNote, expectedVersionNo, ...input } = parse(timelineTrackSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1295
1346
|
const track = store.updateTimelineTrack(request.params.trackId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1296
|
-
publishCollaborativeChange(String(track.workId), modulePageKey("timeline"));
|
|
1297
1347
|
data(response, track);
|
|
1298
1348
|
});
|
|
1299
1349
|
app.delete("/api/timeline-tracks/:trackId", (request, response) => {
|
|
1300
1350
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1301
|
-
const track = store.getTimelineTrack(request.params.trackId);
|
|
1302
1351
|
store.deleteTimelineTrack(request.params.trackId, input.expectedVersionNo);
|
|
1303
|
-
publishCollaborativeChange(String(track.workId), modulePageKey("timeline"));
|
|
1304
1352
|
noContent(response);
|
|
1305
1353
|
});
|
|
1306
1354
|
app.get("/api/works/:workId/timeline", (request, response) => {
|
|
@@ -1309,7 +1357,6 @@ export function createRuntime(options) {
|
|
|
1309
1357
|
});
|
|
1310
1358
|
app.post("/api/works/:workId/timeline", (request, response) => {
|
|
1311
1359
|
const event = store.createTimelineEvent(request.params.workId, parse(timelineSchema, request.body));
|
|
1312
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1313
1360
|
data(response, event, 201);
|
|
1314
1361
|
});
|
|
1315
1362
|
app.post("/api/works/:workId/timeline/merge", (request, response) => {
|
|
@@ -1323,14 +1370,12 @@ export function createRuntime(options) {
|
|
|
1323
1370
|
}).strict(), request.body);
|
|
1324
1371
|
const { expectedVersionNos, ...mergeInput } = input;
|
|
1325
1372
|
const merged = store.mergeTimelineEvents(request.params.workId, input.eventIds, mergeInput, expectedVersionNos);
|
|
1326
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("timeline"));
|
|
1327
1373
|
data(response, merged, 201);
|
|
1328
1374
|
});
|
|
1329
1375
|
app.get("/api/timeline/:eventId", (request, response) => data(response, store.getTimelineEvent(request.params.eventId)));
|
|
1330
1376
|
app.patch("/api/timeline/:eventId", (request, response) => {
|
|
1331
1377
|
const { changeNote, expectedVersionNo, ...input } = parse(timelineSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1332
1378
|
const event = store.updateTimelineEvent(request.params.eventId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1333
|
-
publishCollaborativeChange(String(event.workId), modulePageKey("timeline"));
|
|
1334
1379
|
data(response, event);
|
|
1335
1380
|
});
|
|
1336
1381
|
app.post("/api/timeline/:eventId/split", (request, response) => {
|
|
@@ -1344,16 +1389,11 @@ export function createRuntime(options) {
|
|
|
1344
1389
|
expectedVersionNo: expectedVersionNoSchema
|
|
1345
1390
|
}).strict(), request.body);
|
|
1346
1391
|
const split = store.splitTimelineEvent(request.params.eventId, input.parts, input.expectedVersionNo);
|
|
1347
|
-
const first = split[0];
|
|
1348
|
-
if (first)
|
|
1349
|
-
publishCollaborativeChange(String(first.workId), modulePageKey("timeline"));
|
|
1350
1392
|
data(response, split, 201);
|
|
1351
1393
|
});
|
|
1352
1394
|
app.delete("/api/timeline/:eventId", (request, response) => {
|
|
1353
1395
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1354
|
-
const event = store.getTimelineEvent(request.params.eventId);
|
|
1355
1396
|
store.deleteTimelineEvent(request.params.eventId, input.expectedVersionNo);
|
|
1356
|
-
publishCollaborativeChange(String(event.workId), modulePageKey("timeline"));
|
|
1357
1397
|
noContent(response);
|
|
1358
1398
|
});
|
|
1359
1399
|
app.get("/api/works/:workId/relationships", (request, response) => {
|
|
@@ -1367,21 +1407,20 @@ export function createRuntime(options) {
|
|
|
1367
1407
|
});
|
|
1368
1408
|
app.post("/api/works/:workId/relationships", (request, response) => {
|
|
1369
1409
|
const relationship = store.createRelationship(request.params.workId, parse(relationshipSchema, request.body));
|
|
1370
|
-
publishCollaborativeChange(request.params.workId, modulePageKey("relationships"));
|
|
1371
1410
|
data(response, relationship, 201);
|
|
1372
1411
|
});
|
|
1373
1412
|
app.get("/api/relationships/:relationshipId", (request, response) => data(response, store.getRelationship(request.params.relationshipId)));
|
|
1374
1413
|
app.patch("/api/relationships/:relationshipId", (request, response) => {
|
|
1375
1414
|
const { changeNote, expectedVersionNo, ...input } = parse(relationshipSchema.partial().extend({ changeNote: changeNoteSchema, expectedVersionNo: expectedVersionNoSchema }).strict(), request.body);
|
|
1376
1415
|
const relationship = store.updateRelationship(request.params.relationshipId, input, "manual", null, changeNote, expectedVersionNo);
|
|
1377
|
-
|
|
1416
|
+
publishRelationshipChange(String(relationship.workId), String(relationship.id));
|
|
1378
1417
|
data(response, relationship);
|
|
1379
1418
|
});
|
|
1380
1419
|
app.delete("/api/relationships/:relationshipId", (request, response) => {
|
|
1381
1420
|
const input = parse(z.object({ expectedVersionNo: expectedVersionNoSchema }).strict(), request.body ?? {});
|
|
1382
1421
|
const relationship = store.getRelationship(request.params.relationshipId);
|
|
1383
1422
|
store.deleteRelationship(request.params.relationshipId, input.expectedVersionNo);
|
|
1384
|
-
|
|
1423
|
+
publishRelationshipChange(String(relationship.workId), String(relationship.id));
|
|
1385
1424
|
noContent(response);
|
|
1386
1425
|
});
|
|
1387
1426
|
app.get("/api/entity-versions/:entityType/:entityId", (request, response) => {
|
|
@@ -1434,6 +1473,20 @@ export function createRuntime(options) {
|
|
|
1434
1473
|
const permissions = requestPermissions(request, request.params.workId);
|
|
1435
1474
|
data(response, mapRecords(store.listTaskSummariesPage(request.params.workId, parsePagination(request.query) ?? { page: 1, limit: 30, offset: 0 }), (task) => redactTaskCharacterNames(task, permissions)));
|
|
1436
1475
|
});
|
|
1476
|
+
app.post("/api/works/:workId/tasks/relationship-source-preview", async (request, response) => {
|
|
1477
|
+
const input = parse(z.object({
|
|
1478
|
+
scope: relationshipAnalysisScopeSchema,
|
|
1479
|
+
modelId: identifier.optional()
|
|
1480
|
+
}).strict(), request.body);
|
|
1481
|
+
const permissions = requestPermissions(request, request.params.workId);
|
|
1482
|
+
const deniedModules = relationshipAnalysisReadModules(input.scope).filter((module) => permissions[module] === "none");
|
|
1483
|
+
if (deniedModules.length > 0) {
|
|
1484
|
+
throw new AppError(403, "WORK_MODULE_READ_DENIED", "你没有读取人物关系来源预检所需资料模块的权限", {
|
|
1485
|
+
modules: deniedModules
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
data(response, await ai.previewRelationshipSources(request.params.workId, input.scope, input.modelId));
|
|
1489
|
+
});
|
|
1437
1490
|
app.post("/api/works/:workId/tasks", (request, response) => {
|
|
1438
1491
|
const input = parse(analysisTaskSchema, request.body);
|
|
1439
1492
|
data(response, redactTaskCharacterNames(ai.createTask(request.params.workId, input), requestPermissions(request, request.params.workId)), 201);
|
|
@@ -1485,7 +1538,30 @@ export function createRuntime(options) {
|
|
|
1485
1538
|
allowAdminAccess: request.authMethod !== "api-key"
|
|
1486
1539
|
} : undefined), requestPermissions(request)));
|
|
1487
1540
|
});
|
|
1541
|
+
app.post("/api/tasks/:taskId/rerun", (request, response) => {
|
|
1542
|
+
parse(z.object({}).strict(), request.body ?? {});
|
|
1543
|
+
const task = store.getTask(request.params.taskId);
|
|
1544
|
+
if (task.taskType === "relationship-analysis") {
|
|
1545
|
+
const permissions = requestPermissions(request, String(task.workId));
|
|
1546
|
+
const deniedModules = relationshipAnalysisReadModules(task.scope).filter((module) => permissions[module] === "none");
|
|
1547
|
+
if (deniedModules.length > 0) {
|
|
1548
|
+
throw new AppError(403, "WORK_MODULE_READ_DENIED", "你没有读取本次定向人物关系分析所需资料模块的权限", {
|
|
1549
|
+
modules: deniedModules
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
data(response, redactTaskCharacterNames(ai.rerunTask(request.params.taskId), requestPermissions(request)), 201);
|
|
1554
|
+
});
|
|
1488
1555
|
app.post("/api/tasks/:taskId/cancel", (request, response) => data(response, redactTaskCharacterNames(ai.cancelTask(request.params.taskId), requestPermissions(request))));
|
|
1556
|
+
app.post("/api/tasks/:taskId/relationship-changes/apply", (request, response) => {
|
|
1557
|
+
parse(z.object({}).strict(), request.body ?? {});
|
|
1558
|
+
const applied = ai.applyRelationshipChangePreview(request.params.taskId);
|
|
1559
|
+
data(response, redactTaskCharacterNames(applied, requestPermissions(request)));
|
|
1560
|
+
});
|
|
1561
|
+
app.post("/api/tasks/:taskId/relationship-changes/discard", (request, response) => {
|
|
1562
|
+
parse(z.object({}).strict(), request.body ?? {});
|
|
1563
|
+
data(response, redactTaskCharacterNames(ai.discardRelationshipChangePreview(request.params.taskId), requestPermissions(request)));
|
|
1564
|
+
});
|
|
1489
1565
|
app.get("/api/platform/ai/providers", (request, response) => {
|
|
1490
1566
|
const pagination = parsePagination(request.query);
|
|
1491
1567
|
data(response, pagination ? ai.listProvidersPage(pagination) : ai.listProviders());
|
|
@@ -1497,12 +1573,39 @@ export function createRuntime(options) {
|
|
|
1497
1573
|
});
|
|
1498
1574
|
app.get("/api/platform/ai/settings", (_request, response) => data(response, store.getPlatformAiSettings()));
|
|
1499
1575
|
app.patch("/api/platform/ai/settings", (request, response) => data(response, store.updatePlatformAiSettings(parse(aiPromptSchema, request.body))));
|
|
1576
|
+
app.get("/api/platform/ai/usage", (request, response) => {
|
|
1577
|
+
const query = parse(aiUsageQuerySchema, request.query);
|
|
1578
|
+
data(response, ai.getPlatformTokenUsage(query.timezoneOffset));
|
|
1579
|
+
});
|
|
1500
1580
|
app.get("/api/ui-settings", (_request, response) => data(response, store.getPlatformUiSettings()));
|
|
1501
1581
|
app.get("/api/platform/ui-settings", (_request, response) => data(response, store.getPlatformUiSettings()));
|
|
1502
1582
|
app.patch("/api/platform/ui-settings", (request, response) => {
|
|
1503
1583
|
data(response, store.updatePlatformUiSettings(parse(platformUiSettingsSchema, request.body)));
|
|
1504
1584
|
});
|
|
1505
1585
|
app.get("/api/works/:workId/ai-settings", (request, response) => data(response, store.getWorkAiSettings(request.params.workId)));
|
|
1586
|
+
app.get("/api/works/:workId/ai-settings/usage", (request, response) => {
|
|
1587
|
+
const query = parse(aiUsageQuerySchema, request.query);
|
|
1588
|
+
data(response, ai.getWorkTokenUsage(request.params.workId, query.timezoneOffset));
|
|
1589
|
+
});
|
|
1590
|
+
app.get("/api/works/:workId/ai-settings/relationship-search-index", (request, response) => {
|
|
1591
|
+
data(response, ai.getRelationshipSearchIndexStatus(request.params.workId));
|
|
1592
|
+
});
|
|
1593
|
+
app.post("/api/works/:workId/ai-settings/relationship-search-index/sync", (request, response) => {
|
|
1594
|
+
const workId = request.params.workId;
|
|
1595
|
+
const result = ai.syncRelationshipSearchIndex(workId);
|
|
1596
|
+
store.audit(workId, "relationship.search-index.incremental-sync-queued", "work-ai-settings", workId, {
|
|
1597
|
+
queuedSourceCount: result.queuedSourceCount
|
|
1598
|
+
});
|
|
1599
|
+
data(response, result, 202);
|
|
1600
|
+
});
|
|
1601
|
+
app.post("/api/works/:workId/ai-settings/relationship-search-index/rebuild", (request, response) => {
|
|
1602
|
+
const workId = request.params.workId;
|
|
1603
|
+
const result = ai.rebuildRelationshipSearchIndex(workId);
|
|
1604
|
+
store.audit(workId, "relationship.search-index.rebuild-queued", "work-ai-settings", workId, {
|
|
1605
|
+
queuedSourceCount: result.queuedSourceCount
|
|
1606
|
+
});
|
|
1607
|
+
data(response, result, 202);
|
|
1608
|
+
});
|
|
1506
1609
|
app.patch("/api/works/:workId/ai-settings", (request, response) => {
|
|
1507
1610
|
const workId = request.params.workId;
|
|
1508
1611
|
const before = store.getWorkAiSettings(workId);
|
|
@@ -1767,6 +1870,15 @@ export function createRuntime(options) {
|
|
|
1767
1870
|
const pagination = parsePagination(request.query);
|
|
1768
1871
|
data(response, pagination ? store.listAuditLogsPage(request.params.workId, pagination) : store.listAuditLogs(request.params.workId));
|
|
1769
1872
|
});
|
|
1873
|
+
app.get("/api/works/:workId/writing-progress", (request, response) => data(response, store.getWritingProgress(request.params.workId)));
|
|
1874
|
+
app.put("/api/works/:workId/writing-goal", (request, response) => {
|
|
1875
|
+
const input = parse(z.object({
|
|
1876
|
+
dailyGoal: z.number().int().min(0).max(1_000_000),
|
|
1877
|
+
targetTotal: z.number().int().min(0).max(100_000_000),
|
|
1878
|
+
deadline: z.string().date().nullable()
|
|
1879
|
+
}).strict(), request.body);
|
|
1880
|
+
data(response, store.updateWritingGoal(request.params.workId, input));
|
|
1881
|
+
});
|
|
1770
1882
|
if (options.serveUi ?? true) {
|
|
1771
1883
|
const publicPath = options.publicPath ?? join(process.cwd(), "src", "public");
|
|
1772
1884
|
// index.html 按登录态动态下发:未登录时注入 login-route 类,首帧直接渲染登录页;
|