@musnows/scriverse 1.0.8 → 1.0.10

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
@@ -1111,6 +1111,18 @@ function redactSuggestion(record, permissions) {
1111
1111
  restricted: true
1112
1112
  };
1113
1113
  }
1114
+ function redactAiConversationInlineReferences(content, permissions) {
1115
+ const source = typeof content === "string" ? content : "";
1116
+ return source.replace(/<ai_reference kind="(character|setting|chapter|context-settings)" id="[^"]+">[\s\S]*?<\/ai_reference>/gu, (reference, kind) => {
1117
+ const readable = ({
1118
+ character: permissions.characters !== "none",
1119
+ setting: permissions.settings !== "none",
1120
+ chapter: permissions.prose !== "none",
1121
+ "context-settings": permissions.settings !== "none"
1122
+ })[kind] ?? false;
1123
+ return readable ? reference : "(已隐藏引用)";
1124
+ });
1125
+ }
1114
1126
  function redactAiConversationMessage(item, permissions) {
1115
1127
  const message = recordValue(item);
1116
1128
  if (!message)
@@ -1130,9 +1142,10 @@ function redactAiConversationMessage(item, permissions) {
1130
1142
  delete readableMetadata.mentionSettingIds;
1131
1143
  if (permissions.settings === "none")
1132
1144
  delete readableMetadata.mentionContextSettingIds;
1133
- if (Object.keys(readableMetadata).length === Object.keys(metadata).length)
1145
+ const content = redactAiConversationInlineReferences(message.content, permissions);
1146
+ if (Object.keys(readableMetadata).length === Object.keys(metadata).length && content === message.content)
1134
1147
  return item;
1135
- return { ...message, metadata: readableMetadata };
1148
+ return { ...message, content, metadata: readableMetadata };
1136
1149
  }
1137
1150
  return {
1138
1151
  ...message,
@@ -1387,9 +1400,14 @@ export function createRuntime(options) {
1387
1400
  });
1388
1401
  if (!options.liteLlmPriceCache && options.liteLlmPriceCachePath)
1389
1402
  liteLlmPriceCache.start();
1390
- const ai = new AiManager(store, credentialVault, options.fetchImpl ?? fetch, options.developmentServer === true || options.disableAiEndpointValidation === true
1403
+ const disableAiEndpointValidation = options.developmentServer === true || options.disableAiEndpointValidation === true;
1404
+ const validateAiEndpoint = disableAiEndpointValidation || options.disableAiProviderEndpointValidation === true
1391
1405
  ? undefined
1392
- : options.security ? (url) => assertSafeAiEndpoint(url, options.security?.allowPrivateAiEndpoints) : undefined, (task, actor) => {
1406
+ : options.security ? (url) => assertSafeAiEndpoint(url, options.security?.allowPrivateAiEndpoints) : undefined;
1407
+ const validateRemoteMcpEndpoint = disableAiEndpointValidation
1408
+ ? undefined
1409
+ : options.security ? (url) => assertSafeAiEndpoint(url, options.security?.allowPrivateAiEndpoints) : undefined;
1410
+ const ai = new AiManager(store, credentialVault, options.fetchImpl ?? fetch, validateAiEndpoint, (task, actor) => {
1393
1411
  const requiredModules = analysisTaskReadModules(task.taskType, task.scope);
1394
1412
  const creator = actor ? null : database.get("SELECT created_by_user_id, created_via_api_key FROM analysis_tasks WHERE id = ?", String(task.id));
1395
1413
  const userId = actor?.userId ?? (typeof creator?.created_by_user_id === "string" ? creator.created_by_user_id : null);
@@ -1408,6 +1426,7 @@ export function createRuntime(options) {
1408
1426
  retrySleep: options.aiRetrySleep,
1409
1427
  aiChatImageMaxBytes: uploadLimits.chatImageBytes,
1410
1428
  liteLlmPriceCache,
1429
+ remoteMcpValidateOutboundUrl: validateRemoteMcpEndpoint,
1411
1430
  allowPrivateAiEndpoints: options.security?.allowPrivateAiEndpoints === true
1412
1431
  });
1413
1432
  const imOrchestrator = new ImOrchestrator(store, auth, im, ai);
@@ -4034,15 +4053,6 @@ export function createRuntime(options) {
4034
4053
  }
4035
4054
  if (begun.request.status === "completed" && begun.assistantMessage) {
4036
4055
  const content = String(begun.assistantMessage.content ?? "");
4037
- const assistantMetadata = begun.assistantMessage.metadata && typeof begun.assistantMessage.metadata === "object"
4038
- ? begun.assistantMessage.metadata
4039
- : {};
4040
- const writingSuggestionId = typeof assistantMetadata.writingSuggestionId === "string"
4041
- ? assistantMetadata.writingSuggestionId
4042
- : "";
4043
- const writingSuggestion = writingSuggestionId
4044
- ? redactSuggestion(ai.getSuggestion(writingSuggestionId), permissions)
4045
- : null;
4046
4056
  if (content)
4047
4057
  sendEvent("delta", { delta: content, replayed: true });
4048
4058
  sendEvent("complete", {
@@ -4050,8 +4060,7 @@ export function createRuntime(options) {
4050
4060
  conversationId,
4051
4061
  conversationTitle: store.getAiConversationSummary(conversationId).title,
4052
4062
  messageId: begun.assistantMessage.id,
4053
- messageCreatedAt: begun.assistantMessage.createdAt,
4054
- ...(writingSuggestion ? { writingSuggestion } : {})
4063
+ messageCreatedAt: begun.assistantMessage.createdAt
4055
4064
  });
4056
4065
  }
4057
4066
  else {
@@ -4083,7 +4092,7 @@ export function createRuntime(options) {
4083
4092
  questionId: pendingQuestion.id
4084
4093
  });
4085
4094
  }
4086
- const suggestion = await ai.createStreamingChat({
4095
+ const result = await ai.createStreamingChat({
4087
4096
  workId: request.params.workId,
4088
4097
  instruction: resolvedInstruction,
4089
4098
  skillInstruction: instructionText,
@@ -4101,33 +4110,30 @@ export function createRuntime(options) {
4101
4110
  ...(input.parameters ? { parameters: input.parameters } : {}),
4102
4111
  ...(preparedChatImageAttachments.length ? { imageAttachments: preparedChatImageAttachments } : {})
4103
4112
  }, (delta) => sendEvent("delta", { delta }));
4104
- const assistantMessageId = typeof suggestion.conversationMessage === "object" && suggestion.conversationMessage !== null
4105
- ? String(suggestion.conversationMessage.id ?? "")
4113
+ const assistantMessageId = typeof result.conversationMessage === "object" && result.conversationMessage !== null
4114
+ ? String(result.conversationMessage.id ?? "")
4106
4115
  : "";
4107
4116
  if (!stopping) {
4108
4117
  store.finishAiConversationStreamRequest(streamRequestId, "completed", "completed", assistantMessageId || undefined);
4109
4118
  }
4110
4119
  streamRequestFinished = true;
4111
4120
  sendEvent("complete", {
4112
- suggestionId: suggestion.id,
4113
- callId: suggestion.callId,
4114
- provider: suggestion.provider,
4115
- model: suggestion.model,
4116
- outputTokens: suggestion.outputTokens,
4117
- cacheHitPercent: suggestion.cacheHitPercent,
4118
- processDurationMs: suggestion.processDurationMs,
4119
- chapterVersion: suggestion.chapterVersion,
4120
- toolCalls: suggestion.toolCalls,
4121
- processSteps: suggestion.processSteps,
4122
- contextUsage: suggestion.contextUsage,
4121
+ callId: result.callId,
4122
+ provider: result.provider,
4123
+ model: result.model,
4124
+ outputTokens: result.outputTokens,
4125
+ cacheHitPercent: result.cacheHitPercent,
4126
+ processDurationMs: result.processDurationMs,
4127
+ toolCalls: result.toolCalls,
4128
+ processSteps: result.processSteps,
4129
+ contextUsage: result.contextUsage,
4123
4130
  conversationId,
4124
- conversationTitle: suggestion.conversationTitle,
4125
- ...(suggestion.action !== "note" ? { writingSuggestion: redactSuggestion(suggestion, permissions) } : {}),
4126
- messageId: typeof suggestion.conversationMessage === "object" && suggestion.conversationMessage !== null
4127
- ? suggestion.conversationMessage.id
4131
+ conversationTitle: result.conversationTitle,
4132
+ messageId: typeof result.conversationMessage === "object" && result.conversationMessage !== null
4133
+ ? result.conversationMessage.id
4128
4134
  : undefined,
4129
- messageCreatedAt: typeof suggestion.conversationMessage === "object" && suggestion.conversationMessage !== null
4130
- ? suggestion.conversationMessage.createdAt
4135
+ messageCreatedAt: typeof result.conversationMessage === "object" && result.conversationMessage !== null
4136
+ ? result.conversationMessage.createdAt
4131
4137
  : undefined
4132
4138
  });
4133
4139
  }
@@ -4183,15 +4189,6 @@ export function createRuntime(options) {
4183
4189
  const permissions = requestPermissions(request, String(suggestion.workId));
4184
4190
  data(response, redactContinuationGuard(await ai.runSuggestionGuard(request.params.suggestionId, input.content), permissions), 201);
4185
4191
  });
4186
- app.post("/api/suggestions/:suggestionId/accept", (request, response) => {
4187
- const input = parse(z.object({ content: z.string().max(2_000_000).optional() }), request.body ?? {});
4188
- const suggestion = ai.getSuggestion(request.params.suggestionId);
4189
- const permissions = requestPermissions(request, String(suggestion.workId));
4190
- if (!canWriteWorkModule(permissions, "prose")) {
4191
- throw new AppError(403, "WORK_MODULE_WRITE_DENIED", "你没有将 AI 建议写入正文的权限");
4192
- }
4193
- data(response, ai.acceptSuggestion(request.params.suggestionId, input.content));
4194
- });
4195
4192
  app.post("/api/suggestions/:suggestionId/reject", (request, response) => {
4196
4193
  const suggestion = ai.rejectSuggestion(request.params.suggestionId);
4197
4194
  const permissions = requestPermissions(request, String(suggestion.workId));