@musnows/scriverse 0.3.6 → 0.3.8

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/app.js CHANGED
@@ -16,6 +16,7 @@ import { TASK_TYPES } from "./domain.js";
16
16
  import { AppError } from "./errors.js";
17
17
  import { applyImportFileHints, parseNovelText } from "./parser.js";
18
18
  import { Store, versionedEntityTypes } from "./store.js";
19
+ import { parsePagination } from "./pagination.js";
19
20
  import { normalizeUploadFileName } from "./utils.js";
20
21
  import { assertSafeAiEndpoint, createApiRateLimitMiddleware, createAuthenticationRateLimitMiddleware, createBasicAuthMiddleware, createSameOriginMiddleware, createSecurityHeadersMiddleware } from "./security.js";
21
22
  import { ImageCaptchaService } from "./image-captcha.js";
@@ -474,8 +475,15 @@ export function createRuntime(options) {
474
475
  });
475
476
  data(response, result);
476
477
  });
477
- app.get("/api/users", (_request, response) => data(response, auth.listUsers()));
478
- app.get("/api/users/directory", (request, response) => data(response, auth.directory(String(request.query.q ?? ""))));
478
+ app.get("/api/users", (request, response) => {
479
+ const pagination = parsePagination(request.query);
480
+ data(response, pagination ? auth.listUsersPage(pagination) : auth.listUsers());
481
+ });
482
+ app.get("/api/users/directory", (request, response) => {
483
+ const pagination = parsePagination(request.query);
484
+ const query = String(request.query.q ?? "");
485
+ data(response, pagination ? auth.directoryPage(query, pagination) : auth.directory(query));
486
+ });
479
487
  app.get("/api/user-avatars/:userId", (request, response) => {
480
488
  const avatar = auth.getAvatar(request.params.userId);
481
489
  response.setHeader("Content-Type", avatar.mimeType);
@@ -491,7 +499,10 @@ export function createRuntime(options) {
491
499
  store.audit(null, "user.updated", "user", updated.userId, { role: updated.role, status: updated.status });
492
500
  data(response, updated);
493
501
  });
494
- app.get("/api/works", (_request, response) => data(response, store.listWorks()));
502
+ app.get("/api/works", (request, response) => {
503
+ const pagination = parsePagination(request.query);
504
+ data(response, pagination ? store.listWorksPage(pagination) : store.listWorks());
505
+ });
495
506
  app.post("/api/works", (request, response) => data(response, store.createWork(parse(workSchema, request.body)), 201));
496
507
  app.post("/api/works/import", upload.single("file"), async (request, response) => {
497
508
  if (!request.file)
@@ -512,8 +523,14 @@ export function createRuntime(options) {
512
523
  });
513
524
  data(response, store.createImportedWork(input, originalFileName, extension.slice(1), parsedNovel), 201);
514
525
  });
515
- app.get("/api/works/:workId", (request, response) => data(response, store.getWorkDirectory(request.params.workId)));
516
- app.get("/api/works/:workId/members", (request, response) => data(response, auth.listMembers(request.params.workId)));
526
+ app.get("/api/works/:workId", (request, response) => {
527
+ const pagination = parsePagination(request.query);
528
+ data(response, pagination ? store.getWorkDirectoryPage(request.params.workId, pagination) : store.getWorkDirectory(request.params.workId));
529
+ });
530
+ app.get("/api/works/:workId/members", (request, response) => {
531
+ const pagination = parsePagination(request.query);
532
+ data(response, pagination ? auth.listMembersPage(request.params.workId, pagination) : auth.listMembers(request.params.workId));
533
+ });
517
534
  app.post("/api/works/:workId/members", (request, response) => {
518
535
  if (!request.authUser)
519
536
  throw new AppError(401, "AUTH_REQUIRED", "请先登录");
@@ -563,7 +580,10 @@ export function createRuntime(options) {
563
580
  store.deleteWorkCover(request.params.workId);
564
581
  noContent(response);
565
582
  });
566
- app.get("/api/works/:workId/file-versions", (request, response) => data(response, store.listFileVersions(request.params.workId)));
583
+ app.get("/api/works/:workId/file-versions", (request, response) => {
584
+ const pagination = parsePagination(request.query);
585
+ data(response, pagination ? store.listFileVersionsPage(request.params.workId, pagination) : store.listFileVersions(request.params.workId));
586
+ });
567
587
  app.post("/api/works/:workId/file-versions/:fileVersionId/restore", (request, response) => {
568
588
  data(response, store.restoreFileVersion(request.params.workId, request.params.fileVersionId));
569
589
  });
@@ -608,8 +628,14 @@ export function createRuntime(options) {
608
628
  store.deleteChapter(request.params.chapterId);
609
629
  noContent(response);
610
630
  });
611
- app.get("/api/chapters/:chapterId/versions", (request, response) => data(response, store.listChapterVersions(request.params.chapterId)));
612
- app.get("/api/chapters/:chapterId/insights", (request, response) => data(response, store.listChapterInsights(request.params.chapterId)));
631
+ app.get("/api/chapters/:chapterId/versions", (request, response) => {
632
+ const pagination = parsePagination(request.query);
633
+ data(response, pagination ? store.listChapterVersionsPage(request.params.chapterId, pagination) : store.listChapterVersions(request.params.chapterId));
634
+ });
635
+ app.get("/api/chapters/:chapterId/insights", (request, response) => {
636
+ const pagination = parsePagination(request.query);
637
+ data(response, pagination ? store.listChapterInsightsPage(request.params.chapterId, pagination) : store.listChapterInsights(request.params.chapterId));
638
+ });
613
639
  app.post("/api/chapters/:chapterId/restore", (request, response) => {
614
640
  const input = parse(z.object({ versionNo: z.number().int().positive() }), request.body);
615
641
  data(response, store.restoreChapter(request.params.chapterId, input.versionNo));
@@ -618,7 +644,10 @@ export function createRuntime(options) {
618
644
  const input = parse(z.object({ volumeId: identifier, sortOrder: z.number().int().min(0) }), request.body);
619
645
  data(response, store.moveChapter(request.params.chapterId, input));
620
646
  });
621
- app.get("/api/works/:workId/outlines", (request, response) => data(response, store.listChapterOutlines(request.params.workId)));
647
+ app.get("/api/works/:workId/outlines", (request, response) => {
648
+ const pagination = parsePagination(request.query);
649
+ data(response, pagination ? store.listChapterOutlinesPage(request.params.workId, pagination) : store.listChapterOutlines(request.params.workId));
650
+ });
622
651
  app.get("/api/chapters/:chapterId/outline", (request, response) => data(response, store.getChapterOutline(request.params.chapterId)));
623
652
  app.put("/api/chapters/:chapterId/outline", (request, response) => {
624
653
  const { changeNote, ...input } = parse(chapterOutlineSchema.extend({ changeNote: changeNoteSchema }), request.body);
@@ -633,7 +662,10 @@ export function createRuntime(options) {
633
662
  status: z.enum(["all", "unresolved", "resolved"]).default("all"),
634
663
  currentChapterId: identifier.optional()
635
664
  }), request.query);
636
- data(response, store.listForeshadows(request.params.workId, query.status, query.currentChapterId));
665
+ const pagination = parsePagination(request.query);
666
+ data(response, pagination
667
+ ? store.listForeshadowsPage(request.params.workId, pagination, query.status, query.currentChapterId)
668
+ : store.listForeshadows(request.params.workId, query.status, query.currentChapterId));
637
669
  });
638
670
  app.post("/api/works/:workId/foreshadows", (request, response) => {
639
671
  data(response, store.createForeshadow(request.params.workId, parse(foreshadowSchema, request.body)), 201);
@@ -657,7 +689,10 @@ export function createRuntime(options) {
657
689
  store.deleteForeshadowOccurrence(request.params.occurrenceId);
658
690
  noContent(response);
659
691
  });
660
- app.get("/api/works/:workId/settings", (request, response) => data(response, store.listSettings(request.params.workId)));
692
+ app.get("/api/works/:workId/settings", (request, response) => {
693
+ const pagination = parsePagination(request.query);
694
+ data(response, pagination ? store.listSettingsPage(request.params.workId, pagination) : store.listSettings(request.params.workId));
695
+ });
661
696
  app.post("/api/works/:workId/settings", (request, response) => data(response, store.createSetting(request.params.workId, parse(settingSchema, request.body)), 201));
662
697
  app.get("/api/settings/:settingId", (request, response) => data(response, store.getSetting(request.params.settingId)));
663
698
  app.patch("/api/settings/:settingId", (request, response) => {
@@ -673,7 +708,10 @@ export function createRuntime(options) {
673
708
  includeSections: z.enum(["true", "false"]).default("false"),
674
709
  includeMerged: z.enum(["0", "1"]).default("0")
675
710
  }), request.query);
676
- data(response, store.listCharacters(request.params.workId, includeSections === "true", includeMerged === "1"));
711
+ const pagination = parsePagination(request.query);
712
+ data(response, pagination
713
+ ? store.listCharactersPage(request.params.workId, pagination, includeSections === "true", includeMerged === "1")
714
+ : store.listCharacters(request.params.workId, includeSections === "true", includeMerged === "1"));
677
715
  });
678
716
  app.post("/api/works/:workId/characters", (request, response) => data(response, store.createCharacter(request.params.workId, parse(characterSchema, request.body)), 201));
679
717
  app.get("/api/characters/:characterId", (request, response) => data(response, store.getCharacter(request.params.characterId)));
@@ -681,7 +719,10 @@ export function createRuntime(options) {
681
719
  const { changeNote, ...input } = parse(characterUpdateSchema, request.body);
682
720
  data(response, store.updateCharacter(request.params.characterId, input, "manual", null, changeNote));
683
721
  });
684
- app.get("/api/characters/:characterId/versions", (request, response) => data(response, store.listCharacterVersions(request.params.characterId)));
722
+ app.get("/api/characters/:characterId/versions", (request, response) => {
723
+ const pagination = parsePagination(request.query);
724
+ data(response, pagination ? store.listCharacterVersionsPage(request.params.characterId, pagination) : store.listCharacterVersions(request.params.characterId));
725
+ });
685
726
  app.post("/api/characters/:characterId/restore", (request, response) => {
686
727
  const input = parse(z.object({ versionNo: z.number().int().positive() }), request.body);
687
728
  data(response, store.restoreCharacter(request.params.characterId, input.versionNo));
@@ -691,7 +732,10 @@ export function createRuntime(options) {
691
732
  noContent(response);
692
733
  });
693
734
  app.get("/api/characters/:characterId/sections", (request, response) => {
694
- data(response, store.listCharacterProfileSections(request.params.characterId));
735
+ const pagination = parsePagination(request.query);
736
+ data(response, pagination
737
+ ? store.listCharacterProfileSectionsPage(request.params.characterId, pagination)
738
+ : store.listCharacterProfileSections(request.params.characterId));
695
739
  });
696
740
  app.post("/api/characters/:characterId/sections", (request, response) => {
697
741
  data(response, store.createCharacterProfileSection(request.params.characterId, parse(characterProfileSectionSchema, request.body)), 201);
@@ -708,14 +752,18 @@ export function createRuntime(options) {
708
752
  noContent(response);
709
753
  });
710
754
  app.get("/api/character-sections/:sectionId/versions", (request, response) => {
711
- data(response, store.listCharacterProfileSectionVersions(request.params.sectionId));
755
+ const pagination = parsePagination(request.query);
756
+ data(response, pagination
757
+ ? store.listCharacterProfileSectionVersionsPage(request.params.sectionId, pagination)
758
+ : store.listCharacterProfileSectionVersions(request.params.sectionId));
712
759
  });
713
760
  app.post("/api/character-sections/:sectionId/restore", (request, response) => {
714
761
  const input = parse(z.object({ versionNo: z.number().int().positive() }).strict(), request.body);
715
762
  data(response, store.restoreCharacterProfileSection(request.params.sectionId, input.versionNo));
716
763
  });
717
764
  app.get("/api/works/:workId/attachments", (request, response) => {
718
- data(response, store.listAttachments(request.params.workId));
765
+ const pagination = parsePagination(request.query);
766
+ data(response, pagination ? store.listAttachmentsPage(request.params.workId, pagination) : store.listAttachments(request.params.workId));
719
767
  });
720
768
  app.post("/api/works/:workId/attachments", attachmentUpload.single("file"), async (request, response) => {
721
769
  if (!request.file)
@@ -758,7 +806,10 @@ export function createRuntime(options) {
758
806
  await attachmentStorage.remove(deleted.storageKey);
759
807
  noContent(response);
760
808
  });
761
- app.get("/api/works/:workId/races", (request, response) => data(response, store.listRaces(request.params.workId)));
809
+ app.get("/api/works/:workId/races", (request, response) => {
810
+ const pagination = parsePagination(request.query);
811
+ data(response, pagination ? store.listRacesPage(request.params.workId, pagination) : store.listRaces(request.params.workId));
812
+ });
762
813
  app.post("/api/works/:workId/races", (request, response) => {
763
814
  data(response, store.createRace(request.params.workId, parse(raceSchema, request.body)), 201);
764
815
  });
@@ -771,7 +822,10 @@ export function createRuntime(options) {
771
822
  store.deleteRace(request.params.raceId);
772
823
  noContent(response);
773
824
  });
774
- app.get("/api/works/:workId/organizations", (request, response) => data(response, store.listOrganizations(request.params.workId)));
825
+ app.get("/api/works/:workId/organizations", (request, response) => {
826
+ const pagination = parsePagination(request.query);
827
+ data(response, pagination ? store.listOrganizationsPage(request.params.workId, pagination) : store.listOrganizations(request.params.workId));
828
+ });
775
829
  app.post("/api/works/:workId/organizations", (request, response) => {
776
830
  data(response, store.createOrganization(request.params.workId, parse(organizationSchema, request.body)), 201);
777
831
  });
@@ -784,7 +838,10 @@ export function createRuntime(options) {
784
838
  store.deleteOrganization(request.params.organizationId);
785
839
  noContent(response);
786
840
  });
787
- app.get("/api/works/:workId/timeline-tracks", (request, response) => data(response, store.listTimelineTracks(request.params.workId)));
841
+ app.get("/api/works/:workId/timeline-tracks", (request, response) => {
842
+ const pagination = parsePagination(request.query);
843
+ data(response, pagination ? store.listTimelineTracksPage(request.params.workId, pagination) : store.listTimelineTracks(request.params.workId));
844
+ });
788
845
  app.post("/api/works/:workId/timeline-tracks", (request, response) => data(response, store.createTimelineTrack(request.params.workId, parse(timelineTrackSchema, request.body)), 201));
789
846
  app.get("/api/timeline-tracks/:trackId", (request, response) => data(response, store.getTimelineTrack(request.params.trackId)));
790
847
  app.patch("/api/timeline-tracks/:trackId", (request, response) => {
@@ -795,7 +852,10 @@ export function createRuntime(options) {
795
852
  store.deleteTimelineTrack(request.params.trackId);
796
853
  noContent(response);
797
854
  });
798
- app.get("/api/works/:workId/timeline", (request, response) => data(response, store.listTimelineEvents(request.params.workId)));
855
+ app.get("/api/works/:workId/timeline", (request, response) => {
856
+ const pagination = parsePagination(request.query);
857
+ data(response, pagination ? store.listTimelineEventsPage(request.params.workId, pagination) : store.listTimelineEvents(request.params.workId));
858
+ });
799
859
  app.post("/api/works/:workId/timeline", (request, response) => data(response, store.createTimelineEvent(request.params.workId, parse(timelineSchema, request.body)), 201));
800
860
  app.post("/api/works/:workId/timeline/merge", (request, response) => {
801
861
  const input = parse(z.object({
@@ -831,7 +891,10 @@ export function createRuntime(options) {
831
891
  const confidence = request.query.minimumConfidence ? Number(request.query.minimumConfidence) : 0;
832
892
  if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1)
833
893
  throw new AppError(400, "INVALID_CONFIDENCE", "置信度必须在 0 到 1 之间");
834
- data(response, store.listRelationships(request.params.workId, confidence));
894
+ const pagination = parsePagination(request.query);
895
+ data(response, pagination
896
+ ? store.listRelationshipsPage(request.params.workId, pagination, confidence)
897
+ : store.listRelationships(request.params.workId, confidence));
835
898
  });
836
899
  app.post("/api/works/:workId/relationships", (request, response) => data(response, store.createRelationship(request.params.workId, parse(relationshipSchema, request.body)), 201));
837
900
  app.get("/api/relationships/:relationshipId", (request, response) => data(response, store.getRelationship(request.params.relationshipId)));
@@ -845,7 +908,10 @@ export function createRuntime(options) {
845
908
  });
846
909
  app.get("/api/entity-versions/:entityType/:entityId", (request, response) => {
847
910
  const input = parse(z.object({ entityType: versionedEntityTypeSchema, entityId: identifier }), request.params);
848
- data(response, store.listEntityVersions(input.entityType, input.entityId));
911
+ const pagination = parsePagination(request.query);
912
+ data(response, pagination
913
+ ? store.listEntityVersionsPage(input.entityType, input.entityId, pagination)
914
+ : store.listEntityVersions(input.entityType, input.entityId));
849
915
  });
850
916
  app.post("/api/entity-versions/:entityType/:entityId/restore", (request, response) => {
851
917
  const params = parse(z.object({ entityType: versionedEntityTypeSchema, entityId: identifier }), request.params);
@@ -854,7 +920,8 @@ export function createRuntime(options) {
854
920
  });
855
921
  app.get("/api/works/:workId/reviews", (request, response) => {
856
922
  const status = typeof request.query.status === "string" ? request.query.status : undefined;
857
- data(response, store.listReviewItems(request.params.workId, status));
923
+ const pagination = parsePagination(request.query);
924
+ data(response, pagination ? store.listReviewItemsPage(request.params.workId, pagination, status) : store.listReviewItems(request.params.workId, status));
858
925
  });
859
926
  app.post("/api/works/:workId/reviews", (request, response) => data(response, store.createReviewItem(request.params.workId, parse(reviewSchema, request.body)), 201));
860
927
  app.patch("/api/reviews/:reviewId", (request, response) => data(response, store.updateReviewItem(request.params.reviewId, parse(reviewSchema.partial(), request.body))));
@@ -875,7 +942,10 @@ export function createRuntime(options) {
875
942
  }
876
943
  data(response, store.mergeCharacters({ reviewId: request.params.reviewId, ...input }));
877
944
  });
878
- app.get("/api/works/:workId/tasks", (request, response) => data(response, store.listTasks(request.params.workId)));
945
+ app.get("/api/works/:workId/tasks", (request, response) => {
946
+ const pagination = parsePagination(request.query);
947
+ data(response, pagination ? store.listTasksPage(request.params.workId, pagination) : store.listTasks(request.params.workId));
948
+ });
879
949
  app.post("/api/works/:workId/tasks", (request, response) => {
880
950
  const input = parse(z.object({ taskType: z.enum(["structure", "chapter-analysis", "character-extraction", "character-summary", "character-identity-audit", "timeline-analysis", "relationship-analysis", "worldview-analysis", "setting-extraction", "consistency-check", "report-update", "book-analysis"]), scope: jsonObject.optional() }), request.body);
881
951
  data(response, store.createTask(request.params.workId, input), 201);
@@ -889,9 +959,15 @@ export function createRuntime(options) {
889
959
  data(response, await ai.runTask(request.params.taskId, input.modelId));
890
960
  });
891
961
  app.post("/api/tasks/:taskId/cancel", (request, response) => data(response, ai.cancelTask(request.params.taskId)));
892
- app.get("/api/platform/ai/providers", (_request, response) => data(response, ai.listProviders()));
962
+ app.get("/api/platform/ai/providers", (request, response) => {
963
+ const pagination = parsePagination(request.query);
964
+ data(response, pagination ? ai.listProvidersPage(pagination) : ai.listProviders());
965
+ });
893
966
  app.post("/api/platform/ai/providers", (request, response) => data(response, ai.createProvider(parse(providerSchema, request.body)), 201));
894
- app.get("/api/platform/ai/models", (_request, response) => data(response, ai.listPlatformModels()));
967
+ app.get("/api/platform/ai/models", (request, response) => {
968
+ const pagination = parsePagination(request.query);
969
+ data(response, pagination ? ai.listPlatformModelsPage(pagination) : ai.listPlatformModels());
970
+ });
895
971
  app.get("/api/platform/ai/settings", (_request, response) => data(response, store.getPlatformAiSettings()));
896
972
  app.patch("/api/platform/ai/settings", (request, response) => data(response, store.updatePlatformAiSettings(parse(aiPromptSchema, request.body))));
897
973
  app.get("/api/ui-settings", (_request, response) => data(response, store.getPlatformUiSettings()));
@@ -911,12 +987,18 @@ export function createRuntime(options) {
911
987
  }
912
988
  data(response, updated);
913
989
  });
914
- app.get("/api/works/:workId/ai-conversations", (request, response) => data(response, store.listAiConversations(request.params.workId)));
990
+ app.get("/api/works/:workId/ai-conversations", (request, response) => {
991
+ const pagination = parsePagination(request.query);
992
+ data(response, pagination ? store.listAiConversationsPage(request.params.workId, pagination) : store.listAiConversations(request.params.workId));
993
+ });
915
994
  app.post("/api/works/:workId/ai-conversations", (request, response) => {
916
995
  const input = parse(z.object({ title: z.string().max(200).optional() }), request.body ?? {});
917
996
  data(response, store.createAiConversation(request.params.workId, input.title), 201);
918
997
  });
919
- app.get("/api/ai-conversations/:conversationId", (request, response) => data(response, store.getAiConversation(request.params.conversationId)));
998
+ app.get("/api/ai-conversations/:conversationId", (request, response) => {
999
+ const pagination = parsePagination(request.query);
1000
+ data(response, pagination ? store.getAiConversationPage(request.params.conversationId, pagination) : store.getAiConversation(request.params.conversationId));
1001
+ });
920
1002
  app.post("/api/ai-conversations/:conversationId/fork", (request, response) => {
921
1003
  const input = parse(z.object({ messageId: identifier, title: z.string().max(200).optional() }), request.body);
922
1004
  data(response, store.forkAiConversation(request.params.conversationId, input.messageId, input.title), 201);
@@ -997,7 +1079,10 @@ export function createRuntime(options) {
997
1079
  noContent(response);
998
1080
  });
999
1081
  app.post("/api/providers/:providerId/test", async (request, response) => data(response, await ai.testProvider(request.params.providerId)));
1000
- app.get("/api/providers/:providerId/models", (request, response) => data(response, ai.listModels(request.params.providerId)));
1082
+ app.get("/api/providers/:providerId/models", (request, response) => {
1083
+ const pagination = parsePagination(request.query);
1084
+ data(response, pagination ? ai.listModelsPage(request.params.providerId, pagination) : ai.listModels(request.params.providerId));
1085
+ });
1001
1086
  app.post("/api/providers/:providerId/models", (request, response) => data(response, ai.createModel(request.params.providerId, parse(modelSchema, request.body)), 201));
1002
1087
  app.get("/api/models/:modelId", (request, response) => data(response, ai.getModel(request.params.modelId)));
1003
1088
  app.patch("/api/models/:modelId", (request, response) => data(response, ai.updateModel(request.params.modelId, parse(modelSchema.partial(), request.body))));
@@ -1005,8 +1090,14 @@ export function createRuntime(options) {
1005
1090
  ai.deleteModel(request.params.modelId);
1006
1091
  noContent(response);
1007
1092
  });
1008
- app.get("/api/works/:workId/models", (request, response) => data(response, ai.listWorkModels(request.params.workId)));
1009
- app.get("/api/works/:workId/task-defaults", (request, response) => data(response, ai.listTaskDefaults(request.params.workId)));
1093
+ app.get("/api/works/:workId/models", (request, response) => {
1094
+ const pagination = parsePagination(request.query);
1095
+ data(response, pagination ? ai.listWorkModelsPage(request.params.workId, pagination) : ai.listWorkModels(request.params.workId));
1096
+ });
1097
+ app.get("/api/works/:workId/task-defaults", (request, response) => {
1098
+ const pagination = parsePagination(request.query);
1099
+ data(response, pagination ? ai.listTaskDefaultsPage(request.params.workId, pagination) : ai.listTaskDefaults(request.params.workId));
1100
+ });
1010
1101
  app.put("/api/works/:workId/task-defaults/:taskType", (request, response) => {
1011
1102
  const taskType = parse(z.enum(TASK_TYPES), request.params.taskType);
1012
1103
  const input = parse(z.object({ modelId: identifier }), request.body);
@@ -1014,7 +1105,8 @@ export function createRuntime(options) {
1014
1105
  });
1015
1106
  app.get("/api/works/:workId/suggestions", (request, response) => {
1016
1107
  const status = typeof request.query.status === "string" ? request.query.status : undefined;
1017
- data(response, ai.listSuggestions(request.params.workId, status));
1108
+ const pagination = parsePagination(request.query);
1109
+ data(response, pagination ? ai.listSuggestionsPage(request.params.workId, pagination, status) : ai.listSuggestions(request.params.workId, status));
1018
1110
  });
1019
1111
  app.post("/api/works/:workId/suggestions", async (request, response) => {
1020
1112
  const input = parse(z.object({
@@ -1109,7 +1201,10 @@ export function createRuntime(options) {
1109
1201
  });
1110
1202
  app.get("/api/suggestions/:suggestionId", (request, response) => data(response, ai.getSuggestion(request.params.suggestionId)));
1111
1203
  app.get("/api/suggestions/:suggestionId/guards", (request, response) => {
1112
- data(response, store.listContinuationGuards(request.params.suggestionId));
1204
+ const pagination = parsePagination(request.query);
1205
+ data(response, pagination
1206
+ ? store.listContinuationGuardsPage(request.params.suggestionId, pagination)
1207
+ : store.listContinuationGuards(request.params.suggestionId));
1113
1208
  });
1114
1209
  app.post("/api/suggestions/:suggestionId/guard", async (request, response) => {
1115
1210
  const input = parse(z.object({ content: z.string().max(2_000_000).optional() }), request.body ?? {});
@@ -1120,7 +1215,10 @@ export function createRuntime(options) {
1120
1215
  data(response, ai.acceptSuggestion(request.params.suggestionId, input.content));
1121
1216
  });
1122
1217
  app.post("/api/suggestions/:suggestionId/reject", (request, response) => data(response, ai.rejectSuggestion(request.params.suggestionId)));
1123
- app.get("/api/works/:workId/ai-calls", (request, response) => data(response, ai.listCalls(request.params.workId)));
1218
+ app.get("/api/works/:workId/ai-calls", (request, response) => {
1219
+ const pagination = parsePagination(request.query);
1220
+ data(response, pagination ? ai.listCallsPage(request.params.workId, pagination) : ai.listCalls(request.params.workId));
1221
+ });
1124
1222
  app.get("/api/works/:workId/search", (request, response) => {
1125
1223
  const query = parse(z.string().trim().min(1).max(500), request.query.q);
1126
1224
  data(response, store.search(request.params.workId, query));
@@ -1136,7 +1234,10 @@ export function createRuntime(options) {
1136
1234
  response.setHeader("Content-Disposition", `attachment; filename=novel-${request.params.workId}.${format === "markdown" ? "md" : "txt"}`);
1137
1235
  response.send(store.exportText(request.params.workId, format));
1138
1236
  });
1139
- app.get("/api/works/:workId/audit-logs", (request, response) => data(response, store.listAuditLogs(request.params.workId)));
1237
+ app.get("/api/works/:workId/audit-logs", (request, response) => {
1238
+ const pagination = parsePagination(request.query);
1239
+ data(response, pagination ? store.listAuditLogsPage(request.params.workId, pagination) : store.listAuditLogs(request.params.workId));
1240
+ });
1140
1241
  if (options.serveUi ?? true) {
1141
1242
  const publicPath = options.publicPath ?? join(process.cwd(), "src", "public");
1142
1243
  // index.html 按登录态动态下发:未登录时注入 login-route 类,首帧直接渲染登录页;