@musnows/scriverse 0.4.11 → 0.5.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/dist/app.js CHANGED
@@ -295,9 +295,17 @@ const modelSchema = z.object({
295
295
  const aiPromptSchema = z.object({
296
296
  systemPrompt: z.string().max(100_000).optional()
297
297
  });
298
- const platformUiSettingsSchema = z.object({
299
- toastPosition: z.enum(["bottom-right", "top-right"])
298
+ const platformPageSizesSchema = z.object({
299
+ characters: z.number().int().min(10).max(100).optional(),
300
+ analysisTasks: z.number().int().min(10).max(100).optional(),
301
+ fileVersions: z.number().int().min(10).max(100).optional()
300
302
  }).strict();
303
+ const platformUiSettingsSchema = z.object({
304
+ toastPosition: z.enum(["bottom-right", "top-right"]).optional(),
305
+ pageSizes: platformPageSizesSchema.optional()
306
+ }).strict().refine((input) => input.toastPosition !== undefined || input.pageSizes !== undefined, {
307
+ message: "至少需要提供一项界面设置"
308
+ });
301
309
  const aiToolCallResultSchema = z.object({
302
310
  id: z.string().min(1).max(300),
303
311
  name: z.string().min(1).max(200),
@@ -348,6 +356,42 @@ const contextSchema = z.object({
348
356
  settingIds: optionalStrings,
349
357
  includeBookSummary: z.boolean().optional()
350
358
  });
359
+ 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"]);
360
+ const relationshipAnalysisScopeSchema = z.object({
361
+ type: z.enum(["chapter", "book"]),
362
+ chapterId: identifier.optional(),
363
+ includeAllSettings: z.boolean().optional(),
364
+ additionalPrompt: z.string().trim().max(10_000).optional(),
365
+ characterIds: z.array(identifier).max(20).optional(),
366
+ replaceExistingRelationships: z.boolean().optional()
367
+ }).strict().superRefine((scope, context) => {
368
+ if (scope.type === "chapter" && !scope.chapterId) {
369
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["chapterId"], message: "指定章节分析必须提供章节标识" });
370
+ }
371
+ if (scope.includeAllSettings && scope.type !== "book") {
372
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["includeAllSettings"], message: "包含所有设定仅支持全书人物关系分析" });
373
+ }
374
+ if (scope.characterIds && new Set(scope.characterIds).size !== scope.characterIds.length) {
375
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["characterIds"], message: "被分析角色不能重复" });
376
+ }
377
+ if (scope.replaceExistingRelationships && !scope.characterIds?.length) {
378
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["replaceExistingRelationships"], message: "覆盖已有关系前必须选择被分析角色" });
379
+ }
380
+ });
381
+ const analysisTaskSchema = z.union([
382
+ z.object({ taskType: z.literal("relationship-analysis"), scope: relationshipAnalysisScopeSchema.optional() }).strict(),
383
+ z.object({ taskType: analysisTaskTypeSchema, scope: jsonObject.optional() }).strict().superRefine((input, context) => {
384
+ if (input.scope?.includeAllSettings !== undefined) {
385
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "includeAllSettings"], message: "包含所有设定仅支持人物关系分析" });
386
+ }
387
+ if (input.scope?.additionalPrompt !== undefined) {
388
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "additionalPrompt"], message: "额外分析提示仅支持人物关系分析" });
389
+ }
390
+ if (input.scope?.characterIds !== undefined || input.scope?.replaceExistingRelationships !== undefined) {
391
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "characterIds"], message: "被分析角色仅支持人物关系分析" });
392
+ }
393
+ })
394
+ ]);
351
395
  function data(response, value, status = 200) {
352
396
  response.status(status).json({ data: value });
353
397
  }
@@ -390,6 +434,19 @@ function redactRaceMembers(record, permissions) {
390
434
  function redactOrganizationMembers(record, permissions) {
391
435
  return permissions.characters === "none" ? { ...record, memberIds: [], members: [] } : record;
392
436
  }
437
+ function redactTaskCharacterNames(record, permissions) {
438
+ const { scopeSummaryWithoutCharacterNames, ...result } = record;
439
+ if (permissions.characters !== "none")
440
+ return result;
441
+ if (typeof scopeSummaryWithoutCharacterNames === "string")
442
+ result.scopeSummary = scopeSummaryWithoutCharacterNames;
443
+ const scope = recordValue(result.scope);
444
+ if (scope) {
445
+ const { targetCharacters: _targetCharacters, ...redactedScope } = scope;
446
+ result.scope = redactedScope;
447
+ }
448
+ return result;
449
+ }
393
450
  function redactMergeRecords(value, mapper) {
394
451
  const record = recordValue(value);
395
452
  if (!record)
@@ -1287,25 +1344,23 @@ export function createRuntime(options) {
1287
1344
  data(response, store.mergeCharacters({ reviewId: request.params.reviewId, ...input }));
1288
1345
  });
1289
1346
  app.get("/api/works/:workId/tasks", (request, response) => {
1290
- const pagination = parsePagination(request.query);
1291
- const summary = request.query.view === "summary";
1292
- data(response, pagination
1293
- ? (summary ? store.listTaskSummariesPage(request.params.workId, pagination) : store.listTasksPage(request.params.workId, pagination))
1294
- : store.listTasks(request.params.workId));
1347
+ const permissions = requestPermissions(request, request.params.workId);
1348
+ data(response, mapRecords(store.listTaskSummariesPage(request.params.workId, parsePagination(request.query) ?? { page: 1, limit: 30, offset: 0 }), (task) => redactTaskCharacterNames(task, permissions)));
1295
1349
  });
1296
1350
  app.post("/api/works/:workId/tasks", (request, response) => {
1297
- 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);
1298
- data(response, store.createTask(request.params.workId, input), 201);
1351
+ const input = parse(analysisTaskSchema, request.body);
1352
+ data(response, redactTaskCharacterNames(store.createTask(request.params.workId, input), requestPermissions(request, request.params.workId)), 201);
1299
1353
  });
1300
1354
  app.post("/api/works/:workId/tasks/auto-run", (request, response) => {
1301
1355
  data(response, ai.startAutoRunBatch(request.params.workId));
1302
1356
  });
1303
- app.get("/api/tasks/:taskId", (request, response) => data(response, store.getTask(request.params.taskId)));
1357
+ app.get("/api/tasks/:taskId", (request, response) => data(response, redactTaskCharacterNames(store.getTask(request.params.taskId), requestPermissions(request))));
1358
+ app.get("/api/tasks/:taskId/trace", (request, response) => data(response, ai.getTaskTrace(request.params.taskId)));
1304
1359
  app.post("/api/tasks/:taskId/run", async (request, response) => {
1305
1360
  const input = parse(z.object({ modelId: identifier.optional() }), request.body ?? {});
1306
- data(response, await ai.runTask(request.params.taskId, input.modelId));
1361
+ data(response, redactTaskCharacterNames(await ai.runTask(request.params.taskId, input.modelId), requestPermissions(request)));
1307
1362
  });
1308
- app.post("/api/tasks/:taskId/cancel", (request, response) => data(response, ai.cancelTask(request.params.taskId)));
1363
+ app.post("/api/tasks/:taskId/cancel", (request, response) => data(response, redactTaskCharacterNames(ai.cancelTask(request.params.taskId), requestPermissions(request))));
1309
1364
  app.get("/api/platform/ai/providers", (request, response) => {
1310
1365
  const pagination = parsePagination(request.query);
1311
1366
  data(response, pagination ? ai.listProvidersPage(pagination) : ai.listProviders());
@@ -1358,6 +1413,7 @@ export function createRuntime(options) {
1358
1413
  metadata: z.object({
1359
1414
  modelDisplayName: z.string().max(200).optional(),
1360
1415
  outputTokens: z.number().int().min(0).max(10_000_000).optional(),
1416
+ cacheHitPercent: z.number().min(0).max(100).optional(),
1361
1417
  processDurationMs: z.number().int().min(0).max(86_400_000).optional(),
1362
1418
  toolCalls: z.array(aiToolCallResultSchema).max(12).optional(),
1363
1419
  processSteps: z.array(aiProcessStepSchema).max(50).optional()
@@ -1528,6 +1584,7 @@ export function createRuntime(options) {
1528
1584
  provider: suggestion.provider,
1529
1585
  model: suggestion.model,
1530
1586
  outputTokens: suggestion.outputTokens,
1587
+ cacheHitPercent: suggestion.cacheHitPercent,
1531
1588
  chapterVersion: suggestion.chapterVersion,
1532
1589
  toolCalls: suggestion.toolCalls,
1533
1590
  processSteps: suggestion.processSteps