koishi-plugin-satori-ai 1.3.8 → 1.3.9

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/lib/index.d.ts CHANGED
@@ -35,7 +35,7 @@ export declare class SAT extends Sat {
35
35
  content: string;
36
36
  error: boolean;
37
37
  }>;
38
- getChatResponse(user: User, messages: Sat.Msg[]): Promise<{
38
+ getChatResponse(user: User, messages: Sat.Msg[], prompt: string): Promise<{
39
39
  content: string;
40
40
  error: boolean;
41
41
  }>;
@@ -47,9 +47,10 @@ export declare class SAT extends Sat {
47
47
  getWarningList(session: Session): Promise<void>;
48
48
  private clearSession;
49
49
  private addCommonSense;
50
+ addGroupCommonSense(session: Session, content: string, groupId: string): Promise<string>;
50
51
  private handleUserLevel;
51
52
  private handleUserUsage;
52
- handleRandomMiddleware(session: Session, prompt: string): Promise<string>;
53
+ handleRandomMiddleware(session: Session): Promise<string>;
53
54
  handleNickNameMiddleware(session: Session, prompt: string): Promise<string>;
54
55
  handleChannelMemoryManager(session: Session): Promise<void>;
55
56
  }
package/lib/index.js CHANGED
@@ -258,25 +258,36 @@ function processPrompt(prompt) {
258
258
  return prompt.trim();
259
259
  }
260
260
  __name(processPrompt, "processPrompt");
261
- function filterResponse(prompt, words) {
262
- const parts = prompt.split(/([(\[【《(][^))]*[)\]】》)])/g);
263
- const filtered = parts.map((part) => {
264
- if (part.startsWith("(") && part.endsWith(")") || part.startsWith("(") && part.endsWith(")") || part.startsWith("[") && part.endsWith("]") || part.startsWith("【") && part.endsWith("】") || part.startsWith("《") && part.endsWith("》")) {
265
- return words.some((word) => part.includes(word)) ? "" : part;
266
- }
267
- return part;
268
- }).join("");
269
- const cleaned = filtered.replace(/\s+/g, "");
270
- const answerRegex = /<p>((?!<\/?p>)[\s\S])*?<\/p/g;
271
- const answerRegex2 = /<doubaothinking>((?!<\/?doubaothinking>)[\s\S])*?<\/p/g;
261
+ function filterResponse(prompt, words, options) {
262
+ const applyBracketFilter = options?.applyBracketFilter ?? true;
263
+ const applyTagFilter = options?.applyTagFilter ?? true;
264
+ let working = prompt;
265
+ if (applyBracketFilter) {
266
+ const parts = working.split(/([(\[【《(][^))]*[)\]】》)])/g);
267
+ const filtered = parts.map((part) => {
268
+ if (part.startsWith("(") && part.endsWith(")") || part.startsWith("(") && part.endsWith(")") || part.startsWith("[") && part.endsWith("]") || part.startsWith("【") && part.endsWith("】") || part.startsWith("《") && part.endsWith("》")) {
269
+ return words.some((word) => part.includes(word)) ? "" : part;
270
+ }
271
+ return part;
272
+ }).join("");
273
+ working = filtered.replace(/\s+/g, "");
274
+ if (!working) {
275
+ working = prompt;
276
+ }
277
+ }
278
+ if (!applyTagFilter) {
279
+ return working ? { content: working, error: false } : { content: "有点问题,请重置对话", error: true };
280
+ }
281
+ const answerRegex = /<p>((?!<\/?p>)[\s\S])*?<\/p>/g;
282
+ const answerRegex2 = /<doubaothinking>((?!<\/?doubaothinking>)[\s\S])*?<\/p>/g;
272
283
  const answerRegex3 = /<doubaothinking>((?!<\/?doubaothinking>)[\s\S])*?<\/doubaothinking>/g;
273
284
  const answerRegex4 = /<answer>((?!<\/?answer>)[\s\S])*?<\/answer>/g;
274
285
  const answerRegex5 = /<doubaothinking>((?!<\/?doubaothinking>)[\s\S])*?<\/answer>/g;
275
- const answerMatches = cleaned.match(answerRegex);
276
- const answerMatches2 = cleaned.match(answerRegex2);
277
- const answerMatches3 = cleaned.match(answerRegex3);
278
- const answerMatches4 = cleaned.match(answerRegex4);
279
- const answerMatches5 = cleaned.match(answerRegex5);
286
+ const answerMatches = working.match(answerRegex);
287
+ const answerMatches2 = working.match(answerRegex2);
288
+ const answerMatches3 = working.match(answerRegex3);
289
+ const answerMatches4 = working.match(answerRegex4);
290
+ const answerMatches5 = working.match(answerRegex5);
280
291
  const lastAnswer = answerMatches ? answerMatches[answerMatches.length - 1] : null;
281
292
  const lastDoubao = answerMatches2 ? answerMatches2[answerMatches2.length - 1] : null;
282
293
  const lastAnswer3 = answerMatches3 ? answerMatches3[answerMatches3.length - 1] : null;
@@ -718,11 +729,14 @@ var MemoryManager = class {
718
729
  async searchMemories(session, prompt, type = "user") {
719
730
  const filePathMap = {
720
731
  "user": this.getUserMemoryPath(session.userId),
721
- "common": path2.join(this.config.dataDir, "common_sense.txt")
732
+ "common": path2.join(this.config.dataDir, "common_sense.txt"),
733
+ "group": path2.join(this.config.dataDir, "group_sense", `${session.channelId}.txt`)
722
734
  };
723
735
  const topNMap = {
724
736
  "user": this.config.dailogues_topN,
725
- "common": this.config.common_topN
737
+ "common": this.config.common_topN,
738
+ "group": this.config.common_topN
739
+ // 群常识和常识使用同样的topN
726
740
  };
727
741
  const filePath = filePathMap[type];
728
742
  if (!fs2.existsSync(filePath)) {
@@ -759,7 +773,8 @@ var MemoryManager = class {
759
773
  formatMatches(matched, type, topN = 5) {
760
774
  const prefixMap = {
761
775
  "common": "这是你可能用到的信息:",
762
- "user": "以下是较久之前用户说过的话和对话时间:"
776
+ "user": "以下是较久之前用户说过的话和对话时间:",
777
+ "group": "以下是本群聊你可能需要知道的信息:"
763
778
  };
764
779
  const time = `时段:${getTimeOfDay((/* @__PURE__ */ new Date()).getHours())}`;
765
780
  const date = `当前日期和时间:${(/* @__PURE__ */ new Date()).toLocaleString()} ${time}`;
@@ -772,11 +787,17 @@ ${date}
772
787
  }
773
788
  `;
774
789
  return result;
775
- } else {
790
+ } else if (type === "user") {
776
791
  matched.forEach((entry) => entry.content = entry.content + (entry.role === "user" ? "(未记录时间)" : entry.role));
777
792
  const result = `${prefixMap[type]}{
778
793
  ${matched.map((entry) => entry.content).join("\n")}
779
794
  }
795
+ `;
796
+ return result;
797
+ } else if (type === "group") {
798
+ const result = `${prefixMap[type]}{
799
+ ${matched.map((entry) => entry.content).join("\n")}
800
+ }
780
801
  `;
781
802
  return result;
782
803
  }
@@ -925,6 +946,8 @@ async function handleFavorabilitySystem(ctx, session, config) {
925
946
  }
926
947
  __name(handleFavorabilitySystem, "handleFavorabilitySystem");
927
948
  function getFavorabilityLevel(user, config) {
949
+ if (user.favorability >= config.favorability_div_3 && user?.items["镇定贴"]?.count > 0 && user?.items["镇定贴"]?.description && user?.items["镇定贴"]?.description == "on")
950
+ return "朋友";
928
951
  if (user?.items["订婚戒指"]?.count > 0 && user?.items["订婚戒指"]?.description && user?.items["订婚戒指"]?.description == "已使用")
929
952
  return "夫妻";
930
953
  if (user.favorability < config.favorability_div_1)
@@ -1074,7 +1097,7 @@ function createMiddleware(ctx, sat, config) {
1074
1097
  return await handleNickNameMessage(sat, session);
1075
1098
  }
1076
1099
  if (shouldRandomTrigger(session, config)) {
1077
- return await sat.handleRandomMiddleware(session, session.content);
1100
+ return await sat.handleRandomMiddleware(session);
1078
1101
  }
1079
1102
  return next();
1080
1103
  };
@@ -1145,6 +1168,7 @@ var Sat = class extends import_koishi5.Service {
1145
1168
  import_koishi5.Schema.transform(String, (value) => [value])
1146
1169
  ]).default([]).role("secret").description("深度思考模型api_key"),
1147
1170
  appointModel: import_koishi5.Schema.string().default("deepseek-reasoner").description("深度思考模型"),
1171
+ enhanceReasoningProtection: import_koishi5.Schema.boolean().default(true).description("是否增强思维链保护(开启后会强制输出内容带有限制标签,极大防止思维链溢出问题)"),
1148
1172
  not_reasoner_LLM_URL: import_koishi5.Schema.string().default("https://api.deepseek.com").description("非深度思考模型请求地址"),
1149
1173
  not_reasoner_LLM: import_koishi5.Schema.string().default("deepseek-chat").description("非深度思考模型(用于节省成本"),
1150
1174
  not_reasoner_LLM_key: import_koishi5.Schema.union([
@@ -1188,7 +1212,7 @@ var Sat = class extends import_koishi5.Service {
1188
1212
  dataDir: import_koishi5.Schema.string().default("./data/satori_ai").description("聊天记录保存位置(长期记忆)"),
1189
1213
  memory_block_words: import_koishi5.Schema.array(String).default(["好感"]).description("记忆屏蔽词"),
1190
1214
  remember_min_length: import_koishi5.Schema.number().description("触发保存到记忆的长度").default(20),
1191
- common_topN: import_koishi5.Schema.number().default(5).description("常识记忆检索最大匹配数"),
1215
+ common_topN: import_koishi5.Schema.number().default(5).description("群常识、常识记忆检索最大匹配数"),
1192
1216
  dailogues_topN: import_koishi5.Schema.number().default(5).description("对话记忆检索最大匹配数"),
1193
1217
  enable_fixed_dialogues: import_koishi5.Schema.boolean().default(false).description("是否启用固定对话(在dataDir中的fixed_dialogues.json修改)")
1194
1218
  }).description("记忆设置"),
@@ -1203,6 +1227,7 @@ var Sat = class extends import_koishi5.Service {
1203
1227
  duplicateDialogueCheck: import_koishi5.Schema.boolean().default(true).description("是否检查重复对话"),
1204
1228
  enable_online_user_check: import_koishi5.Schema.boolean().default(true).description("在未回答而再次提问时是否提示用户有未完成的对话"),
1205
1229
  random_min_tokens: import_koishi5.Schema.number().default(20).description("随机触发对话的最小长度"),
1230
+ enable_random_without_favorability: import_koishi5.Schema.boolean().default(true).description("是否启用随机触发对话无视高好感度(即使用户好感度很高也会最多视为朋友)"),
1206
1231
  randnum: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0).description("在群聊中随机触发对话的概率,如需关闭可设置为 0"),
1207
1232
  sentences_divide: import_koishi5.Schema.boolean().default(true).description("是否分句发送"),
1208
1233
  min_sentences_length: import_koishi5.Schema.number().default(10).description("每个分句的最小长度"),
@@ -3058,6 +3083,7 @@ __name(wrapInHTML2, "wrapInHTML");
3058
3083
 
3059
3084
  // src/index.tsx
3060
3085
  var logger12 = new import_koishi13.Logger("satori-ai");
3086
+ var randomPrompt = "根据群聊内最近的包括所有人的聊天记录,锐评一下群聊中的话题";
3061
3087
  var puppeteer = null;
3062
3088
  function refreshPuppeteer(ctx) {
3063
3089
  if (ctx.puppeteer) {
@@ -3192,7 +3218,8 @@ var SAT = class extends Sat {
3192
3218
  registerCommands(ctx) {
3193
3219
  ctx.command("sat <text:text>", { authority: this.config.authority }).alias(...this.config.alias).action(async ({ session }, prompt) => this.handleSatCommand(session, prompt));
3194
3220
  ctx.command("sat.clear", "清空会话").option("global", "-g").action(({ session, options }) => this.clearSession(session, options.global));
3195
- ctx.command("sat.common_sense <text:text>", "添加常识").action(async ({ session }, prompt) => this.addCommonSense(session, prompt));
3221
+ ctx.command("sat.common_sense <text:text>", "添加常识", { authority: 4 }).alias("添加常识").action(async ({ session }, prompt) => this.addCommonSense(session, prompt));
3222
+ ctx.command("sat.group_sense <text:text>", "添加群常识", { authority: 3 }).alias("添加群常识").option("id", "-i <id:string>", { authority: 3 }).action(async ({ session, options }, prompt) => this.addGroupCommonSense(session, prompt, options.id));
3196
3223
  ctx.command("sat.update_user_level", "更新用户等级", { authority: 2 }).alias("更新用户").option("id", "-i <id:string>", { authority: 4 }).option("level", "-l <level:number>", { authority: 4 }).action(async ({ session, options }) => this.handleUserLevel(session, options));
3197
3224
  ctx.command("sat.user_usage", "查看用户使用次数").alias("查询次数").action(async ({ session }) => this.handleUserUsage(session));
3198
3225
  ctx.command("sat.add_output_censor <text:text>", "添加输出敏感词", { authority: 4 }).alias("添加输出屏蔽词").action(async ({ session }, word) => addOutputCensor(session, word, this.config.dataDir));
@@ -3356,15 +3383,18 @@ var SAT = class extends Sat {
3356
3383
  const messages = await this.buildMessages(session, prompt);
3357
3384
  logger12.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
3358
3385
  const user = await getUser(this.ctx, session.userId);
3359
- let response = await this.getChatResponse(user, messages);
3386
+ let response = await this.getChatResponse(user, messages, prompt);
3360
3387
  if (response.error)
3361
- response = await this.getChatResponse(user, messages);
3388
+ response = await this.getChatResponse(user, messages, prompt);
3362
3389
  if (response.error)
3363
3390
  updateUserUsage(this.ctx, user, -1);
3364
3391
  return response;
3365
3392
  }
3366
3393
  // 获取聊天回复
3367
- async getChatResponse(user, messages) {
3394
+ async getChatResponse(user, messages, prompt) {
3395
+ const hasTicket = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on";
3396
+ const maxLength = hasTicket ? user?.items?.["地灵殿通行证"]?.metadata?.use_not_reasoner_LLM_length : this.config.use_not_reasoner_LLM_length;
3397
+ const useNoReasoner = prompt.length <= maxLength && this.config.enable_reasoner_like;
3368
3398
  let response = await this.apiClient.chat(user, messages);
3369
3399
  if (this.config.log_ask_response) {
3370
3400
  if (this.config.enable_favorability && this.config.enable_mood)
@@ -3372,25 +3402,38 @@ var SAT = class extends Sat {
3372
3402
  else
3373
3403
  logger12.info(`Satori AI:${response.content}`);
3374
3404
  }
3375
- if (this.config.reasoner_filter && !response.error)
3376
- response = filterResponse(response.content, this.config.reasoner_filter_word.split("-"));
3405
+ if (!response.error) {
3406
+ response = filterResponse(response.content, this.config.reasoner_filter_word.split("-"), {
3407
+ applyBracketFilter: this.config.reasoner_filter,
3408
+ applyTagFilter: useNoReasoner || this.config.enhanceReasoningProtection
3409
+ });
3410
+ }
3377
3411
  return response;
3378
3412
  }
3379
3413
  // 构建消息
3380
3414
  async buildMessages(session, prompt) {
3381
3415
  const messages = [];
3382
- const example = `<think>
3416
+ const user = await ensureUserExists(this.ctx, session.userId, session.username);
3417
+ const hasTicket = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on";
3418
+ const maxLength = hasTicket ? user?.items?.["地灵殿通行证"]?.metadata?.use_not_reasoner_LLM_length : this.config.use_not_reasoner_LLM_length;
3419
+ const useNoReasoner = prompt.length <= maxLength && this.config.enable_reasoner_like;
3420
+ const exampleWithoutReasoner = `<think>
3383
3421
  好的,我会尽量做到的
3384
3422
  </think>
3385
3423
  <p>已明确对话要求</p>`;
3424
+ const exampleWithTag = `<p>已明确对话要求</p>`;
3425
+ const exampleWithoutTag = `已明确对话要求`;
3426
+ const example = useNoReasoner ? exampleWithoutReasoner : this.config.enhanceReasoningProtection ? exampleWithTag : exampleWithoutTag;
3386
3427
  if (this.config.no_system_prompt) {
3387
3428
  messages.push({ role: "user", content: await this.buildSystemPrompt(session, prompt) });
3388
3429
  messages.push({ role: "assistant", content: example });
3389
3430
  } else {
3390
3431
  messages.push({ role: "system", content: await this.buildSystemPrompt(session, prompt) });
3391
3432
  }
3392
- const userMemory = this.memoryManager.getChannelContext(this.config.personal_memory ? session.userId : session.channelId);
3393
- messages.push(...userMemory);
3433
+ if (prompt != randomPrompt) {
3434
+ const userMemory = this.memoryManager.getChannelContext(this.config.personal_memory ? session.userId : session.channelId);
3435
+ messages.push(...userMemory);
3436
+ }
3394
3437
  messages.push({ role: "user", content: prompt });
3395
3438
  let payload = messages.map((msg) => msg.role + ":" + msg.content).join("\n");
3396
3439
  if (this.config.log_system_prompt)
@@ -3401,20 +3444,34 @@ ${payload}`);
3401
3444
  // 构建系统提示
3402
3445
  async buildSystemPrompt(session, prompt) {
3403
3446
  const commonSense = await this.memoryManager.searchMemories(session, prompt, "common");
3447
+ const groupSense = await this.memoryManager.searchMemories(session, prompt, "group");
3404
3448
  const channelDialogue = await this.memoryManager.getChannelDialogue(session);
3405
3449
  const userMemory = await this.memoryManager.searchMemories(session, prompt);
3406
3450
  const user = await getUser(this.ctx, session.userId);
3407
3451
  const moodLevel = this.moodManager.getMoodLevel(user.userid);
3408
3452
  let systemPrompt = "";
3453
+ if (prompt == randomPrompt) {
3454
+ systemPrompt += "#首先明确一些参考信息\n";
3455
+ systemPrompt += "\n##" + channelDialogue;
3456
+ systemPrompt += this.getThinkingPrompt(user, prompt);
3457
+ systemPrompt += this.config.prompt;
3458
+ if (this.config.enhanceReasoningProtection) {
3459
+ systemPrompt += `
3460
+ #注意:你最终的回复内容必须使用“<p>”开头,使用“</p>”结尾
3461
+ `;
3462
+ if (this.config.no_system_prompt)
3463
+ systemPrompt += "\n#如果你明白以上内容,请回复“<p>已明确对话要求</p>”";
3464
+ }
3465
+ return systemPrompt;
3466
+ }
3409
3467
  systemPrompt += "#首先明确一些参考信息\n";
3410
3468
  systemPrompt += "\n##" + commonSense;
3469
+ systemPrompt += "\n##" + groupSense;
3411
3470
  systemPrompt += "\n##" + channelDialogue;
3412
3471
  systemPrompt += "\n##" + userMemory;
3413
3472
  if (moodLevel == "normal" || moodLevel == "happy")
3414
3473
  systemPrompt += "\n##" + this.portraitManager.getUserPortrait(session);
3415
- systemPrompt += "\n#参考信息到此为止,接下来是思考要求\n";
3416
3474
  systemPrompt += this.getThinkingPrompt(user, prompt);
3417
- systemPrompt += "\n#接下来是对话要求,以下要求仅对最终的回复内容生效,不限制思考过程\n";
3418
3475
  systemPrompt += this.config.prompt;
3419
3476
  if (user?.items?.["觉的衣柜"]?.count && (moodLevel == "normal" || moodLevel == "happy")) {
3420
3477
  const clothes = user?.items?.["觉的衣柜"]?.metadata?.clothes;
@@ -3442,23 +3499,31 @@ ${payload}`);
3442
3499
  if (nickName)
3443
3500
  systemPrompt += `, 昵称是:${nickName},称呼用户时请优先使用昵称
3444
3501
  `;
3445
- systemPrompt += `
3502
+ if (this.config.enhanceReasoningProtection) {
3503
+ systemPrompt += `
3446
3504
  #注意:你最终的回复内容必须使用“<p>”开头,使用“</p>”结尾
3447
3505
  `;
3448
- if (this.config.no_system_prompt)
3449
- systemPrompt += "\n#如果你明白以上内容,请回复“<p>已明确对话要求</p>”";
3506
+ if (this.config.no_system_prompt)
3507
+ systemPrompt += "\n#如果你明白以上内容,请回复“<p>已明确对话要求</p>”";
3508
+ }
3450
3509
  return systemPrompt;
3451
3510
  }
3452
3511
  // 思考提示
3453
3512
  getThinkingPrompt(user, prompt) {
3454
3513
  const reasonerPrompt = this.config.reasoner_prompt;
3455
- const promptForNoReasoner = `#请你在回复时先进行分析思考,并且模仿思维链的模式输出思考内容,${reasonerPrompt};
3514
+ const promptForNoReasoner = `
3515
+ #参考信息到此为止,接下来是思考要求
3516
+ #请你在回复时先进行分析思考,并且模仿思维链的模式输出思考内容,${reasonerPrompt};
3456
3517
  #你在思考时必须以 "<think>" 开头, "</think>" 结尾。仔细揣摩用户意图,**完整输出思考内容后**再输出正式的回复内容;
3457
- #注意:你的正式回复内容必须使用“<p>”开头,使用“</p>”结尾,并且无论如何都要把标签输出完整
3458
- `;
3459
- const promptForReasoner = `#你在思考时必须以 "嗯" 开头。仔细揣摩用户意图,思考结束后返回符合要求的回复。
3460
- #注意:你的回复内容必须使用“<p>”开头,使用“</p>”结尾
3518
+ #注意:你的正式回复内容必须使用“<p>”开头,在输出全部回复后使用“</p>”结尾(即输出且仅输出一对标签),并且无论如何都要把标签输出完整
3519
+ #接下来是对话要求,以下要求仅对最终的回复内容生效,不限制思考过程
3461
3520
  `;
3521
+ const promptForReasoner = this.config.enhanceReasoningProtection ? `
3522
+ #参考信息到此为止,接下来是思考要求
3523
+ #你在思考时必须以 "嗯" 开头。仔细揣摩用户意图,思考结束后返回符合要求的回复。
3524
+ #注意:你的回复内容必须使用“<p>”开头,在输出全部回复后使用“</p>”结尾(即输出且仅输出一对标签)
3525
+ #接下来是对话要求,以下要求仅对最终的回复内容生效,不限制思考过程
3526
+ ` : "";
3462
3527
  const hasTicket = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on";
3463
3528
  const maxLength = hasTicket ? user?.items?.["地灵殿通行证"]?.metadata?.use_not_reasoner_LLM_length : this.config.use_not_reasoner_LLM_length;
3464
3529
  const useNoReasoner = prompt.length <= maxLength;
@@ -3559,6 +3624,18 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
3559
3624
  }], filePath);
3560
3625
  return session.text("commands.sat.common_sense.messages.succeed", [content]);
3561
3626
  }
3627
+ // 添加群常识
3628
+ async addGroupCommonSense(session, content, groupId) {
3629
+ if (!content)
3630
+ return session.text("commands.sat.common_sense.messages.no-prompt");
3631
+ const id = groupId || session.channelId;
3632
+ const filePath = path6.join(this.config.dataDir, `group_sense`, `${id}.txt`);
3633
+ await this.memoryManager.saveLongTermMemory(session, [{
3634
+ role: "user",
3635
+ content: content.replace(/\"/g, "'").trim()
3636
+ }], filePath);
3637
+ return session.text("commands.sat.common_sense.messages.succeed", [`群${id}中:` + content]);
3638
+ }
3562
3639
  // 更新用户等级
3563
3640
  async handleUserLevel(session, options) {
3564
3641
  const userId = options.id || session.userId;
@@ -3587,21 +3664,10 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
3587
3664
  return result;
3588
3665
  }
3589
3666
  // 随机中间件转接
3590
- async handleRandomMiddleware(session, prompt) {
3591
- const user = await getUser(this.ctx, session.userId);
3592
- const processedPrompt = processPrompt(session.content);
3593
- if (this.performPreChecks(session, processedPrompt))
3594
- return null;
3595
- if (await this.checkUserDialogueCount(session, user, 0))
3596
- return null;
3597
- if (await this.checkFavorabilityBlock(session))
3598
- return null;
3599
- let censored = processedPrompt;
3600
- if (this.ctx.censor)
3601
- censored = await this.ctx.censor.transform(processedPrompt, session);
3602
- if (censored.includes("**"))
3603
- return null;
3604
- return this.handleSatCommand(session, prompt);
3667
+ async handleRandomMiddleware(session) {
3668
+ await this.updateChannelParallelCount(session, 1);
3669
+ const response = await this.generateResponse(session, randomPrompt);
3670
+ return await this.formatResponse(session, response.content, null);
3605
3671
  }
3606
3672
  // 昵称中间件转接
3607
3673
  async handleNickNameMiddleware(session, prompt) {
package/lib/memory.d.ts CHANGED
@@ -23,7 +23,7 @@ export declare class MemoryManager {
23
23
  clearAllMemories(): void;
24
24
  getChannelMemory(channelId: string): MemoryEntry[];
25
25
  saveLongTermMemory(session: Session, dialogues: MemoryEntry[], filePath?: string): Promise<void>;
26
- searchMemories(session: Session, prompt: string, type?: 'user' | 'common'): Promise<string>;
26
+ searchMemories(session: Session, prompt: string, type?: 'user' | 'common' | 'group'): Promise<string>;
27
27
  private findBestMatches;
28
28
  private calculateMatchScore;
29
29
  private formatMatches;
package/lib/types.d.ts CHANGED
@@ -148,6 +148,7 @@ export declare namespace Sat {
148
148
  baseURL: string;
149
149
  key: string[];
150
150
  appointModel: string;
151
+ enhanceReasoningProtection: boolean;
151
152
  not_reasoner_LLM_URL: string;
152
153
  not_reasoner_LLM: string;
153
154
  not_reasoner_LLM_key: string[];
@@ -191,6 +192,7 @@ export declare namespace Sat {
191
192
  duplicateDialogueCheck: boolean;
192
193
  enable_online_user_check: boolean;
193
194
  random_min_tokens: number;
195
+ enable_random_without_favorability: boolean;
194
196
  randnum: number;
195
197
  sentences_divide: boolean;
196
198
  min_sentences_length: number;
package/lib/utils.d.ts CHANGED
@@ -23,7 +23,10 @@ export declare function processPrompt(prompt: string): string;
23
23
  * @param words 需要过滤的关键词
24
24
  * @returns 处理后的字符串,删除含有关键词的部分
25
25
  */
26
- export declare function filterResponse(prompt: string, words: string[]): {
26
+ export declare function filterResponse(prompt: string, words: string[], options?: {
27
+ applyBracketFilter?: boolean;
28
+ applyTagFilter?: boolean;
29
+ }): {
27
30
  content: string;
28
31
  error: boolean;
29
32
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-satori-ai",
3
3
  "description": "基于 Satori 适配器的智能对话插件,具备用户画像、长期记忆、常识管理和好感度系统",
4
- "version": "1.3.8",
4
+ "version": "1.3.9",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "types": "lib/index.d.ts",