@musnows/scriverse 0.7.7 → 0.7.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
@@ -1033,6 +1033,15 @@ export function createRuntime(options) {
1033
1033
  return fullWorkModulePermissions();
1034
1034
  return auth.workModulePermissions(request.authUser, resolvedWorkId, request.authMethod !== "api-key") ?? fullWorkModulePermissions();
1035
1035
  };
1036
+ const resolveConversationModelId = (workId, conversationId, requestedModelId) => {
1037
+ if (!conversationId)
1038
+ return requestedModelId;
1039
+ const lockedModelId = store.getAiConversationLockedModelId(conversationId, workId);
1040
+ if (lockedModelId && requestedModelId && lockedModelId !== requestedModelId) {
1041
+ throw new AppError(409, "AI_CONVERSATION_MODEL_LOCKED", "当前对话已经锁定模型,请新建对话后再切换模型");
1042
+ }
1043
+ return lockedModelId ?? requestedModelId;
1044
+ };
1036
1045
  const captcha = new ImageCaptchaService({ revealAnswer: options.revealCaptchaAnswer === true });
1037
1046
  const credentialVault = new CredentialVault(options.masterSecret);
1038
1047
  const backups = new S3BackupManager(database, credentialVault, store, attachmentStorage, {
@@ -2354,6 +2363,7 @@ export function createRuntime(options) {
2354
2363
  citations: z.array(z.unknown()).max(100).optional(),
2355
2364
  requestId: identifier.optional(),
2356
2365
  metadata: z.object({
2366
+ modelId: identifier.optional(),
2357
2367
  modelDisplayName: z.string().max(200).optional(),
2358
2368
  outputTokens: z.number().int().min(0).max(10_000_000).optional(),
2359
2369
  cacheHitPercent: z.number().min(0).max(100).optional(),
@@ -2468,6 +2478,7 @@ export function createRuntime(options) {
2468
2478
  instruction: nonEmpty.max(100_000),
2469
2479
  scope: contextSchema,
2470
2480
  modelId: identifier.optional(),
2481
+ conversationId: identifier.optional(),
2471
2482
  parameters: jsonObject.optional(),
2472
2483
  citations: aiCitationsSchema.optional()
2473
2484
  }), request.body);
@@ -2476,12 +2487,14 @@ export function createRuntime(options) {
2476
2487
  if (store.getChapter(citation.chapterId).workId !== request.params.workId)
2477
2488
  throw new AppError(400, "CITATION_WORK_MISMATCH", "引用章节不属于当前作品");
2478
2489
  }
2490
+ const modelId = resolveConversationModelId(request.params.workId, input.conversationId, input.modelId);
2479
2491
  data(response, redactSuggestion(await ai.createSuggestion({
2480
2492
  workId: request.params.workId,
2481
2493
  taskType: input.taskType,
2482
2494
  instruction: instructionWithCitations(input.instruction, citations),
2483
2495
  scope: input.scope,
2484
- ...(input.modelId ? { modelId: input.modelId } : {}),
2496
+ ...(modelId ? { modelId } : {}),
2497
+ ...(input.conversationId ? { conversationId: input.conversationId } : {}),
2485
2498
  ...(input.parameters ? { parameters: input.parameters } : {})
2486
2499
  }), requestPermissions(request, request.params.workId)), 201);
2487
2500
  });
@@ -2521,6 +2534,7 @@ export function createRuntime(options) {
2521
2534
  throw new AppError(400, "CONVERSATION_WORK_MISMATCH", "AI 对话不属于当前作品");
2522
2535
  }
2523
2536
  const conversationId = String(conversation.id);
2537
+ const modelId = resolveConversationModelId(request.params.workId, conversationId, input.modelId);
2524
2538
  const permissions = requestPermissions(request, request.params.workId);
2525
2539
  const controller = new AbortController();
2526
2540
  response.on("close", () => {
@@ -2556,7 +2570,7 @@ export function createRuntime(options) {
2556
2570
  preparedContext = await ai.prepareConversationContext({
2557
2571
  conversationId,
2558
2572
  workId: request.params.workId,
2559
- modelId: input.modelId,
2573
+ modelId,
2560
2574
  scope: input.scope,
2561
2575
  instruction: resolvedInstruction,
2562
2576
  excludeConversationMessageId: input.currentMessageId
@@ -2601,7 +2615,10 @@ export function createRuntime(options) {
2601
2615
  content: input.instruction,
2602
2616
  citations,
2603
2617
  ...(input.currentMessageId ? { existingMessageId: input.currentMessageId } : {}),
2604
- ...(mentionCharacterIds.length ? { metadata: { mentionCharacterIds } } : {})
2618
+ ...((modelId || mentionCharacterIds.length) ? { metadata: {
2619
+ ...(modelId ? { modelId } : {}),
2620
+ ...(mentionCharacterIds.length ? { mentionCharacterIds } : {})
2621
+ } } : {})
2605
2622
  }
2606
2623
  });
2607
2624
  streamRequestId = begun.request.id;
@@ -2659,7 +2676,7 @@ export function createRuntime(options) {
2659
2676
  conversationId,
2660
2677
  excludeConversationMessageId: currentMessageId,
2661
2678
  ...(currentMessageId ? { assistantMessageRequestId: `assistant:${currentMessageId}` } : {}),
2662
- ...(input.modelId ? { modelId: input.modelId } : {}),
2679
+ ...(modelId ? { modelId } : {}),
2663
2680
  ...(input.parameters ? { parameters: input.parameters } : {})
2664
2681
  }, (delta) => sendEvent("delta", { delta }));
2665
2682
  const assistantMessageId = typeof suggestion.conversationMessage === "object" && suggestion.conversationMessage !== null
@@ -2676,6 +2693,7 @@ export function createRuntime(options) {
2676
2693
  model: suggestion.model,
2677
2694
  outputTokens: suggestion.outputTokens,
2678
2695
  cacheHitPercent: suggestion.cacheHitPercent,
2696
+ processDurationMs: suggestion.processDurationMs,
2679
2697
  chapterVersion: suggestion.chapterVersion,
2680
2698
  toolCalls: suggestion.toolCalls,
2681
2699
  processSteps: suggestion.processSteps,