koishi-plugin-satori-ai 1.3.4 → 1.3.6

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.
@@ -0,0 +1,24 @@
1
+ import { Context, Session } from 'koishi';
2
+ import { Sat } from './types';
3
+ export declare class BroadcastManager {
4
+ private ctx;
5
+ private config;
6
+ private idCounter;
7
+ private broadcastMessages;
8
+ constructor(ctx: Context, cfg: Sat.Config);
9
+ createBroadcast(message: string, img: boolean): Promise<string>;
10
+ deleteBroadcast(id: string): Promise<string>;
11
+ seedBroadcast(session: Session): Promise<void>;
12
+ getBroadcastList(): Promise<string>;
13
+ }
14
+ export declare class broadcastMessage {
15
+ private ctx;
16
+ private config;
17
+ message: string;
18
+ private alreadySentChannels;
19
+ setTime: Date;
20
+ private img;
21
+ constructor(ctx: Context, cfg: Sat.Config, message: string, img: boolean);
22
+ sendMessage(session: Session): Promise<void>;
23
+ getAlreadySentChannels(): string;
24
+ }
@@ -30,8 +30,7 @@ declare class OneTouchSingleGame extends abstractGameSingleGame {
30
30
  private buildMyTurnBonusMessage;
31
31
  private processAiTurn;
32
32
  private buildAiTurnBonusMessage;
33
- private applyEffectToEnemy;
34
- private applyEffectToSelf;
33
+ private applyEffect;
35
34
  private checkCombo;
36
35
  private buildResultMessage;
37
36
  private aiSearchEntrance;
@@ -42,6 +41,7 @@ declare class OneTouchSingleGame extends abstractGameSingleGame {
42
41
  private evaluateState;
43
42
  private generateChat;
44
43
  private instuction;
44
+ private skillList;
45
45
  }
46
46
  export declare class OneTouchGame extends abstractGame<OneTouchSingleGame> {
47
47
  constructor();
package/lib/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Context, Session } from 'koishi';
2
2
  import { Sat, User } from './types';
3
3
  import Puppeteer from 'koishi-plugin-puppeteer';
4
+ import { BroadcastManager } from './broadcast';
4
5
  export declare let puppeteer: Puppeteer | null;
5
6
  export declare function refreshPuppeteer(ctx: Context): void;
6
7
  export declare class SAT extends Sat {
@@ -11,6 +12,7 @@ export declare class SAT extends Sat {
11
12
  private ChannelParallelCount;
12
13
  private onlineUsers;
13
14
  private moodManager;
15
+ broadcastManager: BroadcastManager;
14
16
  private usersToWarn;
15
17
  private game;
16
18
  constructor(ctx: Context, config: Sat.Config);
package/lib/index.js CHANGED
@@ -33,7 +33,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
33
33
  // src/locales/zh.yml
34
34
  var require_zh = __commonJS({
35
35
  "src/locales/zh.yml"(exports, module2) {
36
- module2.exports = { commands: { sat: { description: "AI聊天", messages: { "no-prompt": "你好。使用说明可以看我的空间哦。", tooManyEnglishLetters: "请不要用这么多英文......", err: "寄!{0}", tooLong: "你的话太多了。", content_tooLong: "这个问题有点复杂,你还是去问别人吧。", "duplicate-dialogue": "这个刚刚说过了吧......", online: "思考中,请再等一会!", "no-response": "我不知道你在说什么……", update_level_succeed: "用户等级已更新为{0}", exceeds: "已经差不多够了吧?请明天再来。", usage: "今日次数{0}/{1}", hatMan: "叮!帽子先生保护了你的好感度,快说谢谢帽子先生吧!", rockBottom: "叮!谷底小石保护了你的好感度,快说谢谢谷底小石吧!", not_good_mood: "别得寸进尺……(好感↓)", pocket_money: "心情不错,给你点零花钱吧~(获得了{0}p点)", warning: "<at id={0}/>", block1: "我讨厌你!", block2: "我讨厌你们!" } }, "sat.clear": { description: "清空当前频道会话", messages: { clean: "已清空当前会话。", Allclean: "已清空所有会话。" } }, "sat.common_sense": { description: "添加常识", messages: { "no-prompt": "你想让我知道什么?", succeed: "我知道了,{0}" } } } };
36
+ module2.exports = { commands: { sat: { description: "AI聊天", messages: { "no-prompt": "你好。使用说明可以看我的空间哦。", tooManyEnglishLetters: "请不要用这么多英文......", err: "寄!{0}", tooLong: "你的话太多了。", content_tooLong: "这个问题有点复杂,你还是去问别人吧。", "duplicate-dialogue": "这个刚刚说过了吧......", online: "思考中,请再等一会!", "no-response": "我不知道你在说什么……", update_level_succeed: "用户等级已更新为{0}", exceeds: "已经差不多够了吧?请明天再来。", usage: "今日次数{0}/{1}", hatMan: "叮!帽子先生保护了你的好感度,快说谢谢帽子先生吧!", rockBottom: "叮!谷底小石保护了你的好感度,快说谢谢谷底小石吧!", not_good_mood: "别得寸进尺……(好感↓)", pocket_money: "心情不错,给你点零花钱吧~(获得了{0}p点)", warning: "<at id={0}/>", block1: "我讨厌你!", block2: "我讨厌你们!" } }, "sat.clear": { description: "清空当前频道会话", messages: { clean: "已清空当前会话。", Allclean: "已清空所有会话。" } }, "sat.common_sense": { description: "添加常识", messages: { "no-prompt": "你想让我知道什么?", succeed: "我知道了,{0}" } }, "sat.broadcast": { description: "广播一条消息,在每个生效群收到首条消息时会推送", options: { delete: "删除一条广播,参数为广播的ID", list: "查看当前所有广播", img: "使用puppeteer图片化广播消息" } } } };
37
37
  }
38
38
  });
39
39
 
@@ -46,7 +46,7 @@ __export(src_exports, {
46
46
  refreshPuppeteer: () => refreshPuppeteer
47
47
  });
48
48
  module.exports = __toCommonJS(src_exports);
49
- var import_koishi13 = require("koishi");
49
+ var import_koishi14 = require("koishi");
50
50
  var path7 = __toESM(require("path"));
51
51
 
52
52
  // src/api.ts
@@ -255,7 +255,7 @@ function processPrompt(prompt) {
255
255
  prompt = prompt.replace(/\*\*/g, "");
256
256
  if (!prompt)
257
257
  return "**";
258
- return prompt;
258
+ return prompt.trim();
259
259
  }
260
260
  __name(processPrompt, "processPrompt");
261
261
  function filterResponse(prompt, words) {
@@ -607,7 +607,7 @@ var MemoryManager = class {
607
607
  return acc;
608
608
  }, []);
609
609
  const filtered = sentences.filter((sentence) => !filterWords.some((word) => sentence.includes(word))).join("");
610
- const result = filtered.replace(/([,、])\1+/g, "$1").replace(/^[,。!?;,.!?]+/, "").trim();
610
+ const result = filtered.replace(/([,、…])\1+/g, "$1").replace(/^[,。!?;,.!?]+/, "").trim();
611
611
  return result || content;
612
612
  }
613
613
  // 更新短期记忆
@@ -1028,6 +1028,7 @@ function createMiddleware(ctx, sat, config) {
1028
1028
  return async (session, next) => {
1029
1029
  if (config.enable_favorability && config.enable_warning && session.channelId === config.warning_group)
1030
1030
  sat.getWarningList(session);
1031
+ await sat.broadcastManager.seedBroadcast(session);
1031
1032
  if (!isSpecialMessage(session))
1032
1033
  await sat.handleChannelMemoryManager(session);
1033
1034
  if (config.private && isPrivateSession(session)) {
@@ -1217,6 +1218,10 @@ var Sat = class extends import_koishi5.Service {
1217
1218
  max_pocket_money: import_koishi5.Schema.number().default(400).description("随机p点最大值"),
1218
1219
  pocket_money_cost: import_koishi5.Schema.number().default(2).description("消耗心情换p点的心情值")
1219
1220
  }).description("好感度拓展:心情设置(需要开启好感度模块才能生效)"),
1221
+ import_koishi5.Schema.object({
1222
+ Broadcast_block_channel: import_koishi5.Schema.array(String).description("不提供广播的频道id"),
1223
+ waiting_time: import_koishi5.Schema.number().default(1440).description("广播在缓存中等待的最大时间(分钟)(超过时间后没有触发会不再推送)")
1224
+ }).description("广播设置(发出后在每个生效群收到首条消息时会推送)"),
1220
1225
  import_koishi5.Schema.object({
1221
1226
  enable_game: import_koishi5.Schema.boolean().default(false).description("是否开启游戏模块"),
1222
1227
  game_block_channel: import_koishi5.Schema.array(String).description("不提供游戏的频道id"),
@@ -1292,12 +1297,11 @@ var UserPortraitManager = class {
1292
1297
  return [{
1293
1298
  role: "user",
1294
1299
  content: `你是一个角色扮演智能体工作流中的一环,请根据以下信息更新用户画像。需包括:
1295
- 1. 基本信息(性别、年龄、生日等)
1300
+ 1. 基本信息(性别、年龄、生日等,不要遗漏或改动已有的信息)
1296
1301
  2. 生活习惯(作息等)
1297
1302
  3. 反感点(如有)
1298
1303
  4. 对AI的期望(从对话历史中推断)
1299
1304
  5. 用户希望记住的信息(如有)
1300
- 6. 需要短期记忆的信息(如有)
1301
1305
 
1302
1306
  用户名:${user.usersname}
1303
1307
  你与用户的关系:${level}
@@ -1310,9 +1314,7 @@ ${history}
1310
1314
  注意事项:
1311
1315
  ·用户一定是人类,其他情况是角色扮演
1312
1316
  ·根据发言修正历史画像内容,但是历史画像中与发言无关的部分必须保留
1313
- ·除非用户要求,否则不要删除基本信息中的内容
1314
1317
  ·尤其注意用户说“记住”的部分,可能是用户希望记录的信息
1315
- ·历史画像中的需要短期记忆的信息不需要保留,只需要删除旧的添加新的
1316
1318
  ·因为在角色扮演中,用户可能会说出不符合事实的信息,需要根据事实推断,避免盲目相信或主观臆测
1317
1319
  ·使用尽可能简洁的表达
1318
1320
  ·保留不确定性的表述(如"可能"、"似乎"、"用户自称")
@@ -1448,7 +1450,6 @@ var MoodManager = class {
1448
1450
  const userId = user.userid;
1449
1451
  if (!this.moodMap.has(userId))
1450
1452
  this.initUser(userId);
1451
- await this.checkDailyReset(userId);
1452
1453
  let effect = this.config.value_of_input_mood;
1453
1454
  switch (favorabilityLevel) {
1454
1455
  case "厌恶":
@@ -1484,7 +1485,6 @@ var MoodManager = class {
1484
1485
  const userId = user.userid;
1485
1486
  if (!this.moodMap.has(userId))
1486
1487
  this.initUser(userId);
1487
- await this.checkDailyReset(userId);
1488
1488
  let effect = this.config.value_of_output_mood;
1489
1489
  switch (favorabilityLevel) {
1490
1490
  case "厌恶":
@@ -1514,7 +1514,7 @@ var MoodManager = class {
1514
1514
  return;
1515
1515
  }
1516
1516
  // 应用心情变化
1517
- applyMoodChange(user, delta) {
1517
+ async applyMoodChange(user, delta) {
1518
1518
  if (!this.config.enable_mood)
1519
1519
  return;
1520
1520
  const userId = user.userid;
@@ -1528,6 +1528,7 @@ var MoodManager = class {
1528
1528
  mood: newMood,
1529
1529
  lastUpdate: Date.now()
1530
1530
  });
1531
+ await this.checkDailyReset(userId);
1531
1532
  return;
1532
1533
  }
1533
1534
  // 获取心情等级
@@ -2171,7 +2172,7 @@ var import_koishi11 = require("koishi");
2171
2172
  var logger10 = new import_koishi11.Logger("satori-game-onetouch");
2172
2173
  var SKILL_MAP = {
2173
2174
  // 基础技能
2174
- "-1": { name: "无效" },
2175
+ "-1": {},
2175
2176
  "1": { pierceDamage: 1, bleed: 3, name: "锥刺" },
2176
2177
  //特性:流血
2177
2178
  "2": { pierceDamage: 1, stun: true, name: "点穴" },
@@ -2203,13 +2204,13 @@ var SKILL_MAP = {
2203
2204
  "4+6": { shield: 2, heal: 5, selfbleed: -3, name: "固守" },
2204
2205
  "8+8": { damage: 13, damageTimes: 2, selfStun: true, name: "双持" },
2205
2206
  "1+2": { pierceDamage: 3, vulnerablility: 3, stun: true, name: "弱点刺击" },
2206
- "2+8": { damage: 8, stun: true, selfStun: true, addLeft: 1, addRight: 9, name: "点射" },
2207
+ "2+8": { damage: 12, stun: true, selfStun: true, addLeft: 1, addRight: 9, name: "点射" },
2207
2208
  "3+4": { name: "防御反击", shield: 1, counterAttack: 15 },
2208
2209
  "7+7": { pierceDamage: 7, destroyShield: 5, name: "穿龙枪" },
2209
2210
  "7+8": { pierceDamage: 13, destroyShield: 3, selfStun: true, name: "穿甲弹" },
2210
2211
  "2+6": { damage: 5, heal: 6, selfbleed: -1, selfstrengthChange: 1, stun: true, name: "点辰" },
2211
2212
  "3+7": { name: "混沌", counterAttack: 7, destroyShield: 2, addLeft: 9, addRight: 1 },
2212
- "0+9": { name: "将大局逆转吧", revwersalOfStrength: true },
2213
+ "0+9": { name: "将大局逆转吧", revwersalOfStrength: true, selfstrengthChange: 2, strengthChange: -1 },
2213
2214
  "0+0": { name: "华丽收场", bleed: 5, selfstrengthChange: -99, magnificentEnd: true }
2214
2215
  };
2215
2216
  var OneTouchSingleGame = class extends abstractGameSingleGame {
@@ -2266,17 +2267,18 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2266
2267
  例如"左 右"表示用你的左手触碰对方的右手
2267
2268
  注:
2268
2269
  发送"游戏规则"查看游戏规则
2270
+ 发送"技能列表"查看技能列表
2269
2271
  发送"结束游戏"退出游戏`);
2270
2272
  }
2271
2273
  // 结束游戏,返回结果
2272
2274
  endGame = async () => {
2273
2275
  if (this.winningFlag === 4 /* pending */ || this.winningFlag === 2 /* lose */) {
2274
2276
  this.bonus = Math.abs(Math.floor(this.level * 0.2 * this.bonus));
2275
- this.bonus -= Math.floor(this.level * this.level * (Math.random() * 2 + 2) + 200);
2277
+ this.bonus -= Math.floor(this.level * this.level * (Math.random() * 2 + 2) + 50);
2276
2278
  this.bonus = Math.min(this.bonus, 0);
2277
2279
  }
2278
2280
  if (this.winningFlag === 1 /* win */) {
2279
- this.bonus = Math.floor(this.level * this.bonus * 0.2 * (Math.random() * 1 + 1));
2281
+ this.bonus = Math.floor(this.level * this.bonus * 0.1 * (Math.random() * 1 + 1));
2280
2282
  }
2281
2283
  const finalBonus = this.bonus;
2282
2284
  super.endGame();
@@ -2287,7 +2289,7 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2287
2289
  left: this.player.left,
2288
2290
  right: this.player.right,
2289
2291
  hp: this.baseHP + level * this.playerLevelHP,
2290
- shield: Math.round(level / 2),
2292
+ shield: Math.round(6 - level / 2),
2291
2293
  strength: 0,
2292
2294
  bleed: 0,
2293
2295
  counterAttack: 0,
@@ -2309,6 +2311,8 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2309
2311
  async processInput(input) {
2310
2312
  if (input === "游戏规则")
2311
2313
  return await wrapInHTML2(this.instuction);
2314
+ if (input === "技能列表")
2315
+ return await wrapInHTML2(this.skillList);
2312
2316
  if (this.turnCount === 0)
2313
2317
  this.initState(this.level);
2314
2318
  this.turnCount++;
@@ -2369,11 +2373,11 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2369
2373
  judgeEnd() {
2370
2374
  if (this.ai.hp <= 0) {
2371
2375
  this.winningFlag = 1 /* win */;
2372
- return `你赢了!发送结束游戏退出`;
2376
+ return `你赢了!发送"结束游戏"退出`;
2373
2377
  }
2374
2378
  if (this.player.hp <= 0) {
2375
2379
  this.winningFlag = 2 /* lose */;
2376
- return `你输了!发送结束游戏退出`;
2380
+ return `你输了!发送"结束游戏"退出`;
2377
2381
  }
2378
2382
  }
2379
2383
  processPlayerTurn(handA, handB) {
@@ -2382,8 +2386,8 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2382
2386
  }
2383
2387
  if (this.player.status === 1 /* Stunned */) {
2384
2388
  this.player.status = 2 /* lastStunned */;
2385
- this.player = this.applyEffectToSelf(this.ai, this.player, SKILL_MAP["-1"]);
2386
- return "你被眩晕,跳过回合";
2389
+ this.applyEffect(this.player, this.ai, SKILL_MAP["-1"], false);
2390
+ return "你被眩晕,跳过回合" + this.buildResultMessage(SKILL_MAP["-1"], false, this.player, this.ai);
2387
2391
  }
2388
2392
  const sum = (handA + handB) % 10;
2389
2393
  this.player[handA === this.player.left ? "left" : "right"] = sum;
@@ -2398,10 +2402,7 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
2398
2402
  this.comboCombos = 0;
2399
2403
  }
2400
2404
  const bonusMessage = this.buildMyTurnBonusMessage(effect, isCombo);
2401
- const playerState = this.player;
2402
- const aiState = this.ai;
2403
- this.ai = this.applyEffectToEnemy(playerState, aiState, effect, !!combo);
2404
- this.player = this.applyEffectToSelf(aiState, playerState, effect);
2405
+ this.applyEffect(this.player, this.ai, effect, !!combo);
2405
2406
  return this.buildResultMessage(effect, isCombo, this.player, this.ai) + (bonusMessage ? `
2406
2407
 
2407
2408
  ${bonusMessage}` : "");
@@ -2440,7 +2441,7 @@ ${bonusMessage}` : "");
2440
2441
  bonusMessage += `流血打击!获得${effectBonus}点分数!
2441
2442
  `;
2442
2443
  }
2443
- if ((effect.shield || 0) + this.player.shield >= 5) {
2444
+ if (effect.shield && (effect.shield || 0) + this.player.shield >= 5) {
2444
2445
  const effectBonus = Math.round(((effect.shield || 0) + this.player.shield) * 2);
2445
2446
  this.singleBonus += effectBonus;
2446
2447
  bonusMessage += `强效护盾!获得${effectBonus}点分数!
@@ -2477,7 +2478,7 @@ ${bonusMessage}` : "");
2477
2478
  `;
2478
2479
  }
2479
2480
  if (effect.revwersalOfStrength && this.player.strength <= this.ai.strength - 5) {
2480
- const effectBonus = Math.round((this.ai.strength - this.player.strength) * 3);
2481
+ const effectBonus = Math.min((this.ai.strength - this.player.strength) * 3, 100);
2481
2482
  this.singleBonus += effectBonus;
2482
2483
  bonusMessage += `逆转大局!获得${effectBonus}点分数!
2483
2484
  `;
@@ -2495,7 +2496,7 @@ ${bonusMessage}` : "");
2495
2496
  bonusMessage += `压倒性的优势!获得${effectBonus}点分数!本回合分数*2!
2496
2497
  `;
2497
2498
  }
2498
- if (effect.magnificentEnd && this.ai.bleed > 4) {
2499
+ if (effect.magnificentEnd && this.ai.bleed > 1) {
2499
2500
  const effectBonus = Math.round(this.ai.bleed * 1.5);
2500
2501
  this.singleBonusMultiplier *= effectBonus;
2501
2502
  this.bonus *= 2;
@@ -2518,8 +2519,8 @@ ${bonusMessage}` : "");
2518
2519
  }
2519
2520
  if (this.ai.status === 1 /* Stunned */) {
2520
2521
  this.ai.status = 2 /* lastStunned */;
2521
- this.ai = this.applyEffectToSelf(this.player, this.ai, SKILL_MAP["-1"]);
2522
- return "被眩晕,跳过回合,本回合分数奖励继承到下一回合";
2522
+ this.applyEffect(this.ai, this.player, SKILL_MAP["-1"], false);
2523
+ return "被眩晕,跳过回合,本回合分数奖励继承到下一回合" + this.buildResultMessage(SKILL_MAP["-1"], false, this.ai, this.player);
2523
2524
  }
2524
2525
  const sum = (handA + handB) % 10;
2525
2526
  this.ai[handA === this.ai.left ? "left" : "right"] = sum;
@@ -2530,11 +2531,8 @@ ${bonusMessage}` : "");
2530
2531
  isCombo = true;
2531
2532
  effect = { ...combo };
2532
2533
  }
2533
- const playerState = this.player;
2534
- const aiState = this.ai;
2535
2534
  const bonusMessage = this.buildAiTurnBonusMessage(effect);
2536
- this.player = this.applyEffectToEnemy(aiState, playerState, effect, !!combo);
2537
- this.ai = this.applyEffectToSelf(playerState, aiState, effect);
2535
+ this.applyEffect(this.ai, this.player, effect, !!combo);
2538
2536
  return handA + "碰" + handB + "," + this.buildResultMessage(effect, isCombo, this.ai, this.player) + (bonusMessage ? `
2539
2537
 
2540
2538
  ${bonusMessage}` : "");
@@ -2587,50 +2585,31 @@ ${bonusMessage}` : "");
2587
2585
  // destroyShield?: number // 破坏护盾
2588
2586
  // weakStun?: boolean // 弱眩晕
2589
2587
  // strengthChange?: number // 力量变化
2590
- applyEffectToEnemy(self, target, effect, isCombo) {
2588
+ // heal?: number // 治疗
2589
+ // shield?: number // 护盾
2590
+ // selfbleed?: number // 自身流血
2591
+ // selfStun?: boolean // 自身眩晕
2592
+ // selfstrengthChange?: number // 自身力量变化
2593
+ applyEffect(self, enemy, effect, isCombo) {
2594
+ if (effect.revwersalOfStrength) {
2595
+ const temp = self.strength;
2596
+ self.strength = enemy.strength;
2597
+ enemy.strength = temp;
2598
+ }
2591
2599
  if (effect.pierceDamage)
2592
- target.hp -= Math.max(effect.pierceDamage + (self.strength || 0), 0);
2600
+ enemy.hp -= Math.max(effect.pierceDamage + (self.strength || 0), 0);
2593
2601
  if (effect.destroyShield)
2594
- target.shield = Math.max(0, target.shield - effect.destroyShield);
2602
+ enemy.shield = Math.max(0, enemy.shield - effect.destroyShield);
2595
2603
  if (effect.bleed)
2596
- target.bleed += effect.bleed;
2604
+ enemy.bleed += effect.bleed;
2597
2605
  if (effect.strengthChange)
2598
- target.strength = target.strength + effect.strengthChange;
2606
+ enemy.strength = enemy.strength + effect.strengthChange;
2599
2607
  if (effect.addLeft)
2600
- target.left = (target.left + effect.addLeft) % 10;
2608
+ enemy.left = (enemy.left + effect.addLeft) % 10;
2601
2609
  if (effect.addRight)
2602
- target.right = (target.right + effect.addRight) % 10;
2610
+ enemy.right = (enemy.right + effect.addRight) % 10;
2603
2611
  if (effect.vulnerablility)
2604
- target.vulnerablility = (target.vulnerablility || 0) + effect.vulnerablility;
2605
- if (effect.damage) {
2606
- effect.damageTimes = effect.damageTimes || 1;
2607
- for (let i = 0; i < effect.damageTimes; i++) {
2608
- const blocked = target.shield > 0;
2609
- target.shield = Math.max(0, target.shield - (isCombo ? 2 : 1));
2610
- if (!blocked) {
2611
- target.hp -= Math.round(Math.max(0, effect.damage + (self.strength || 0)) * (target.vulnerablility ? 1.5 : 1));
2612
- if (effect.weakStun && target.status !== 2 /* lastStunned */) {
2613
- target.status = 1 /* Stunned */;
2614
- }
2615
- }
2616
- }
2617
- }
2618
- if (effect.revwersalOfStrength)
2619
- target.strength = self.strength;
2620
- if (effect.magnificentEnd) {
2621
- target.hp -= target.bleed * (target.bleed + 1) / 2;
2622
- target.bleed = 0;
2623
- }
2624
- if (effect.stun && target.status !== 2 /* lastStunned */)
2625
- target.status = 1 /* Stunned */;
2626
- return target;
2627
- }
2628
- // heal?: number // 治疗
2629
- // shield?: number // 护盾
2630
- // selfbleed?: number // 自身流血
2631
- // selfStun?: boolean // 自身眩晕
2632
- // selfstrengthChange?: number // 自身力量变化
2633
- applyEffectToSelf(enemy, self, effect) {
2612
+ enemy.vulnerablility = (enemy.vulnerablility || 0) + effect.vulnerablility;
2634
2613
  if (effect.heal)
2635
2614
  self.hp += effect.heal;
2636
2615
  if (effect.shield)
@@ -2641,24 +2620,41 @@ ${bonusMessage}` : "");
2641
2620
  self.left = (self.left + effect.addSelfLeft) % 10;
2642
2621
  if (effect.addSelfRight)
2643
2622
  self.right = (self.right + effect.addSelfRight) % 10;
2623
+ if (effect.damage) {
2624
+ effect.damageTimes = effect.damageTimes || 1;
2625
+ for (let i = 0; i < effect.damageTimes; i++) {
2626
+ const blocked = enemy.shield > 0;
2627
+ enemy.shield = Math.max(0, enemy.shield - (isCombo ? 2 : 1));
2628
+ if (!blocked) {
2629
+ enemy.hp -= Math.round(Math.max(0, effect.damage + (self.strength || 0)) * (enemy.vulnerablility ? 1.5 : 1));
2630
+ if (effect.weakStun && enemy.status !== 2 /* lastStunned */) {
2631
+ enemy.status = 1 /* Stunned */;
2632
+ }
2633
+ }
2634
+ }
2635
+ }
2644
2636
  if (self.counterAttack)
2645
2637
  self.counterAttack = 0;
2646
2638
  if (effect.counterAttack)
2647
2639
  self.counterAttack = effect.counterAttack;
2648
2640
  if (enemy.counterAttack > 0 && (effect.damage > 0 || effect.pierceDamage > 0))
2649
2641
  self.hp -= Math.max(enemy.counterAttack + (enemy.strength || 0), 0);
2650
- if (effect.revwersalOfStrength)
2651
- self.strength = enemy.strength;
2652
- if (effect.selfStun && self.status !== 2 /* lastStunned */)
2653
- self.status = 1 /* Stunned */;
2654
2642
  if (effect.selfbleed)
2655
- self.bleed = self.bleed + effect.selfbleed;
2643
+ self.bleed += effect.selfbleed;
2656
2644
  if (self.bleed > 0)
2657
2645
  self.hp -= self.bleed;
2658
2646
  self.bleed = Math.max(0, self.bleed - 1);
2647
+ if (effect.magnificentEnd) {
2648
+ enemy.hp -= enemy.bleed * (enemy.bleed + 1) / 2;
2649
+ enemy.bleed = 0;
2650
+ }
2659
2651
  if (self.vulnerablility)
2660
2652
  self.vulnerablility = Math.max(0, self.vulnerablility - 1);
2661
- return self;
2653
+ if (effect.stun && enemy.status !== 2 /* lastStunned */)
2654
+ enemy.status = 1 /* Stunned */;
2655
+ if (effect.selfStun && self.status !== 2 /* lastStunned */)
2656
+ self.status = 1 /* Stunned */;
2657
+ return;
2662
2658
  }
2663
2659
  checkCombo(a, b) {
2664
2660
  const key = `${Math.min(a, b)}+${Math.max(a, b)}`;
@@ -2668,6 +2664,8 @@ ${bonusMessage}` : "");
2668
2664
  let msg = [];
2669
2665
  if (effect.name)
2670
2666
  msg.push(`${effect.name}!`);
2667
+ if (effect.revwersalOfStrength)
2668
+ msg.push(`双方力量反转!`);
2671
2669
  if (effect.pierceDamage)
2672
2670
  msg.push(`对对方造成穿刺伤害${Math.max(0, effect.pierceDamage + (self.strength || 0))}`);
2673
2671
  if (effect.damage)
@@ -2729,7 +2727,7 @@ ${bonusMessage}` : "");
2729
2727
  ];
2730
2728
  const newState = this.simulateMove(move, simulatedState, 1);
2731
2729
  const score = this.aiSearch(
2732
- this.level,
2730
+ Math.round(this.level / 2),
2733
2731
  false,
2734
2732
  newState,
2735
2733
  -Infinity,
@@ -2788,7 +2786,7 @@ ${bonusMessage}` : "");
2788
2786
  }
2789
2787
  return moves;
2790
2788
  }
2791
- // 深度克隆玩家状态
2789
+ // 克隆玩家状态
2792
2790
  cloneState(state) {
2793
2791
  return {
2794
2792
  left: state.left,
@@ -2797,6 +2795,8 @@ ${bonusMessage}` : "");
2797
2795
  shield: state.shield,
2798
2796
  strength: state.strength,
2799
2797
  bleed: state.bleed,
2798
+ counterAttack: state.counterAttack,
2799
+ vulnerablility: state.vulnerablility,
2800
2800
  status: state.status
2801
2801
  };
2802
2802
  }
@@ -2809,16 +2809,13 @@ ${bonusMessage}` : "");
2809
2809
  attacker.status = 0 /* Normal */;
2810
2810
  if (attacker.status === 1 /* Stunned */) {
2811
2811
  attacker.status = 2 /* lastStunned */;
2812
- attacker = this.applyEffectToSelf(defender, attacker, SKILL_MAP["-1"]);
2812
+ this.applyEffect(attacker, defender, SKILL_MAP["-1"], false);
2813
2813
  } else {
2814
2814
  const sum = (handA + handB) % 10;
2815
2815
  attacker[handA === attacker.left ? "left" : "right"] = sum;
2816
2816
  const combo = this.checkCombo(attacker.left, attacker.right);
2817
2817
  const effect = combo ? combo : SKILL_MAP[sum.toString()] || {};
2818
- const defenderState = defender;
2819
- const attackerState = attacker;
2820
- defender = this.applyEffectToEnemy(attackerState, defenderState, effect, !!combo);
2821
- attacker = this.applyEffectToSelf(defenderState, attackerState, effect);
2818
+ this.applyEffect(attacker, defender, effect, !!combo);
2822
2819
  }
2823
2820
  if (attackerIndex === 1) {
2824
2821
  const temp = attacker;
@@ -2848,11 +2845,7 @@ ${bonusMessage}` : "");
2848
2845
  if (player.hp < playerBaseHP / 8)
2849
2846
  score += Math.round(playerBaseHP / 4);
2850
2847
  score += Math.min(ai.strength * 5, 100);
2851
- score -= Math.min(player.strength * 5);
2852
- if (ai.strength < 0)
2853
- score += Math.round(ai.strength * 5);
2854
- if (player.strength < 0)
2855
- score -= Math.round(player.strength * 5);
2848
+ score -= Math.max(player.strength * 5, -100);
2856
2849
  score += ai.shield * 8;
2857
2850
  score -= player.shield * 8;
2858
2851
  score -= Math.min(Math.round(ai.bleed * ai.bleed / 2.5));
@@ -2879,10 +2872,10 @@ ${bonusMessage}` : "");
2879
2872
  if (this.lastScore < 9e4 && Score > 9e4) {
2880
2873
  return "我觉得你要输了哦~";
2881
2874
  }
2882
- if (this.lastScore < 0 && Score > 0) {
2875
+ if (this.lastScore < 0 && Score > 0 && Math.random() > 0.5) {
2883
2876
  return "局势发生变化了呢~";
2884
2877
  }
2885
- if (Score - this.lastScore > 10)
2878
+ if (Score - this.lastScore > 10 && Math.random() > 0.8)
2886
2879
  return "看招!";
2887
2880
  }
2888
2881
  instuction = `游戏说明:
@@ -2895,9 +2888,23 @@ ${bonusMessage}` : "");
2895
2888
  当自身两手手势相同时,无论选择左手还是右手最终发生变化的都是左手。
2896
2889
  玩家初始有"${this.baseHP} + ${this.playerLevelHP} * 难度"血量。
2897
2890
  ai初始有"${this.baseHP} + ${this.aiLevelHp} * 难度"血量。
2898
- 玩家初始有"难度 / 2"护盾,四舍五入取整。
2891
+ 玩家初始有"6 - 难度 / 2"护盾,四舍五入取整。
2899
2892
  血量没有上限,率先将对方血量减到零的人获胜:
2900
- 具体的技能设计如下:{
2893
+
2894
+ 游戏名称说明:
2895
+ 流血效果:每次到自己回合结束时,收到流血层数点伤害,不可被护盾阻挡,然后流血层数减1;
2896
+ 护盾效果:每一层护盾可阻挡下一次受到的普通伤害,如果伤害来源是组合技则消耗两层护盾(若仅有一层则消耗一层)。护盾上限为五层。
2897
+ 眩晕效果:跳过自己的下一个回合,若上回合已经被眩晕,则本回合不受眩晕影响(即不可被连续眩晕)
2898
+ 弱眩晕效果:若对方没有护盾,则眩晕对方一回合
2899
+ 反击:下一回合若对方行动中有攻击,则对方攻击前受到反击层数点穿刺伤害,此效果受力量加成,且仅持续一回合
2900
+ 穿刺伤害:不被护盾影响的伤害(不会消耗护盾)
2901
+ 力量效果:每有一点力量,每次造成的伤害+1,若为负数则减一
2902
+ 易伤效果:受到的普通伤害+50%,自己的回合结束时减少一层
2903
+ 组合技:在触碰完成后,若你的两只手手势符合组合技条件,则触发组合技,组合技的效果会覆盖普通技能的效果,组合无序
2904
+ bonus: 当行动导致关键效果时,获得额外奖励,在ai回合结束时结算,若ai被眩晕则奖励继承到下一回合
2905
+ `;
2906
+ skillList = `
2907
+ 具体的技能设计如下:
2901
2908
  一:${SKILL_MAP["1"].name}:造成${SKILL_MAP["1"].pierceDamage}穿刺伤害,${SKILL_MAP["1"].bleed}流血;
2902
2909
  二:${SKILL_MAP["2"].name}:造成${SKILL_MAP["2"].pierceDamage}穿刺伤害,眩晕对方;
2903
2910
  三:${SKILL_MAP["3"].name}:造成${SKILL_MAP["3"].damage}伤害,获得${SKILL_MAP["3"].counterAttack}层反击;
@@ -2925,20 +2932,8 @@ ${bonusMessage}` : "");
2925
2932
  七+八:${SKILL_MAP["7+8"].name}:造成${SKILL_MAP["7+8"].pierceDamage}穿刺伤害,破坏对方${SKILL_MAP["7+8"].destroyShield}层护盾,眩晕自己
2926
2933
  六+二:${SKILL_MAP["2+6"].name}:造成${SKILL_MAP["2+6"].damage}伤害,恢复${SKILL_MAP["2+6"].heal}生命,自身${SKILL_MAP["2+6"].selfbleed}流血,自身增加${SKILL_MAP["2+6"].selfstrengthChange}力量,眩晕对方
2927
2934
  三+七:${SKILL_MAP["3+7"].name}:获得${SKILL_MAP["3+7"].counterAttack}层反击,破坏对方${SKILL_MAP["3+7"].destroyShield}层护盾,对方左手数值增加${SKILL_MAP["3+7"].addLeft},右手数值增加${SKILL_MAP["3+7"].addRight}
2928
- 九+十:${SKILL_MAP["0+9"].name}:逆转双方力量。
2935
+ 九+十:${SKILL_MAP["0+9"].name}:逆转双方力量,然后增加自身${SKILL_MAP["0+9"].selfstrengthChange}力量,对方${SKILL_MAP["0+9"].strengthChange}力量
2929
2936
  十+十:${SKILL_MAP["0+0"].name}:对对方造成${SKILL_MAP["0+0"].bleed}流血,自身${SKILL_MAP["0+0"].selfstrengthChange}力量,然后立即结算对方全部流血
2930
- }
2931
- 注:
2932
- 流血效果:每次到自己回合结束时,收到流血层数点伤害,不可被护盾阻挡,然后流血层数减1;
2933
- 护盾效果:每一层护盾可阻挡下一次受到的普通伤害,如果伤害来源是组合技则消耗两层护盾(若仅有一层则消耗一层)。护盾上限为五层。
2934
- 眩晕效果:跳过自己的下一个回合,若上回合已经被眩晕,则本回合不受眩晕影响(即不可被连续眩晕)
2935
- 弱眩晕效果:若对方没有护盾,则眩晕对方一回合
2936
- 反击:下一回合若对方行动中有攻击,则对方攻击前受到反击层数点穿刺伤害,此效果受力量加成,且仅持续一回合
2937
- 穿刺伤害:不被护盾影响的伤害(不会消耗护盾)
2938
- 力量效果:每有一点力量,每次造成的伤害+1,若为负数则减一
2939
- 易伤效果:受到的普通伤害+50%,自己的回合结束时减少一层
2940
- 组合技:两只手势符合组合技条件时触发组合技,组合技的效果会覆盖普通技能的效果,组合无序
2941
- bonus: 当行动导致关键效果时,获得额外奖励,在ai回合结束时结算,若ai被眩晕则奖励继承到下一回合
2942
2937
  `;
2943
2938
  };
2944
2939
  var OneTouchGame = class extends abstractGame {
@@ -3134,14 +3129,152 @@ var Game = class {
3134
3129
  }
3135
3130
  };
3136
3131
 
3132
+ // src/broadcast.ts
3133
+ var import_koishi13 = require("koishi");
3134
+ var logger12 = new import_koishi13.Logger("satori-ai-broadcast");
3135
+ var BroadcastManager = class {
3136
+ static {
3137
+ __name(this, "BroadcastManager");
3138
+ }
3139
+ ctx;
3140
+ config;
3141
+ idCounter = 0;
3142
+ broadcastMessages = /* @__PURE__ */ new Map();
3143
+ constructor(ctx, cfg) {
3144
+ this.ctx = ctx;
3145
+ this.config = cfg;
3146
+ this.idCounter = 0;
3147
+ ctx.command("sat.broadcast <text:text>", "推送广播", { authority: 4 }).alias("广播").option("delete", "-d <id:string>", { authority: 4 }).option("list", "-l", { authority: 4 }).option("img", "-i", { authority: 4 }).action(async ({ options }, prompt) => {
3148
+ refreshPuppeteer(this.ctx);
3149
+ if (options.list) {
3150
+ const list = this.broadcastMessages.size > 0 ? await this.getBroadcastList() : null;
3151
+ return list ? `${list}` : "当前没有广播";
3152
+ }
3153
+ if (options.delete) {
3154
+ return await this.deleteBroadcast(options.delete);
3155
+ } else {
3156
+ return await this.createBroadcast(prompt, options.img);
3157
+ }
3158
+ });
3159
+ }
3160
+ async createBroadcast(message, img) {
3161
+ const id = `broadcast-${this.idCounter++}`;
3162
+ const broadcast = new broadcastMessage(this.ctx, this.config, message, img);
3163
+ this.broadcastMessages.set(id, broadcast);
3164
+ logger12.info(`广播已创建 ID: ${id}`);
3165
+ return `广播已创建 ID: ${id}`;
3166
+ }
3167
+ async deleteBroadcast(id) {
3168
+ if (this.broadcastMessages.has(id)) {
3169
+ this.broadcastMessages.delete(id);
3170
+ logger12.info(`广播已删除 ID: ${id}`);
3171
+ return "已删除广播:" + id;
3172
+ } else {
3173
+ logger12.warn(`未找到广播 ID: ${id}`);
3174
+ return "未找到该广播";
3175
+ }
3176
+ }
3177
+ async seedBroadcast(session) {
3178
+ for (const [id, broadcast] of this.broadcastMessages.entries()) {
3179
+ if (broadcast.setTime.getTime() + 1e3 * 60 * this.config.waiting_time < Date.now()) {
3180
+ this.broadcastMessages.delete(id);
3181
+ logger12.info(`广播已过期 ID: ${id}`);
3182
+ continue;
3183
+ }
3184
+ await broadcast.sendMessage(session);
3185
+ }
3186
+ return;
3187
+ }
3188
+ async getBroadcastList() {
3189
+ const idList = Array.from(this.broadcastMessages.keys());
3190
+ const list = [];
3191
+ list.push("当前广播列表:");
3192
+ for (const id of idList) {
3193
+ const broadcast = this.broadcastMessages.get(id);
3194
+ if (broadcast) {
3195
+ const time = broadcast.setTime.toLocaleString("zh-CN", { hour12: false });
3196
+ const ddl = new Date(broadcast.setTime.getTime() + 1e3 * 60 * this.config.waiting_time).toLocaleString("zh-CN", { hour12: false });
3197
+ const message = broadcast.message;
3198
+ const alreadySentChannels = broadcast.getAlreadySentChannels();
3199
+ list.push(`ID: ${id}
3200
+ 消息: ${message}
3201
+ 已发送频道:
3202
+ ${alreadySentChannels}
3203
+ 创建时间: ${time}
3204
+ 过期时间: ${ddl}
3205
+ `);
3206
+ }
3207
+ }
3208
+ const result = list.length > 0 ? list.join("\n") : null;
3209
+ return result ? wrapInHTML3(result) : null;
3210
+ }
3211
+ };
3212
+ var broadcastMessage = class {
3213
+ static {
3214
+ __name(this, "broadcastMessage");
3215
+ }
3216
+ ctx;
3217
+ config;
3218
+ message;
3219
+ alreadySentChannels = /* @__PURE__ */ new Set();
3220
+ setTime;
3221
+ img;
3222
+ constructor(ctx, cfg, message, img) {
3223
+ this.message = message;
3224
+ this.alreadySentChannels = /* @__PURE__ */ new Set();
3225
+ this.ctx = ctx;
3226
+ this.config = cfg;
3227
+ this.img = img;
3228
+ this.setTime = /* @__PURE__ */ new Date();
3229
+ for (const channelId of this.config.Broadcast_block_channel) {
3230
+ this.alreadySentChannels.add(channelId);
3231
+ }
3232
+ }
3233
+ async sendMessage(session) {
3234
+ const channelId = session.channelId;
3235
+ if (this.alreadySentChannels.has(channelId))
3236
+ return;
3237
+ try {
3238
+ this.alreadySentChannels.add(channelId);
3239
+ if (this.img) {
3240
+ session.send(await wrapInHTML3(this.message));
3241
+ } else {
3242
+ session.send(this.message);
3243
+ }
3244
+ logger12.info(`向群 ${channelId} 广播: ${this.message}`);
3245
+ } catch (error) {
3246
+ logger12.error(`广播失败 ${channelId}: ${error}`);
3247
+ }
3248
+ }
3249
+ getAlreadySentChannels() {
3250
+ const alreadySentChannels = Array.from(this.alreadySentChannels).filter((channelId) => !this.config.Broadcast_block_channel.includes(channelId));
3251
+ return alreadySentChannels.length > 0 ? alreadySentChannels.join("\n") : "无";
3252
+ }
3253
+ };
3254
+ async function wrapInHTML3(str) {
3255
+ if (!puppeteer) {
3256
+ logger12.warn("puppeteer未就绪");
3257
+ return str;
3258
+ }
3259
+ return puppeteer.render(`<html><body>${str.replaceAll(/\n/g, "<BR>")}</body>
3260
+ <style>
3261
+ body {
3262
+ padding: 10px;
3263
+ display: inline-block;
3264
+ }
3265
+ </style>
3266
+ </html>`);
3267
+ }
3268
+ __name(wrapInHTML3, "wrapInHTML");
3269
+
3137
3270
  // src/index.tsx
3138
- var logger12 = new import_koishi13.Logger("satori-ai");
3271
+ var logger13 = new import_koishi14.Logger("satori-ai");
3139
3272
  var puppeteer = null;
3140
3273
  function refreshPuppeteer(ctx) {
3141
3274
  if (ctx.puppeteer) {
3142
3275
  puppeteer = ctx.puppeteer;
3143
3276
  } else {
3144
- logger12.warn("puppeteer未就绪");
3277
+ logger13.warn("puppeteer未就绪");
3145
3278
  }
3146
3279
  }
3147
3280
  __name(refreshPuppeteer, "refreshPuppeteer");
@@ -3157,6 +3290,7 @@ var SAT = class extends Sat {
3157
3290
  this.memoryManager = new MemoryManager(ctx, this.getMemoryConfig());
3158
3291
  this.portraitManager = new UserPortraitManager(ctx, config);
3159
3292
  this.moodManager = new MoodManager(ctx, config);
3293
+ this.broadcastManager = new BroadcastManager(ctx, config);
3160
3294
  ensureCensorFileExists(this.config.dataDir);
3161
3295
  ctx.middleware(createMiddleware(ctx, this, this.getMiddlewareConfig()));
3162
3296
  this.registerCommands(ctx);
@@ -3172,6 +3306,7 @@ var SAT = class extends Sat {
3172
3306
  ChannelParallelCount = /* @__PURE__ */ new Map();
3173
3307
  onlineUsers = [];
3174
3308
  moodManager;
3309
+ broadcastManager;
3175
3310
  usersToWarn = /* @__PURE__ */ new Map();
3176
3311
  game;
3177
3312
  getAPIConfig() {
@@ -3327,9 +3462,9 @@ var SAT = class extends Sat {
3327
3462
  const messages = generateAuxiliaryPrompt(prompt, response.content, user, this.getFavorabilityConfig());
3328
3463
  const result = await this.apiClient.auxiliaryChat(messages);
3329
3464
  if (result.error) {
3330
- logger12.error(`辅助判断失败:${result.content}`);
3465
+ logger13.error(`辅助判断失败:${result.content}`);
3331
3466
  } else {
3332
- logger12.info(`辅助判断:${result.content}`);
3467
+ logger13.info(`辅助判断:${result.content}`);
3333
3468
  return handleAuxiliaryResult(this.ctx, session, this.getFavorabilityConfig(), result.content);
3334
3469
  }
3335
3470
  }
@@ -3416,13 +3551,13 @@ var SAT = class extends Sat {
3416
3551
  await inputContentCheck(this.ctx, censored, session.userId, this.getFavorabilityConfig(), session, this.moodManager);
3417
3552
  }
3418
3553
  if (this.config.log_ask_response)
3419
- logger12.info(`用户 ${session.username}:${processedPrompt}`);
3554
+ logger13.info(`用户 ${session.username}:${processedPrompt}`);
3420
3555
  return censored;
3421
3556
  }
3422
3557
  // 生成回复
3423
3558
  async generateResponse(session, prompt) {
3424
3559
  if (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
3425
- logger12.info(`频道 ${session.channelId} 并发数过高(${this.getChannelParallelCount(session)}),${session.username}等待中...`);
3560
+ logger13.info(`频道 ${session.channelId} 并发数过高(${this.getChannelParallelCount(session)}),${session.username}等待中...`);
3426
3561
  }
3427
3562
  while (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
3428
3563
  this.updateChannelParallelCount(session, -1);
@@ -3430,7 +3565,7 @@ var SAT = class extends Sat {
3430
3565
  this.updateChannelParallelCount(session, 1);
3431
3566
  }
3432
3567
  const messages = await this.buildMessages(session, prompt);
3433
- logger12.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
3568
+ logger13.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
3434
3569
  const user = await getUser(this.ctx, session.userId);
3435
3570
  let response = await this.getChatResponse(user, messages);
3436
3571
  if (response.error)
@@ -3444,9 +3579,9 @@ var SAT = class extends Sat {
3444
3579
  let response = await this.apiClient.chat(user, messages);
3445
3580
  if (this.config.log_ask_response) {
3446
3581
  if (this.config.enable_favorability && this.config.enable_mood)
3447
- logger12.info(`Satori AI:(心情值:${this.moodManager.getMoodValue(user.userid)})${response.content}`);
3582
+ logger13.info(`Satori AI:(心情值:${this.moodManager.getMoodValue(user.userid)})${response.content}`);
3448
3583
  else
3449
- logger12.info(`Satori AI:${response.content}`);
3584
+ logger13.info(`Satori AI:${response.content}`);
3450
3585
  }
3451
3586
  if (this.config.reasoner_filter && !response.error)
3452
3587
  response = filterResponse(response.content, this.config.reasoner_filter_word.split("-"));
@@ -3470,7 +3605,7 @@ var SAT = class extends Sat {
3470
3605
  messages.push({ role: "user", content: prompt });
3471
3606
  let payload = messages.map((msg) => msg.role + ":" + msg.content).join("\n");
3472
3607
  if (this.config.log_system_prompt)
3473
- logger12.info(`系统提示:
3608
+ logger13.info(`系统提示:
3474
3609
  ${payload}`);
3475
3610
  return messages;
3476
3611
  }
@@ -3575,7 +3710,7 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
3575
3710
  response = `@${session.username} ` + response;
3576
3711
  }
3577
3712
  if (this.config.sentences_divide && response.length > 10) {
3578
- const sentences = splitSentences(response, this.config.min_sentences_length, this.config.max_sentences_length).map((text) => import_koishi13.h.text(text));
3713
+ const sentences = splitSentences(response, this.config.min_sentences_length, this.config.max_sentences_length).map((text) => import_koishi14.h.text(text));
3579
3714
  for (const sentence of sentences) {
3580
3715
  await session.send(sentence);
3581
3716
  await new Promise((resolve3) => setTimeout(resolve3, this.config.time_interval));
@@ -3588,7 +3723,7 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
3588
3723
  if (!this.config.enable_warning)
3589
3724
  return;
3590
3725
  if (auxiliaryResult.includes("好感↓")) {
3591
- logger12.info(`在群${session.channelId}中,${session.username}骚扰我!`);
3726
+ logger13.info(`在群${session.channelId}中,${session.username}骚扰我!`);
3592
3727
  this.usersToWarn.set(session.channelId, session.username);
3593
3728
  }
3594
3729
  }
package/lib/mood.d.ts CHANGED
@@ -9,7 +9,7 @@ export declare class MoodManager {
9
9
  private checkDailyReset;
10
10
  handleInputMoodChange(user: User, favorabilityLevel: string): Promise<void>;
11
11
  handleOutputMoodChange(user: User, favorabilityLevel: string): Promise<void>;
12
- applyMoodChange(user: User, delta: number): void;
12
+ applyMoodChange(user: User, delta: number): Promise<void>;
13
13
  getMoodLevel(userId: string): string;
14
14
  getMoodValue(userId: string): number;
15
15
  generateMoodPrompt(userId: string): string;
package/lib/types.d.ts CHANGED
@@ -240,6 +240,8 @@ export declare namespace Sat {
240
240
  warning_admin_id: string;
241
241
  maxRetryTimes: number;
242
242
  retry_delay_time: number;
243
+ Broadcast_block_channel: string[];
244
+ waiting_time: number;
243
245
  enable_game: boolean;
244
246
  game_block_channel: string[];
245
247
  enable_gobang: boolean;
package/lib/utils.d.ts CHANGED
@@ -29,3 +29,5 @@ export declare function filterResponse(prompt: string, words: string[]): {
29
29
  };
30
30
  export declare function addOutputCensor(session: Session, word: string, baseURL: string): void;
31
31
  export declare function updateUserPWithTicket(ctx: Context, user: User, adjustment: number): Promise<void>;
32
+ export declare function findLongestCommonSubstring(str1: string, str2: string): number;
33
+ export declare function countCommonChars(str1: string, str2: string): number;
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.4",
4
+ "version": "1.3.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "types": "lib/index.d.ts",