koishi-plugin-satori-ai 1.2.9 → 1.2.11

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/database.d.ts CHANGED
@@ -11,6 +11,7 @@ export declare function updateFavorability(ctx: Context, user: User, adjustment:
11
11
  export declare function updateUserLevel(ctx: Context, user: User, level: number): Promise<void>;
12
12
  export declare function updateUserUsage(ctx: Context, user: User, adjustment?: number): Promise<number | void>;
13
13
  export declare function updateUserItems(ctx: Context, user: User): Promise<void>;
14
+ export declare function updateUserP(ctx: Context, user: User, adjustment: number): Promise<void>;
14
15
  export declare function getUser(ctx: Context, userId: string): Promise<User | null>;
15
16
  export declare function ensureUserExists(ctx: Context, userId: string, username: string): Promise<User>;
16
17
  export declare function extendDatabase(ctx: Context): void;
@@ -1,15 +1,16 @@
1
1
  import { Context, Session } from 'koishi';
2
2
  import { User, FavorabilityLevel, FavorabilityConfig } from './types';
3
+ import { MoodManager } from './mood';
3
4
  import { Sat } from './types';
4
5
  export declare function handleFavorabilitySystem(ctx: Context, session: Session, config: FavorabilityConfig): Promise<string | void>;
5
6
  export declare function getFavorabilityLevel(user: User, config: FavorabilityConfig): FavorabilityLevel;
6
7
  export declare function generateLevelPrompt(level: FavorabilityLevel, config: FavorabilityConfig, user: User): string;
7
8
  export declare function generateAuxiliaryPrompt(prompt: string, responseContent: string, user: User, config: FavorabilityConfig): Sat.Msg[];
8
9
  export declare function handleAuxiliaryResult(ctx: Context, session: Session, config: FavorabilityConfig, responseContent: string): Promise<string | void>;
9
- export declare function inputContentCheck(ctx: Context, content: string, userid: string, config: FavorabilityConfig, session: Session): Promise<number>;
10
+ export declare function inputContentCheck(ctx: Context, content: string, userid: string, config: FavorabilityConfig, session: Session, moodManager: MoodManager): Promise<number>;
10
11
  export declare function outputContentCheck(ctx: Context, response: {
11
12
  content: string;
12
13
  error: boolean;
13
- }, userid: string, config: FavorabilityConfig, session: Session): Promise<number>;
14
+ }, userid: string, config: FavorabilityConfig, session: Session, moodManager: MoodManager): Promise<number>;
14
15
  export declare function ensureCensorFileExists(basePath: string): Promise<void>;
15
16
  export declare function applyFavorabilityEffect(ctx: Context, user: User, effect: number, session: Session): Promise<void>;
package/lib/game.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Session, Context } from 'koishi';
2
2
  import { Sat } from './types';
3
+ import { SAT } from './index';
3
4
  /**
4
5
  * 游戏总控类,管理所有可用游戏和命令
5
6
  */
@@ -10,9 +11,10 @@ export declare class Game {
10
11
  private context;
11
12
  private config;
12
13
  private sat;
13
- constructor(ctx: Context, cfg: Sat.Config, sat: Sat);
14
+ constructor(ctx: Context, cfg: Sat.Config, sat: SAT);
14
15
  private registerCommands;
15
16
  startGame(session: Session, gameName: string, args: string[]): Promise<"当前频道已经有游戏在进行中" | "没有这个游戏哦">;
16
17
  endGame(session: Session): Promise<string>;
17
18
  private selectGame;
19
+ private chat;
18
20
  }
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Session } from 'koishi';
2
- import { Sat } from './types';
2
+ import { Sat, User } from './types';
3
3
  export declare class SAT extends Sat {
4
4
  config: Sat.Config;
5
5
  private apiClient;
@@ -7,6 +7,7 @@ export declare class SAT extends Sat {
7
7
  private portraitManager;
8
8
  private ChannelParallelCount;
9
9
  private onlineUsers;
10
+ private moodManager;
10
11
  private game;
11
12
  constructor(ctx: Context, config: Sat.Config);
12
13
  private getAPIConfig;
@@ -24,9 +25,17 @@ export declare class SAT extends Sat {
24
25
  private updateChannelParallelCount;
25
26
  private getChannelParallelCount;
26
27
  private processInput;
27
- private generateResponse;
28
+ generateResponse(session: Session, prompt: string): Promise<{
29
+ content: string;
30
+ error: boolean;
31
+ }>;
32
+ getChatResponse(user: User, messages: Sat.Msg[]): Promise<{
33
+ content: string;
34
+ error: boolean;
35
+ }>;
28
36
  private buildMessages;
29
37
  private buildSystemPrompt;
38
+ private getThinkingPrompt;
30
39
  private formatResponse;
31
40
  private clearSession;
32
41
  private addCommonSense;
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: "叮!谷底小石保护了你的好感度,快说谢谢谷底小石吧!", 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点)", block1: "我讨厌你!", block2: "我讨厌你们!" } }, "sat.clear": { description: "清空当前频道会话", messages: { clean: "已清空当前会话。", Allclean: "已清空所有会话。" } }, "sat.common_sense": { description: "添加常识", messages: { "no-prompt": "你想让我知道什么?", succeed: "我知道了,{0}" } } } };
37
37
  }
38
38
  });
39
39
 
@@ -44,7 +44,7 @@ __export(src_exports, {
44
44
  default: () => src_default
45
45
  });
46
46
  module.exports = __toCommonJS(src_exports);
47
- var import_koishi7 = require("koishi");
47
+ var import_koishi8 = require("koishi");
48
48
  var path6 = __toESM(require("path"));
49
49
 
50
50
  // src/api.ts
@@ -52,6 +52,107 @@ var import_koishi2 = require("koishi");
52
52
 
53
53
  // src/utils.ts
54
54
  var import_koishi = require("koishi");
55
+
56
+ // src/database.ts
57
+ async function isTargetIdNotExists(ctx, userId) {
58
+ const users = await ctx.database.get("p_system", { userid: userId });
59
+ return users.length === 0;
60
+ }
61
+ __name(isTargetIdNotExists, "isTargetIdNotExists");
62
+ async function createUser(ctx, user) {
63
+ await ctx.database.create("p_system", {
64
+ userid: user.userid || "",
65
+ usersname: user.usersname || "",
66
+ p: user.p || 0,
67
+ favorability: user.favorability || 0,
68
+ userlevel: user.userlevel || 0,
69
+ usage: user.usage || 0,
70
+ lastChatTime: user.lastChatTime || (/* @__PURE__ */ new Date()).getDate(),
71
+ items: user.items || {}
72
+ });
73
+ }
74
+ __name(createUser, "createUser");
75
+ async function updateFavorability(ctx, user, adjustment) {
76
+ if (!user)
77
+ return;
78
+ let newValue;
79
+ if (typeof adjustment === "number")
80
+ newValue = user.favorability + adjustment;
81
+ else
82
+ newValue = user.favorability;
83
+ await ctx.database.set("p_system", { userid: user.userid }, { favorability: newValue });
84
+ }
85
+ __name(updateFavorability, "updateFavorability");
86
+ async function updateUserLevel(ctx, user, level) {
87
+ if (!user)
88
+ return;
89
+ level = level < 5 ? level : 4;
90
+ await ctx.database.set("p_system", { userid: user.userid }, { userlevel: level });
91
+ }
92
+ __name(updateUserLevel, "updateUserLevel");
93
+ async function updateUserUsage(ctx, user, adjustment = 1) {
94
+ if (!user)
95
+ return;
96
+ if (user.lastChatTime && (/* @__PURE__ */ new Date()).getDate() !== user.lastChatTime)
97
+ user.usage = 0;
98
+ await ctx.database.set("p_system", { userid: user.userid }, { usage: user.usage + adjustment });
99
+ await ctx.database.set("p_system", { userid: user.userid }, { lastChatTime: (/* @__PURE__ */ new Date()).getDate() });
100
+ return user.usage + adjustment;
101
+ }
102
+ __name(updateUserUsage, "updateUserUsage");
103
+ async function updateUserItems(ctx, user) {
104
+ if (!user)
105
+ return;
106
+ await ctx.database.set("p_system", { userid: user.userid }, { items: user.items });
107
+ }
108
+ __name(updateUserItems, "updateUserItems");
109
+ async function updateUserP(ctx, user, adjustment) {
110
+ if (!user)
111
+ return;
112
+ user.p = await ctx.database.get("p_system", { userid: user.userid })[0]?.p || user.p;
113
+ if (user.p + adjustment < 0)
114
+ adjustment = -user.p;
115
+ await ctx.database.set("p_system", { userid: user.userid }, { p: user.p + adjustment });
116
+ }
117
+ __name(updateUserP, "updateUserP");
118
+ async function getUser(ctx, userId) {
119
+ const users = await ctx.database.get("p_system", { userid: userId });
120
+ return users[0] || null;
121
+ }
122
+ __name(getUser, "getUser");
123
+ async function ensureUserExists(ctx, userId, username) {
124
+ const notExists = await isTargetIdNotExists(ctx, userId);
125
+ if (notExists) {
126
+ await createUser(ctx, {
127
+ userid: userId,
128
+ usersname: username,
129
+ p: 0,
130
+ favorability: 0,
131
+ userlevel: 0,
132
+ usage: 0,
133
+ lastChatTime: (/* @__PURE__ */ new Date()).getDate(),
134
+ items: {}
135
+ });
136
+ }
137
+ return getUser(ctx, userId);
138
+ }
139
+ __name(ensureUserExists, "ensureUserExists");
140
+ function extendDatabase(ctx) {
141
+ ctx.model.extend("p_system", {
142
+ id: "unsigned",
143
+ userid: "string",
144
+ usersname: "string",
145
+ p: "integer",
146
+ favorability: "integer",
147
+ userlevel: "integer",
148
+ usage: "integer",
149
+ lastChatTime: "integer",
150
+ items: "object"
151
+ }, { autoInc: true });
152
+ }
153
+ __name(extendDatabase, "extendDatabase");
154
+
155
+ // src/utils.ts
55
156
  var fs = __toESM(require("fs"));
56
157
  var path = __toESM(require("path"));
57
158
  var logger = new import_koishi.Logger("satori-utils");
@@ -89,39 +190,50 @@ function trimSlash(url) {
89
190
  return url.replace(/\/$/, "");
90
191
  }
91
192
  __name(trimSlash, "trimSlash");
92
- function splitSentences(text) {
93
- const parts = text.split(/(“[^”]*”|"[^"]*")/g);
94
- const result = [];
95
- for (let i = 0; i < parts.length; i++) {
96
- const part = parts[i];
97
- if (i % 2 === 1) {
98
- result.push(part);
193
+ function splitSentences(text, MIN_LENGTH, MAX_LENGTH) {
194
+ const PUNCTUATION_REGEX = /([。!?!?…]+)/g;
195
+ const rawSegments = text.split(PUNCTUATION_REGEX);
196
+ const initialSentences = [];
197
+ for (let i = 0; i < rawSegments.length; i += 2) {
198
+ const sentence = rawSegments[i]?.trim() || "";
199
+ const punctuation = rawSegments[i + 1]?.trim() || "";
200
+ if (sentence)
201
+ initialSentences.push(sentence + punctuation);
202
+ }
203
+ const finalSentences = [];
204
+ let currentSentence = "";
205
+ for (const sentence of initialSentences) {
206
+ const potentialLength = currentSentence.length + sentence.length;
207
+ if (sentence.length > MAX_LENGTH) {
208
+ if (currentSentence)
209
+ finalSentences.push(currentSentence);
210
+ finalSentences.push(sentence);
211
+ currentSentence = "";
212
+ continue;
213
+ }
214
+ if (potentialLength <= MAX_LENGTH) {
215
+ currentSentence += sentence;
216
+ if (currentSentence.length >= MIN_LENGTH && potentialLength >= MAX_LENGTH * 0.8) {
217
+ finalSentences.push(currentSentence);
218
+ currentSentence = "";
219
+ }
99
220
  } else {
100
- const outerSentences = splitOuterSentences(part);
101
- result.push(...outerSentences);
221
+ finalSentences.push(currentSentence);
222
+ currentSentence = sentence;
102
223
  }
103
224
  }
104
- return result.filter((s) => s.trim() !== "");
105
- }
106
- __name(splitSentences, "splitSentences");
107
- function splitOuterSentences(text) {
108
- const sentences = text.split(/(?<=[。!?!?])/g).filter((s) => s.trim());
109
- const result = [];
110
- let temp = "";
111
- for (let i = 0; i < sentences.length; i++) {
112
- if (i === sentences.length - 2) {
113
- temp = sentences[i] + sentences[i + 1];
114
- result.push(temp);
115
- break;
225
+ if (currentSentence)
226
+ finalSentences.push(currentSentence);
227
+ return finalSentences.reduce((result, sentence) => {
228
+ if (sentence.length < MIN_LENGTH && result.length > 0) {
229
+ result[result.length - 1] += sentence;
116
230
  } else {
117
- temp += sentences[i];
118
- result.push(temp);
119
- temp = "";
231
+ result.push(sentence);
120
232
  }
121
- }
122
- return result;
233
+ return result;
234
+ }, []);
123
235
  }
124
- __name(splitOuterSentences, "splitOuterSentences");
236
+ __name(splitSentences, "splitSentences");
125
237
  function probabilisticCheck(probability) {
126
238
  return Math.random() < probability;
127
239
  }
@@ -138,6 +250,9 @@ function processPrompt(prompt) {
138
250
  prompt = prompt.replace(/<[^>]*?avatar[^>]*>/g, "。回复:");
139
251
  prompt = prompt.replace(/<[^>]*?img[^>]*>/g, "[图片]");
140
252
  prompt = prompt.replace(/<[^>]*?name="([^\"]*)"[^>]*>/g, (_, name) => `@${name}`);
253
+ prompt = prompt.replace(/\*\*/g, "");
254
+ if (!prompt)
255
+ return "**";
141
256
  return prompt;
142
257
  }
143
258
  __name(processPrompt, "processPrompt");
@@ -149,12 +264,14 @@ function filterResponse(prompt, words) {
149
264
  }
150
265
  return part;
151
266
  }).join("");
267
+ if (filtered.includes("<think>") && !filtered.includes("</think>"))
268
+ return { content: "……", error: true };
152
269
  const regex = /<think>[\s\S]*?<\/think>/g;
153
270
  const filteredThink = filtered.replace(regex, "");
154
271
  const regex2 = /<think>|<\/think>/g;
155
272
  const filtered2 = filteredThink.replace(regex2, "");
156
273
  const trimmedResult = filtered2.trim();
157
- return trimmedResult === "" ? "……" : trimmedResult;
274
+ return trimmedResult === "" ? { content: "……", error: true } : { content: trimmedResult, error: false };
158
275
  }
159
276
  __name(filterResponse, "filterResponse");
160
277
  function addOutputCensor(session, word, baseURL) {
@@ -169,6 +286,14 @@ function addOutputCensor(session, word, baseURL) {
169
286
  session.send(`添加"${word}"成功`);
170
287
  }
171
288
  __name(addOutputCensor, "addOutputCensor");
289
+ async function updateUserPWithTicket(ctx, user, adjustment) {
290
+ if (!user)
291
+ return;
292
+ if (user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on") {
293
+ await updateUserP(ctx, user, adjustment);
294
+ }
295
+ }
296
+ __name(updateUserPWithTicket, "updateUserPWithTicket");
172
297
 
173
298
  // src/api.ts
174
299
  var logger2 = new import_koishi2.Logger("satori-api");
@@ -185,20 +310,26 @@ var APIClient = class {
185
310
  // 发送聊天请求
186
311
  async chat(user, messages) {
187
312
  if (user.userid == "Alice")
188
- return { content: "(系统)(abc)测试", error: false };
313
+ return { content: "(系统)这是一个测试句子。这个句子稍长一些,包含多个标点符号!这是一个特别长的句子,需要超过最大长度限制的句子应该被保留原样,但这种情况在实际使用中应该尽量避免。最后?这是一个需要合并的短句!;", error: false };
189
314
  const enableUserKey = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description == "on";
190
315
  let keys;
191
316
  let modle;
192
317
  let baseURL;
193
318
  if (enableUserKey) {
194
- const key = user.items["地灵殿通行证"].metadata?.key;
195
- keys = [key];
196
- modle = user.items["地灵殿通行证"].metadata?.model;
197
- baseURL = user.items["地灵殿通行证"].metadata?.baseURL;
319
+ const ticket = user.items["地灵殿通行证"].metadata;
320
+ keys = [ticket?.key];
321
+ modle = ticket?.model;
322
+ baseURL = ticket?.baseURL;
323
+ const not_reasoner_model = ticket?.not_reasoner_model;
324
+ const length = ticket?.use_not_reasoner_LLM_length;
325
+ if (not_reasoner_model && length && messages[messages.length - 1].content.length <= length)
326
+ modle = not_reasoner_model;
198
327
  } else {
199
- keys = this.config.keys;
200
- modle = this.config.appointModel;
201
- baseURL = this.config.baseURL;
328
+ const config = this.config;
329
+ const useNotReasoner = messages[messages.length - 1].content.length <= config.use_not_reasoner_LLM_length;
330
+ keys = useNotReasoner ? config.not_reasoner_LLM_key : config.keys;
331
+ modle = useNotReasoner ? config.not_reasoner_LLM : config.appointModel;
332
+ baseURL = useNotReasoner ? config.not_reasoner_LLM_URL : config.baseURL;
202
333
  }
203
334
  const payload = this.createPayload(messages, modle);
204
335
  for (let i = 0; i < keys.length; i++) {
@@ -276,7 +407,6 @@ var APIClient = class {
276
407
  return {
277
408
  model,
278
409
  messages,
279
- max_tokens: this.config.content_max_tokens,
280
410
  temperature: this.config.temperature,
281
411
  top_p: 1,
282
412
  frequency_penalty: this.config.frequency_penalty,
@@ -300,19 +430,13 @@ var APIClient = class {
300
430
  try {
301
431
  const response = await this.ctx.http.post(url, payload, { headers, timeout: 36e5 });
302
432
  content = response.choices[0].message.content;
303
- const reasoning_content = response.choices[0].message.reasoning_content;
433
+ const reasoning_content = response.choices[0].message.reasoning_content || "无";
304
434
  if (this.config.reasoning_content)
305
- logger2.info(`思维链: ${reasoning_content || "无"}`);
435
+ logger2.info(`思维链: ${reasoning_content}`);
306
436
  if (!content && reasoning_content) {
307
437
  logger2.warn("返回内容为空,但存在推理内容");
308
438
  content = response.choices[0].message.reasoning_content;
309
439
  }
310
- if (content.length > this.config.content_max_length) {
311
- logger2.warn(`返回内容超过最大长度(${content.length} > ${this.config.content_max_length})`);
312
- if (i >= 2)
313
- return { content: "返回内容超过最大长度", error: true };
314
- continue;
315
- }
316
440
  const responseMsg = { role: "assistant", content };
317
441
  if (payload.messages.some((msg) => msg === responseMsg) && content.length > 5) {
318
442
  const lastMsg = payload.messages[payload.messages.length - 1];
@@ -388,98 +512,6 @@ var APIClient = class {
388
512
  var import_koishi3 = require("koishi");
389
513
  var fs2 = __toESM(require("fs"));
390
514
  var path2 = __toESM(require("path"));
391
-
392
- // src/database.ts
393
- async function isTargetIdNotExists(ctx, userId) {
394
- const users = await ctx.database.get("p_system", { userid: userId });
395
- return users.length === 0;
396
- }
397
- __name(isTargetIdNotExists, "isTargetIdNotExists");
398
- async function createUser(ctx, user) {
399
- await ctx.database.create("p_system", {
400
- userid: user.userid || "",
401
- usersname: user.usersname || "",
402
- p: user.p || 0,
403
- favorability: user.favorability || 0,
404
- userlevel: user.userlevel || 0,
405
- usage: user.usage || 0,
406
- lastChatTime: user.lastChatTime || (/* @__PURE__ */ new Date()).getDate(),
407
- items: user.items || {}
408
- });
409
- }
410
- __name(createUser, "createUser");
411
- async function updateFavorability(ctx, user, adjustment) {
412
- if (!user)
413
- return;
414
- let newValue;
415
- if (typeof adjustment === "number")
416
- newValue = user.favorability + adjustment;
417
- else
418
- newValue = user.favorability;
419
- await ctx.database.set("p_system", { userid: user.userid }, { favorability: newValue });
420
- }
421
- __name(updateFavorability, "updateFavorability");
422
- async function updateUserLevel(ctx, user, level) {
423
- if (!user)
424
- return;
425
- level = level < 5 ? level : 4;
426
- await ctx.database.set("p_system", { userid: user.userid }, { userlevel: level });
427
- }
428
- __name(updateUserLevel, "updateUserLevel");
429
- async function updateUserUsage(ctx, user, adjustment = 1) {
430
- if (!user)
431
- return;
432
- if (user.lastChatTime && (/* @__PURE__ */ new Date()).getDate() !== user.lastChatTime)
433
- user.usage = 0;
434
- await ctx.database.set("p_system", { userid: user.userid }, { usage: user.usage + adjustment });
435
- await ctx.database.set("p_system", { userid: user.userid }, { lastChatTime: (/* @__PURE__ */ new Date()).getDate() });
436
- return user.usage + adjustment;
437
- }
438
- __name(updateUserUsage, "updateUserUsage");
439
- async function updateUserItems(ctx, user) {
440
- if (!user)
441
- return;
442
- await ctx.database.set("p_system", { userid: user.userid }, { items: user.items });
443
- }
444
- __name(updateUserItems, "updateUserItems");
445
- async function getUser(ctx, userId) {
446
- const users = await ctx.database.get("p_system", { userid: userId });
447
- return users[0] || null;
448
- }
449
- __name(getUser, "getUser");
450
- async function ensureUserExists(ctx, userId, username) {
451
- const notExists = await isTargetIdNotExists(ctx, userId);
452
- if (notExists) {
453
- await createUser(ctx, {
454
- userid: userId,
455
- usersname: username,
456
- p: 0,
457
- favorability: 0,
458
- userlevel: 0,
459
- usage: 0,
460
- lastChatTime: (/* @__PURE__ */ new Date()).getDate(),
461
- items: {}
462
- });
463
- }
464
- return getUser(ctx, userId);
465
- }
466
- __name(ensureUserExists, "ensureUserExists");
467
- function extendDatabase(ctx) {
468
- ctx.model.extend("p_system", {
469
- id: "unsigned",
470
- userid: "string",
471
- usersname: "string",
472
- p: "integer",
473
- favorability: "integer",
474
- userlevel: "integer",
475
- usage: "integer",
476
- lastChatTime: "integer",
477
- items: "object"
478
- }, { autoInc: true });
479
- }
480
- __name(extendDatabase, "extendDatabase");
481
-
482
- // src/memory.ts
483
515
  var logger3 = new import_koishi3.Logger("satori-memory");
484
516
  var MemoryManager = class {
485
517
  constructor(ctx, config) {
@@ -886,24 +918,25 @@ async function handleAuxiliaryResult(ctx, session, config, responseContent) {
886
918
  return;
887
919
  }
888
920
  __name(handleAuxiliaryResult, "handleAuxiliaryResult");
889
- async function inputContentCheck(ctx, content, userid, config, session) {
921
+ async function inputContentCheck(ctx, content, userid, config, session, moodManager) {
890
922
  const user = await getUser(ctx, userid);
891
923
  if (!user)
892
924
  return 0;
893
925
  const regex = /\*\*/g;
894
926
  const hasCensor = regex.test(content);
895
927
  if (hasCensor && config.input_censor_favorability) {
928
+ moodManager.handleInputMoodChange(user);
896
929
  await applyFavorabilityEffect(ctx, user, -1 * config.value_of_input_favorability, session);
897
930
  return -1 * config.value_of_input_favorability;
898
931
  }
899
- if (config.enable_auxiliary_LLM || user.usage > config.max_favorability_perday) {
932
+ moodManager.applyMoodChange(user, 1);
933
+ if (config.enable_auxiliary_LLM || user.usage > config.max_favorability_perday)
900
934
  return 0;
901
- }
902
935
  await applyFavorabilityEffect(ctx, user, 1, session);
903
936
  return 1;
904
937
  }
905
938
  __name(inputContentCheck, "inputContentCheck");
906
- async function outputContentCheck(ctx, response, userid, config, session) {
939
+ async function outputContentCheck(ctx, response, userid, config, session, moodManager) {
907
940
  if (response.error)
908
941
  return 0;
909
942
  const user = await getUser(ctx, userid);
@@ -919,9 +952,18 @@ async function outputContentCheck(ctx, response, userid, config, session) {
919
952
  const censoredContent = censorWords.reduce((acc, cur) => acc.replace(cur, "**"), content);
920
953
  const regex = /\*\*/g;
921
954
  const hasCensor = regex.test(censoredContent);
955
+ const moodLevel = moodManager.getMoodLevel(user.userid);
922
956
  if (hasCensor) {
957
+ const mood = moodManager.getMoodValue(user.userid);
958
+ moodManager.handleOutputMoodChange(user);
959
+ if (mood <= 0) {
960
+ await applyFavorabilityEffect(ctx, user, -1 * config.value_of_output_favorability, session);
961
+ return -config.value_of_output_favorability;
962
+ }
963
+ }
964
+ if (moodLevel === "angry") {
923
965
  await applyFavorabilityEffect(ctx, user, -1 * config.value_of_output_favorability, session);
924
- return -1 * config.value_of_output_favorability;
966
+ return -config.value_of_output_favorability;
925
967
  }
926
968
  }
927
969
  return 0;
@@ -1031,27 +1073,34 @@ var Sat = class extends import_koishi5.Service {
1031
1073
  ((Sat2) => {
1032
1074
  Sat2.Config = import_koishi5.Schema.intersect([
1033
1075
  import_koishi5.Schema.object({
1034
- baseURL: import_koishi5.Schema.string().default("https://api.deepseek.com").description("请求地址"),
1076
+ baseURL: import_koishi5.Schema.string().default("https://api.deepseek.com").description("深度思考模型请求地址"),
1035
1077
  key: import_koishi5.Schema.union([
1036
1078
  import_koishi5.Schema.array(String).role("secret"),
1037
1079
  import_koishi5.Schema.transform(String, (value) => [value])
1038
- ]).default([]).role("secret").description("api_key"),
1039
- appointModel: import_koishi5.Schema.string().default("deepseek-reasoner").description("主模型"),
1080
+ ]).default([]).role("secret").description("深度思考模型api_key"),
1081
+ appointModel: import_koishi5.Schema.string().default("deepseek-reasoner").description("深度思考模型"),
1082
+ not_reasoner_LLM_URL: import_koishi5.Schema.string().default("https://api.deepseek.com").description("非深度思考模型请求地址"),
1083
+ not_reasoner_LLM: import_koishi5.Schema.string().default("deepseek-chat").description("非深度思考模型(用于节省成本"),
1084
+ not_reasoner_LLM_key: import_koishi5.Schema.union([
1085
+ import_koishi5.Schema.array(String).role("secret"),
1086
+ import_koishi5.Schema.transform(String, (value) => [value])
1087
+ ]).default([]).role("secret").description("非深度思考模型api_key"),
1088
+ use_not_reasoner_LLM_length: import_koishi5.Schema.number().default(8).description("触发使用非深度思考模型的字数(输入少于此字数时),如果你希望始终使用非深度思考模型进行对话,请将此值设置成一个较大的值,反之亦然"),
1089
+ enable_reasoner_like: import_koishi5.Schema.boolean().default(true).description("是否启用非深度思考模型模仿思维链(可以在节省成本的同时提高效果)"),
1040
1090
  auxiliary_LLM_URL: import_koishi5.Schema.string().default("https://api.deepseek.com").description("辅助模型请求地址"),
1041
1091
  auxiliary_LLM: import_koishi5.Schema.string().default("deepseek-chat").description("辅助模型(用于好感度调整等功能,如不需要可不填,建议使用低成本模型"),
1042
1092
  auxiliary_LLM_key: import_koishi5.Schema.union([
1043
1093
  import_koishi5.Schema.array(String).role("secret"),
1044
1094
  import_koishi5.Schema.transform(String, (value) => [value])
1045
1095
  ]).default([]).role("secret").description("辅助模型api_key"),
1046
- prompt: import_koishi5.Schema.string().role("textarea").description("人格设定")
1096
+ prompt: import_koishi5.Schema.string().role("textarea").description("人格设定"),
1097
+ reasoner_prompt: import_koishi5.Schema.string().role("textarea").description("思考提示词(对于深度思考模型和非深度思考模型模仿思维链时生效)").default("你在思考时应当逐步分析以下内容:1.当前对话的禁止事项;2.是否与群聊中其他人的发言有关联;3.是否与当前用户之前说的话有关联;4.对话的具体要求;5.用户的意图如何;6.最终的发言的主要内容。")
1047
1098
  }).description("基础设置"),
1048
1099
  import_koishi5.Schema.object({
1049
1100
  alias: import_koishi5.Schema.array(String).default(["ai"]).description("触发命令;别名"),
1050
1101
  authority: import_koishi5.Schema.number().role("slider").min(0).max(5).step(1).description("允许使用的最低权限").default(1),
1051
- no_system_prompt: import_koishi5.Schema.boolean().default(false).description("是否将系统提示的system替换为user(用于具有思维链的模型或一些特殊的api格式,例如硅基流动)"),
1102
+ no_system_prompt: import_koishi5.Schema.boolean().default(false).description("是否将系统提示的system替换为user(用于具有思维链的模型)"),
1052
1103
  max_tokens: import_koishi5.Schema.number().description("最大请求长度(字符数)").default(100),
1053
- content_max_tokens: import_koishi5.Schema.number().description("最大回答长度(思维链+输出token)").default(4096),
1054
- content_max_length: import_koishi5.Schema.number().description("最大回答长度(仅输出,字符数)").default(100),
1055
1104
  message_max_length: import_koishi5.Schema.number().description("最大频道上下文长度(条数)").default(10),
1056
1105
  temperature: import_koishi5.Schema.number().role("slider").min(0).max(2).step(0.01).default(0.5).description("温度"),
1057
1106
  frequency_penalty: import_koishi5.Schema.number().default(0).description("频率惩罚"),
@@ -1080,7 +1129,7 @@ var Sat = class extends import_koishi5.Service {
1080
1129
  import_koishi5.Schema.object({
1081
1130
  max_usage: import_koishi5.Schema.tuple([Number, Number, Number, Number, Number]).default([40, 240, 3e3, 9999, 0]).description("每日最大使用次数(对应用户level0~level4)(0为不限制)"),
1082
1131
  private: import_koishi5.Schema.boolean().default(false).description("开启后私聊AI可触发对话, 不需要使用指令"),
1083
- nick_name: import_koishi5.Schema.boolean().default(true).description("是否使用昵称触发对话(发言中含有昵称时)"),
1132
+ nick_name: import_koishi5.Schema.boolean().default(true).description("是否使用昵称触发对话(发言中含有昵称时)(把qq号加入昵称可以被at和戳一戳触发)"),
1084
1133
  nick_name_list: import_koishi5.Schema.array(String).default(["昵称1"]).description("昵称列表"),
1085
1134
  nick_name_block_words: import_koishi5.Schema.array(String).default(["屏蔽词1"]).description("昵称屏蔽词(含有屏蔽词的消息不会触发昵称对话)"),
1086
1135
  input_prompt: import_koishi5.Schema.string().role("textarea").default("(注意专注对话主题,遵守对话要求,不要复读)").description("每轮对话前的补充提示(可用于强调要求)不需要时可不填"),
@@ -1091,6 +1140,8 @@ var Sat = class extends import_koishi5.Service {
1091
1140
  random_min_tokens: import_koishi5.Schema.number().default(20).description("随机触发对话的最小长度"),
1092
1141
  randnum: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0).description("在群聊中随机触发对话的概率,如需关闭可设置为 0"),
1093
1142
  sentences_divide: import_koishi5.Schema.boolean().default(true).description("是否分句发送"),
1143
+ min_sentences_length: import_koishi5.Schema.number().default(10).description("每个分句的最小长度"),
1144
+ max_sentences_length: import_koishi5.Schema.number().default(20).description("每个分句的最大长度"),
1094
1145
  time_interval: import_koishi5.Schema.number().default(1e3).description("每句话的时间间隔"),
1095
1146
  reply_pointing: import_koishi5.Schema.boolean().default(true).description("是否在与多人同时对话时显示回复指向")
1096
1147
  }).description("对话设置"),
@@ -1098,9 +1149,9 @@ var Sat = class extends import_koishi5.Service {
1098
1149
  enable_favorability: import_koishi5.Schema.boolean().default(false).description("是否开启好感度系统(每次对话默认+1好感度)"),
1099
1150
  max_favorability_perday: import_koishi5.Schema.number().default(100).description("每日有效(引发好感度增长)对话次数上限"),
1100
1151
  input_censor_favorability: import_koishi5.Schema.boolean().default(false).description("是否开启好感度审查(通过输入屏蔽词扣除好感)"),
1101
- value_of_input_favorability: import_koishi5.Schema.number().default(15).description("输入触发屏蔽词每次扣除的好感度"),
1152
+ value_of_input_favorability: import_koishi5.Schema.number().default(15).description("输入触发输入屏蔽词每次扣除的好感度"),
1102
1153
  output_censor_favorability: import_koishi5.Schema.boolean().default(false).description("通过输出屏蔽词扣除好感,在dataDir中的output_censor.txt修改)"),
1103
- value_of_output_favorability: import_koishi5.Schema.number().default(15).description("输出触发屏蔽词每次扣除的好感度"),
1154
+ value_of_output_favorability: import_koishi5.Schema.number().default(15).description("输出触发输出屏蔽词每次扣除的好感度"),
1104
1155
  enable_auxiliary_LLM: import_koishi5.Schema.boolean().default(false).description("是否使用辅助大模型判断好感度增减(量与输入屏蔽词每次扣除的好感度相关,不稳定,慎用)"),
1105
1156
  offset_of_fafavorability: import_koishi5.Schema.number().default(3.5).description("辅助大模型好感度偏移量(越大越容易扣好感度)"),
1106
1157
  visible_favorability: import_koishi5.Schema.boolean().default(true).description("是否开启好感度升降显示"),
@@ -1118,6 +1169,22 @@ var Sat = class extends import_koishi5.Service {
1118
1169
  favorability_div_4: import_koishi5.Schema.number().default(1e3).description("思慕-恋慕分界线"),
1119
1170
  prompt_4: import_koishi5.Schema.string().role("textarea").description("恋慕好感补充设定")
1120
1171
  }).description("好感度设置"),
1172
+ import_koishi5.Schema.object({
1173
+ enable_mood: import_koishi5.Schema.boolean().default(false).description("是否开启心情系统(通过屏蔽词降低心情,正常聊天心情+1,每天重置为mood_div_1 + value_of_output_mood)"),
1174
+ max_mood: import_koishi5.Schema.number().default(5).description("心情上限"),
1175
+ value_of_input_mood: import_koishi5.Schema.number().default(6).description("输入触发屏蔽词每次扣除的心情"),
1176
+ value_of_output_mood: import_koishi5.Schema.number().default(3).description("输出触发屏蔽词每次扣除的心情,若当时心情大于0,此次不扣好感度"),
1177
+ visible_mood: import_koishi5.Schema.boolean().default(false).description("是否开启心情状态显示"),
1178
+ mood_prompt_2: import_koishi5.Schema.string().role("textarea").default("你现在的心情十分愉悦").description("心情达到最高补充设定"),
1179
+ mood_div_1: import_koishi5.Schema.number().default(-1).description("心情正常-烦躁分界线"),
1180
+ mood_prompt_0: import_koishi5.Schema.string().role("textarea").default("你现在的心情是:有点烦躁").description("烦躁心情补充设定"),
1181
+ mood_div_2: import_koishi5.Schema.number().default(-5).description("烦躁-生气分界线"),
1182
+ mood_prompt_1: import_koishi5.Schema.string().role("textarea").default("你现在的心情是:非常生气").description("生气心情补充设定"),
1183
+ enable_pocket_money: import_koishi5.Schema.boolean().default(false).description("开启要零花钱指令(通过消耗心情换随机数量p点)"),
1184
+ min_pocket_money: import_koishi5.Schema.number().default(100).description("随机p点最小值"),
1185
+ max_pocket_money: import_koishi5.Schema.number().default(400).description("随机p点最大值"),
1186
+ pocket_money_cost: import_koishi5.Schema.number().default(2).description("消耗心情换p点的心情值")
1187
+ }).description("好感度拓展:心情设置(需要开启好感度模块才能生效)"),
1121
1188
  import_koishi5.Schema.object({
1122
1189
  enable_game: import_koishi5.Schema.boolean().default(false).description("是否开启游戏模块"),
1123
1190
  enable_gobang: import_koishi5.Schema.boolean().default(false).description("是否开启五子棋游戏")
@@ -1204,8 +1271,8 @@ ${history}
1204
1271
 
1205
1272
  注意事项:
1206
1273
  ·用户一定是人类,其他情况是角色扮演
1207
- ·若有历史画像则需要根据发言修正历史画像内容,以发言为准,但是历史画像中不需要修改的部分可以保留
1208
- ·除非用户要求,否则尽量不要改动基本信息
1274
+ ·若有历史画像则需要根据发言修正历史画像内容,以发言为准,但是历史画像中不需要修改的部分必须保留
1275
+ ·除非用户要求,否则不要改动基本信息中的内容
1209
1276
  ·及时删除历史画像中明确错误或多余的信息
1210
1277
  ·尤其注意用户说“记住”的部分,可能是用户希望记录的信息
1211
1278
  ·历史画像中的需要短期记忆的信息不需要保留,只需要删除旧的添加新的
@@ -1298,8 +1365,165 @@ ${portrait}
1298
1365
  }
1299
1366
  };
1300
1367
 
1368
+ // src/mood.ts
1369
+ var import_koishi7 = require("koishi");
1370
+ var import_crypto = require("crypto");
1371
+ var logger6 = new import_koishi7.Logger("satori-ai-mood");
1372
+ var MoodManager = class {
1373
+ static {
1374
+ __name(this, "MoodManager");
1375
+ }
1376
+ ctx;
1377
+ config;
1378
+ moodMap = /* @__PURE__ */ new Map();
1379
+ constructor(ctx, config) {
1380
+ this.ctx = ctx;
1381
+ this.config = config;
1382
+ }
1383
+ // 初始化用户心情
1384
+ initUser(userId) {
1385
+ this.moodMap.set(userId, {
1386
+ mood: this.config.mood_div_1 + this.config.value_of_output_mood,
1387
+ lastUpdate: Date.now()
1388
+ });
1389
+ }
1390
+ // 每日重置检查
1391
+ checkDailyReset(userId) {
1392
+ const data = this.moodMap.get(userId);
1393
+ if (!data)
1394
+ return;
1395
+ const lastDate = new Date(data.lastUpdate);
1396
+ const now = /* @__PURE__ */ new Date();
1397
+ if (lastDate.getDate() !== now.getDate() || lastDate.getMonth() !== now.getMonth() || lastDate.getFullYear() !== now.getFullYear()) {
1398
+ this.moodMap.set(userId, { mood: 0, lastUpdate: Date.now() });
1399
+ }
1400
+ }
1401
+ // 处理输入内容心情变化
1402
+ async handleInputMoodChange(user) {
1403
+ if (!this.config.enable_mood)
1404
+ return;
1405
+ const userId = user.userid;
1406
+ if (!this.moodMap.has(userId))
1407
+ this.initUser(userId);
1408
+ this.checkDailyReset(userId);
1409
+ this.applyMoodChange(user, -this.config.value_of_input_mood);
1410
+ return;
1411
+ }
1412
+ // 处理输出内容心情变化
1413
+ async handleOutputMoodChange(user) {
1414
+ if (!this.config.enable_mood)
1415
+ return;
1416
+ const userId = user.userid;
1417
+ if (!this.moodMap.has(userId))
1418
+ this.initUser(userId);
1419
+ this.checkDailyReset(userId);
1420
+ this.applyMoodChange(user, -this.config.value_of_output_mood);
1421
+ return;
1422
+ }
1423
+ // 应用心情变化
1424
+ applyMoodChange(user, delta) {
1425
+ if (!this.config.enable_mood)
1426
+ return;
1427
+ const userId = user.userid;
1428
+ let data = this.moodMap.get(userId);
1429
+ if (!data) {
1430
+ this.initUser(userId);
1431
+ data = this.moodMap.get(userId);
1432
+ }
1433
+ const newMood = Math.min(this.config.max_mood, data.mood + delta);
1434
+ this.moodMap.set(userId, {
1435
+ mood: newMood,
1436
+ lastUpdate: Date.now()
1437
+ });
1438
+ return;
1439
+ }
1440
+ // 获取心情等级
1441
+ getMoodLevel(userId) {
1442
+ if (!this.config.enable_mood)
1443
+ return "normal";
1444
+ const data = this.moodMap.get(userId);
1445
+ if (!data) {
1446
+ this.initUser(userId);
1447
+ return "normal";
1448
+ }
1449
+ if (data.mood == this.config.max_mood)
1450
+ return "happy";
1451
+ if (data.mood <= this.config.mood_div_2)
1452
+ return "angry";
1453
+ if (data.mood <= this.config.mood_div_1)
1454
+ return "upset";
1455
+ return "normal";
1456
+ }
1457
+ // 获取心情值
1458
+ getMoodValue(userId) {
1459
+ if (!this.config.enable_mood)
1460
+ return 0;
1461
+ const data = this.moodMap.get(userId);
1462
+ if (!data) {
1463
+ this.initUser(userId);
1464
+ return 0;
1465
+ }
1466
+ return data.mood;
1467
+ }
1468
+ // 生成心情提示
1469
+ generateMoodPrompt(userId) {
1470
+ const level = this.getMoodLevel(userId);
1471
+ return {
1472
+ "upset": `
1473
+ ${this.config.mood_prompt_0}
1474
+ `,
1475
+ "angry": `
1476
+ ${this.config.mood_prompt_1}
1477
+ `,
1478
+ "happy": `
1479
+ ${this.config.mood_prompt_2}
1480
+ `,
1481
+ "normal": "你现在的心情很平淡"
1482
+ }[level];
1483
+ }
1484
+ async handlePocketMoney(session) {
1485
+ const user = await ensureUserExists(this.ctx, session.userId, session.username);
1486
+ const mood = this.getMoodValue(user.userid);
1487
+ if (mood < this.config.max_mood / 2) {
1488
+ updateFavorability(this.ctx, user, -this.config.value_of_output_favorability);
1489
+ return session.text("commands.sat.messages.not_good_mood");
1490
+ }
1491
+ this.applyMoodChange(user, -this.config.pocket_money_cost);
1492
+ const pocketMoney = (0, import_crypto.randomInt)(this.config.min_pocket_money, this.config.max_pocket_money + 1);
1493
+ updateUserP(this.ctx, user, pocketMoney);
1494
+ return session.text("commands.sat.messages.pocket_money", [pocketMoney]);
1495
+ }
1496
+ setMood(id, mood) {
1497
+ this.moodMap.set(id, {
1498
+ mood: Math.min(this.config.max_mood, mood),
1499
+ lastUpdate: Date.now()
1500
+ });
1501
+ return "已设置" + id + "心情值为" + mood;
1502
+ }
1503
+ viewMood(session, id) {
1504
+ if (!this.config.enable_mood)
1505
+ return "normal";
1506
+ const level = this.getMoodLevel(id);
1507
+ if (id === session.userId) {
1508
+ switch (level) {
1509
+ case "upset":
1510
+ return `!`;
1511
+ case "angry":
1512
+ return `滚`;
1513
+ case "happy":
1514
+ return `♥`;
1515
+ case "normal":
1516
+ return `~`;
1517
+ default:
1518
+ return `你的心情等级为 ${level}`;
1519
+ }
1520
+ } else
1521
+ return `用户 ${id} 的心情等级为 ${level}`;
1522
+ }
1523
+ };
1524
+
1301
1525
  // src/index.tsx
1302
- var logger6 = new import_koishi7.Logger("satori-ai");
1526
+ var logger7 = new import_koishi8.Logger("satori-ai");
1303
1527
  var SAT = class extends Sat {
1304
1528
  // 重写构造函数
1305
1529
  constructor(ctx, config) {
@@ -1310,6 +1534,7 @@ var SAT = class extends Sat {
1310
1534
  this.apiClient = new APIClient(ctx, this.getAPIConfig());
1311
1535
  this.memoryManager = new MemoryManager(ctx, this.getMemoryConfig());
1312
1536
  this.portraitManager = new UserPortraitManager(ctx, config);
1537
+ this.moodManager = new MoodManager(ctx, config);
1313
1538
  ensureCensorFileExists(this.config.dataDir);
1314
1539
  ctx.middleware(createMiddleware(ctx, this, this.getMiddlewareConfig()));
1315
1540
  this.registerCommands(ctx);
@@ -1322,17 +1547,20 @@ var SAT = class extends Sat {
1322
1547
  portraitManager;
1323
1548
  ChannelParallelCount = /* @__PURE__ */ new Map();
1324
1549
  onlineUsers = [];
1550
+ moodManager;
1325
1551
  game;
1326
1552
  getAPIConfig() {
1327
1553
  return {
1328
1554
  baseURL: this.config.baseURL,
1329
1555
  keys: this.config.key,
1330
1556
  appointModel: this.config.appointModel,
1557
+ not_reasoner_LLM_URL: this.config.not_reasoner_LLM_URL,
1558
+ not_reasoner_LLM: this.config.not_reasoner_LLM,
1559
+ not_reasoner_LLM_key: this.config.not_reasoner_LLM_key,
1560
+ use_not_reasoner_LLM_length: this.config.use_not_reasoner_LLM_length,
1331
1561
  auxiliary_LLM_URL: this.config.auxiliary_LLM_URL,
1332
1562
  auxiliary_LLM: this.config.auxiliary_LLM,
1333
1563
  auxiliary_LLM_key: this.config.auxiliary_LLM_key,
1334
- content_max_tokens: this.config.content_max_tokens,
1335
- content_max_length: this.config.content_max_length,
1336
1564
  maxRetryTimes: this.config.maxRetryTimes,
1337
1565
  retry_delay_time: this.config.retry_delay_time,
1338
1566
  temperature: this.config.temperature,
@@ -1416,6 +1644,11 @@ var SAT = class extends Sat {
1416
1644
  ctx.command("sat.user_usage", "查看用户使用次数").alias("查询次数").action(async ({ session }) => this.handleUserUsage(session));
1417
1645
  ctx.command("sat.add_output_censor <text:text>", "添加输出敏感词", { authority: 4 }).alias("添加输出屏蔽词").action(async ({ session }, word) => addOutputCensor(session, word, this.config.dataDir));
1418
1646
  ctx.command("sat.get_user_portrait <text:text>", "查看用户画像", { authority: 4 }).alias("查看画像").action(async ({}, userId) => this.portraitManager.getUserPortraitById(userId));
1647
+ if (this.config.enable_mood && this.config.enable_favorability && this.config.enable_pocket_money) {
1648
+ ctx.command("sat.pocket_money", "消耗心情值换取p点").alias("要零花钱").action(async ({ session }) => this.moodManager.handlePocketMoney(session));
1649
+ ctx.command("sat.set_mood", "设置心情值", { authority: 4 }).alias("设置心情").option("id", "-i <id:string>", { authority: 4 }).option("value", "-v <value:number>", { authority: 4 }).action(async ({ session, options }) => this.moodManager.setMood(options.id || session.userId, options.value || 0));
1650
+ ctx.command("sat.get_mood", "查看心情状态").alias("查看心情").option("id", "-i <id:string>", { authority: 4 }).action(async ({ session, options }) => this.moodManager.viewMood(session, options.id || session.userId));
1651
+ }
1419
1652
  }
1420
1653
  async handleSatCommand(session, prompt) {
1421
1654
  const user = await ensureUserExists(this.ctx, session.userId, session.username);
@@ -1441,16 +1674,18 @@ var SAT = class extends Sat {
1441
1674
  const response = await this.generateResponse(session, processedPrompt);
1442
1675
  const auxiliaryResult = await this.handleAuxiliaryDialogue(session, processedPrompt, response);
1443
1676
  await this.memoryManager.updateMemories(session, processedPrompt, this.getMemoryConfig(), response);
1677
+ if (!response.error)
1678
+ await updateUserPWithTicket(this.ctx, user, 10);
1444
1679
  if (user.usage == this.config.portrait_usage - 1)
1445
1680
  this.portraitManager.generatePortrait(session, user, this.apiClient);
1446
1681
  return await this.formatResponse(session, response.content, auxiliaryResult);
1447
1682
  }
1448
1683
  // 处理辅助判断
1449
1684
  async handleAuxiliaryDialogue(session, prompt, response) {
1450
- if (response.error)
1685
+ if (response.error || !this.config.enable_favorability)
1451
1686
  return null;
1452
1687
  const user = await getUser(this.ctx, session.userId);
1453
- const outputCheck = await outputContentCheck(this.ctx, response, session.userId, this.getFavorabilityConfig(), session);
1688
+ const outputCheck = await outputContentCheck(this.ctx, response, session.userId, this.getFavorabilityConfig(), session, this.moodManager);
1454
1689
  const regex = /\*\*/g;
1455
1690
  const inputCensor = prompt.match(regex)?.length;
1456
1691
  const outputCensor = outputCheck < 0;
@@ -1462,9 +1697,9 @@ var SAT = class extends Sat {
1462
1697
  const messages = generateAuxiliaryPrompt(prompt, response.content, user, this.getFavorabilityConfig());
1463
1698
  const result = await this.apiClient.auxiliaryChat(messages);
1464
1699
  if (result.error) {
1465
- logger6.error(`辅助判断失败:${result.content}`);
1700
+ logger7.error(`辅助判断失败:${result.content}`);
1466
1701
  } else {
1467
- logger6.info(`辅助判断:${result.content}`);
1702
+ logger7.info(`辅助判断:${result.content}`);
1468
1703
  return handleAuxiliaryResult(this.ctx, session, this.getFavorabilityConfig(), result.content);
1469
1704
  }
1470
1705
  }
@@ -1496,7 +1731,7 @@ var SAT = class extends Sat {
1496
1731
  if (!duplicateDialogue)
1497
1732
  return null;
1498
1733
  if (this.config.enable_favorability) {
1499
- updateFavorability(this.ctx, user, -1);
1734
+ updateFavorability(this.ctx, user, -5);
1500
1735
  return session.text("commands.sat.messages.duplicate-dialogue") + " (好感↓)";
1501
1736
  }
1502
1737
  return session.text("commands.sat.messages.duplicate-dialogue");
@@ -1548,30 +1783,43 @@ var SAT = class extends Sat {
1548
1783
  censored = await this.ctx.censor.transform(processedPrompt, session);
1549
1784
  }
1550
1785
  if (this.config.enable_favorability) {
1551
- await inputContentCheck(this.ctx, censored, session.userId, this.getFavorabilityConfig(), session);
1786
+ await inputContentCheck(this.ctx, censored, session.userId, this.getFavorabilityConfig(), session, this.moodManager);
1552
1787
  }
1553
1788
  if (this.config.log_ask_response)
1554
- logger6.info(`用户 ${session.username}:${processedPrompt}`);
1789
+ logger7.info(`用户 ${session.username}:${processedPrompt}`);
1555
1790
  return censored;
1556
1791
  }
1557
1792
  // 生成回复
1558
1793
  async generateResponse(session, prompt) {
1559
1794
  if (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
1560
- logger6.info(`频道 ${session.channelId} 并发数过高(${this.getChannelParallelCount(session)}),${session.username}等待中...`);
1795
+ logger7.info(`频道 ${session.channelId} 并发数过高(${this.getChannelParallelCount(session)}),${session.username}等待中...`);
1561
1796
  }
1562
1797
  while (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
1563
1798
  this.updateChannelParallelCount(session, -1);
1564
1799
  await new Promise((resolve2) => setTimeout(resolve2, 1e3));
1565
1800
  this.updateChannelParallelCount(session, 1);
1566
1801
  }
1567
- const messages = this.buildMessages(session, prompt);
1568
- logger6.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
1802
+ const messages = await this.buildMessages(session, prompt);
1803
+ logger7.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
1569
1804
  const user = await getUser(this.ctx, session.userId);
1570
- let response = await this.apiClient.chat(user, await messages);
1571
- if (this.config.log_ask_response)
1572
- logger6.info(`Satori AI:${response.content}`);
1805
+ let response = await this.getChatResponse(user, messages);
1806
+ if (response.error)
1807
+ response = await this.getChatResponse(user, messages);
1808
+ if (response.error)
1809
+ updateUserUsage(this.ctx, user, -1);
1810
+ return response;
1811
+ }
1812
+ // 获取聊天回复
1813
+ async getChatResponse(user, messages) {
1814
+ let response = await this.apiClient.chat(user, messages);
1815
+ if (this.config.log_ask_response) {
1816
+ if (this.config.enable_favorability && this.config.enable_mood)
1817
+ logger7.info(`Satori AI:(心情值:${this.moodManager.getMoodValue(user.userid)})${response.content}`);
1818
+ else
1819
+ logger7.info(`Satori AI:${response.content}`);
1820
+ }
1573
1821
  if (this.config.reasoner_filter)
1574
- response.content = filterResponse(response.content, this.config.reasoner_filter_word.split("-"));
1822
+ response = filterResponse(response.content, this.config.reasoner_filter_word.split("-"));
1575
1823
  return response;
1576
1824
  }
1577
1825
  // 构建消息
@@ -1592,7 +1840,7 @@ var SAT = class extends Sat {
1592
1840
  messages.push({ role: "user", content: prompt });
1593
1841
  let payload = messages.map((msg) => msg.role + ":" + msg.content).join("\n");
1594
1842
  if (this.config.log_system_prompt)
1595
- logger6.info(`系统提示:
1843
+ logger7.info(`系统提示:
1596
1844
  ${payload}`);
1597
1845
  return messages;
1598
1846
  }
@@ -1603,6 +1851,7 @@ ${payload}`);
1603
1851
  const channelDialogue = await this.memoryManager.getChannelDialogue(session);
1604
1852
  const userMemory = await this.memoryManager.searchMemories(session, prompt);
1605
1853
  const user = await getUser(this.ctx, session.userId);
1854
+ systemPrompt += this.getThinkingPrompt(user, prompt);
1606
1855
  if (user?.items?.["觉的衣柜"]?.count) {
1607
1856
  const clothes = user?.items?.["觉的衣柜"]?.metadata?.clothes;
1608
1857
  if (clothes)
@@ -1614,17 +1863,47 @@ ${payload}`);
1614
1863
  systemPrompt += channelDialogue;
1615
1864
  systemPrompt += userMemory;
1616
1865
  systemPrompt += this.portraitManager.getUserPortrait(session);
1617
- const nickName = user.items["情侣合照"]?.metadata?.userNickName;
1618
1866
  systemPrompt += `用户的名字是:${session.username}, id是:${session.userId}`;
1867
+ const nickName = user.items["情侣合照"]?.metadata?.userNickName;
1619
1868
  if (nickName)
1620
1869
  systemPrompt += `, 昵称是:${nickName},称呼用户时请优先使用昵称`;
1621
1870
  if (this.config.enable_favorability) {
1622
- systemPrompt += generateLevelPrompt(getFavorabilityLevel(user, this.getFavorabilityConfig()), this.getFavorabilityConfig(), user);
1871
+ const favorabilityLevel = getFavorabilityLevel(user, this.getFavorabilityConfig());
1872
+ if (this.config.enable_mood) {
1873
+ const moodLevel = this.moodManager.getMoodLevel(user.userid);
1874
+ if (moodLevel == "normal" || favorabilityLevel == "厌恶")
1875
+ systemPrompt += generateLevelPrompt(favorabilityLevel, this.getFavorabilityConfig(), user);
1876
+ const moodPrompt = this.moodManager.generateMoodPrompt(user.userid);
1877
+ systemPrompt += `
1878
+ ${moodPrompt}
1879
+ `;
1880
+ } else {
1881
+ systemPrompt += generateLevelPrompt(favorabilityLevel, this.getFavorabilityConfig(), user);
1882
+ }
1623
1883
  }
1624
1884
  if (this.config.no_system_prompt)
1625
1885
  systemPrompt += "如果你明白以上内容,请回复“已明确对话要求”";
1626
1886
  return systemPrompt;
1627
1887
  }
1888
+ // 思考提示
1889
+ getThinkingPrompt(user, prompt) {
1890
+ const reasonerPrompt = this.config.reasoner_prompt;
1891
+ const promptForNoReasoner = `请你在回复时先进行分析思考并输出思考内容,所有思考内容必须使用<think>和</think>包裹输出,而后在最后输出正式的回复内容。${reasonerPrompt}
1892
+ `;
1893
+ const promptForReasoner = `你必须将所有思考内容使用<think>和</think>标签包裹并输出在思维链中,注意不要在最终的输出内包含思考内容。${reasonerPrompt}
1894
+ `;
1895
+ const hasTicket = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on";
1896
+ const maxLength = hasTicket ? user?.items?.["地灵殿通行证"]?.metadata?.use_not_reasoner_LLM_length : this.config.use_not_reasoner_LLM_length;
1897
+ const useNoReasoner = prompt.length <= maxLength;
1898
+ if (!this.config.enable_reasoner_like && useNoReasoner)
1899
+ return "";
1900
+ const reasonerText = `
1901
+ 以下是你的【思考要求】:{
1902
+ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
1903
+ }
1904
+ `;
1905
+ return reasonerText;
1906
+ }
1628
1907
  // 处理回复
1629
1908
  async formatResponse(session, response, auxiliaryResult) {
1630
1909
  const user = await getUser(this.ctx, session.userId);
@@ -1640,13 +1919,20 @@ ${payload}`);
1640
1919
  response += " 喵~";
1641
1920
  if (fumo)
1642
1921
  response += "\nfumofumo";
1922
+ if (this.config.enable_mood && this.config.enable_favorability && this.config.visible_mood) {
1923
+ const moodLevel = this.moodManager.getMoodLevel(user.userid);
1924
+ if (moodLevel == "angry")
1925
+ response += "(怒)";
1926
+ if (moodLevel == "upset")
1927
+ response += "(烦躁)";
1928
+ }
1643
1929
  if (auxiliaryResult && this.config.visible_favorability && !ring)
1644
1930
  response += auxiliaryResult;
1645
1931
  if (replyPointing) {
1646
1932
  response = `@${session.username} ` + response;
1647
1933
  }
1648
1934
  if (this.config.sentences_divide && response.length > 10) {
1649
- const sentences = splitSentences(response).map((text) => import_koishi7.h.text(text));
1935
+ const sentences = splitSentences(response, this.config.min_sentences_length, this.config.max_sentences_length).map((text) => import_koishi8.h.text(text));
1650
1936
  for (const sentence of sentences) {
1651
1937
  await session.send(sentence);
1652
1938
  await new Promise((resolve2) => setTimeout(resolve2, this.config.time_interval));
@@ -1728,9 +2014,6 @@ ${payload}`);
1728
2014
  // 昵称中间件转接
1729
2015
  async handleNickNameMiddleware(session, prompt) {
1730
2016
  const user = await getUser(this.ctx, session.userId);
1731
- const processedPrompt = processPrompt(session.content);
1732
- if (this.performPreChecks(session, processedPrompt))
1733
- return null;
1734
2017
  if (await this.checkUserDialogueCount(session, user, 0))
1735
2018
  return null;
1736
2019
  if (await this.checkFavorabilityBlock(session))
package/lib/mood.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { Context, Session } from 'koishi';
2
+ import { User, Sat } from './types';
3
+ export declare class MoodManager {
4
+ private ctx;
5
+ private config;
6
+ private moodMap;
7
+ constructor(ctx: Context, config: Sat.Config);
8
+ private initUser;
9
+ private checkDailyReset;
10
+ handleInputMoodChange(user: User): Promise<void>;
11
+ handleOutputMoodChange(user: User): Promise<void>;
12
+ applyMoodChange(user: User, delta: number): void;
13
+ getMoodLevel(userId: string): string;
14
+ getMoodValue(userId: string): number;
15
+ generateMoodPrompt(userId: string): string;
16
+ handlePocketMoney(session: Session): Promise<string>;
17
+ setMood(id: string, mood: number): string;
18
+ viewMood(session: Session, id: string): string;
19
+ }
package/lib/types.d.ts CHANGED
@@ -87,11 +87,13 @@ export interface APIConfig {
87
87
  baseURL: string;
88
88
  keys: string[];
89
89
  appointModel: string;
90
+ not_reasoner_LLM_URL: string;
91
+ not_reasoner_LLM: string;
92
+ not_reasoner_LLM_key: string[];
93
+ use_not_reasoner_LLM_length: number;
90
94
  auxiliary_LLM_URL: string;
91
95
  auxiliary_LLM: string;
92
96
  auxiliary_LLM_key: string[];
93
- content_max_tokens: number;
94
- content_max_length: number;
95
97
  temperature: number;
96
98
  frequency_penalty: number;
97
99
  presence_penalty: number;
@@ -143,14 +145,17 @@ export declare namespace Sat {
143
145
  baseURL: string;
144
146
  key: string[];
145
147
  appointModel: string;
148
+ not_reasoner_LLM_URL: string;
149
+ not_reasoner_LLM: string;
150
+ not_reasoner_LLM_key: string[];
151
+ use_not_reasoner_LLM_length: number;
146
152
  auxiliary_LLM_URL: string;
147
153
  auxiliary_LLM: string;
148
154
  auxiliary_LLM_key: string[];
149
155
  prompt: string;
156
+ reasoner_prompt: string;
150
157
  no_system_prompt: boolean;
151
158
  max_tokens: number;
152
- content_max_tokens: number;
153
- content_max_length: number;
154
159
  message_max_length: number;
155
160
  remember_min_length: number;
156
161
  temperature: number;
@@ -172,6 +177,7 @@ export declare namespace Sat {
172
177
  common_topN: number;
173
178
  dailogues_topN: number;
174
179
  enable_fixed_dialogues: boolean;
180
+ enable_reasoner_like: boolean;
175
181
  max_usage: number[];
176
182
  private: boolean;
177
183
  nick_name: boolean;
@@ -185,9 +191,25 @@ export declare namespace Sat {
185
191
  random_min_tokens: number;
186
192
  randnum: number;
187
193
  sentences_divide: boolean;
194
+ min_sentences_length: number;
195
+ max_sentences_length: number;
188
196
  time_interval: number;
189
197
  max_parallel_count: number;
190
198
  reply_pointing: boolean;
199
+ enable_mood: boolean;
200
+ max_mood: number;
201
+ value_of_input_mood: number;
202
+ value_of_output_mood: number;
203
+ visible_mood: boolean;
204
+ mood_div_1: number;
205
+ mood_prompt_0: string;
206
+ mood_div_2: number;
207
+ mood_prompt_1: string;
208
+ mood_prompt_2: string;
209
+ enable_pocket_money: boolean;
210
+ min_pocket_money: number;
211
+ max_pocket_money: number;
212
+ pocket_money_cost: number;
191
213
  enable_favorability: boolean;
192
214
  max_favorability_perday: number;
193
215
  input_censor_favorability: boolean;
package/lib/utils.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { Session } from 'koishi';
1
+ import { Context, Session } from 'koishi';
2
+ import { User } from './types';
2
3
  export declare function escapeRegExp(str: string): string;
3
4
  export declare function parseTimeToMinutes(timeStr: string): number;
4
5
  export declare function parseTime(timestamp: number): number;
5
6
  export declare function getTimeOfDay(hours: number): string;
6
7
  export declare function detectEnglishLetters(text: string): number;
7
8
  export declare function trimSlash(url: string): string;
8
- export declare function splitSentences(text: string): string[];
9
+ export declare function splitSentences(text: string, MIN_LENGTH: number, MAX_LENGTH: number): string[];
9
10
  export declare function shouldFilterContent(content: string, blockWords: string[]): boolean;
10
11
  export declare function probabilisticCheck(probability: number): boolean;
11
12
  export declare function isErrorWithMessage(error: unknown): error is {
@@ -22,5 +23,9 @@ export declare function processPrompt(prompt: string): string;
22
23
  * @param words 需要过滤的关键词
23
24
  * @returns 处理后的字符串,删除含有关键词的部分
24
25
  */
25
- export declare function filterResponse(prompt: string, words: string[]): string;
26
+ export declare function filterResponse(prompt: string, words: string[]): {
27
+ content: string;
28
+ error: boolean;
29
+ };
26
30
  export declare function addOutputCensor(session: Session, word: string, baseURL: string): void;
31
+ export declare function updateUserPWithTicket(ctx: Context, user: User, adjustment: number): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-satori-ai",
3
3
  "description": "基于 Satori 适配器的智能对话插件,具备用户画像、长期记忆、常识管理和好感度系统",
4
- "version": "1.2.9",
4
+ "version": "1.2.11",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "types": "lib/index.d.ts",
package/wasm/gobang.cpp CHANGED
@@ -460,8 +460,7 @@ int wholeScore(int player, const Game &game) {
460
460
  if (temp.score == 0)
461
461
  continue;
462
462
  if (temp.score == player) {
463
- if (player == BLACK)
464
- Score += singleScore(temp, player, game); // 己方落子的单点分相加
463
+ Score += singleScore(temp, player, game); // 己方落子的单点分相加
465
464
  } else
466
465
  Score -= singleScore(temp, 3 - player, game); // 对方落子的单点分相加
467
466
  }
@@ -475,11 +474,10 @@ int inspireSearch(coordinate *scoreBoard, int player, Game &game) {
475
474
  for (int j = 0; j < BOARD_SIZE; j++) {
476
475
  if (game.MAP.board[i][j] == 0) {
477
476
  coordinate temp = {i, j, 0};
478
- if (hasNeighbor(temp, 2, game)) {
477
+ if (hasNeighbor(temp, 3, game)) {
479
478
  scoreBoard[length] = temp;
480
479
  scoreBoard[length].score = singleScore(temp, 3 - player, game);
481
- if (player == BLACK)
482
- scoreBoard[length].score += singleScore(temp, player, game);
480
+ scoreBoard[length].score += singleScore(temp, player, game);
483
481
  length++;
484
482
  }
485
483
  }
@@ -561,8 +559,15 @@ coordinate entrance(int depth, int alpha, int beta, int player, coordinate comma
561
559
  * @param myFlag: 我方棋子颜色
562
560
  * @param depth: 搜索深度
563
561
  * @return: 返回落子位置
562
+ * @outX: 落子横坐标指针
563
+ * @outY: 落子纵坐标指针
564
+ * @outScore: 落子分数指针
565
+ * outX: 落子横坐标
566
+ * outY: 落子纵坐标
567
+ * outScore: 落子分数
568
+ * -1: 游戏平局
564
569
  */
565
- extern "C" int decideMove(const int board[BOARD_SIZE * BOARD_SIZE], int myFlag, int depth) {
570
+ extern "C" void decideMove(const int board[BOARD_SIZE * BOARD_SIZE], int myFlag, int depth, int* outX, int* outY, int* outScore) {
566
571
  Game localGame;
567
572
  for (int i = 0; i < BOARD_SIZE; i++) {
568
573
  for (int j = 0; j < BOARD_SIZE; j++) {
@@ -576,7 +581,12 @@ extern "C" int decideMove(const int board[BOARD_SIZE * BOARD_SIZE], int myFlag,
576
581
  coordinate cmd, current;
577
582
  coordinate result = entrance(depth, _INF, INF, localGame.myFlag, cmd, current, localGame);
578
583
  if (localGame.draw) {
579
- return -1;
584
+ *outX = -1;
585
+ *outY = -1;
586
+ *outScore = -1;
587
+ return;
580
588
  }
581
- return result.score * 10000 + result.x * 100 + result.y;
589
+ *outX = result.x;
590
+ *outY = result.y;
591
+ *outScore = result.score;
582
592
  }
package/wasm/gobang.js CHANGED
@@ -1,21 +1,21 @@
1
- var Module = (() => {
2
- var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
3
- if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;
4
- return (
5
- async function(moduleArg = {}) {
6
- var moduleRtn;
7
-
8
- var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_NODE=true;if(ENVIRONMENT_IS_NODE){}var moduleOverrides={...Module};var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;var runtimeInitialized=false;var isFileURI=filename=>filename.startsWith("file://");function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["c"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("gobang.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return{a:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["b"];updateMemoryViews();removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{receiveInstance(mod,inst);resolve(mod.exports)})})}wasmBinaryFile??=findWasmBinary();try{var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}catch(e){readyPromiseReject(e);return Promise.reject(e)}}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.unshift(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.unshift(cb);var noExitRuntime=Module["noExitRuntime"]||true;var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var wasmImports={a:_emscripten_resize_heap};var wasmExports=await createWasm();var ___wasm_call_ctors=wasmExports["c"];var _decideMove=Module["_decideMove"]=wasmExports["d"];var _malloc=Module["_malloc"]=wasmExports["f"];var _free=Module["_free"]=wasmExports["g"];function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;
9
-
10
-
11
- return moduleRtn;
12
- }
13
- );
14
- })();
15
- if (typeof exports === 'object' && typeof module === 'object') {
16
- module.exports = Module;
17
- // This default export looks redundant, but it allows TS to import this
18
- // commonjs style module.
19
- module.exports.default = Module;
20
- } else if (typeof define === 'function' && define['amd'])
21
- define([], () => Module);
1
+ var Module = (() => {
2
+ var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
3
+ if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;
4
+ return (
5
+ async function(moduleArg = {}) {
6
+ var moduleRtn;
7
+
8
+ var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_NODE=true;if(ENVIRONMENT_IS_NODE){}var moduleOverrides={...Module};var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;var runtimeInitialized=false;var isFileURI=filename=>filename.startsWith("file://");function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["c"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("gobang.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return{a:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["b"];updateMemoryViews();removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{receiveInstance(mod,inst);resolve(mod.exports)})})}wasmBinaryFile??=findWasmBinary();try{var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}catch(e){readyPromiseReject(e);return Promise.reject(e)}}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.unshift(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.unshift(cb);var noExitRuntime=Module["noExitRuntime"]||true;var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var wasmImports={a:_emscripten_resize_heap};var wasmExports=await createWasm();var ___wasm_call_ctors=wasmExports["c"];var _decideMove=Module["_decideMove"]=wasmExports["d"];var _malloc=Module["_malloc"]=wasmExports["f"];var _free=Module["_free"]=wasmExports["g"];function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;
9
+
10
+
11
+ return moduleRtn;
12
+ }
13
+ );
14
+ })();
15
+ if (typeof exports === 'object' && typeof module === 'object') {
16
+ module.exports = Module;
17
+ // This default export looks redundant, but it allows TS to import this
18
+ // commonjs style module.
19
+ module.exports.default = Module;
20
+ } else if (typeof define === 'function' && define['amd'])
21
+ define([], () => Module);
package/wasm/gobang.wasm CHANGED
Binary file