koishi-plugin-satori-ai 1.2.0-beta.2 → 1.2.1

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/api.d.ts CHANGED
@@ -13,6 +13,10 @@ export declare class APIClient {
13
13
  content: string;
14
14
  error: boolean;
15
15
  }>;
16
+ generateUserPortrait(user: User, messages: Sat.Msg[]): Promise<{
17
+ content: string;
18
+ error: boolean;
19
+ }>;
16
20
  private createPayload;
17
21
  private createAuxiliaryPayload;
18
22
  private tryRequest;
package/lib/index.js CHANGED
@@ -137,7 +137,7 @@ function processPrompt(prompt) {
137
137
  }
138
138
  __name(processPrompt, "processPrompt");
139
139
  function filterResponse(prompt, words) {
140
- const parts = prompt.split(/[((][^))]*[))]/g);
140
+ const parts = prompt.split(/([((][^))]*[))])/g);
141
141
  const filtered = parts.map((part) => {
142
142
  if (part.startsWith("(") && part.endsWith(")") || part.startsWith("(") && part.endsWith(")")) {
143
143
  return words.some((word) => part.includes(word)) ? "" : part;
@@ -176,7 +176,7 @@ var APIClient = class {
176
176
  // 发送聊天请求
177
177
  async chat(user, messages) {
178
178
  if (user.userid == "Alice")
179
- return { content: "(系统)(用户)测试", error: false };
179
+ return { content: "(系统)(abc)测试", error: false };
180
180
  const enableUserKey = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description == "on";
181
181
  let keys;
182
182
  let modle;
@@ -205,7 +205,7 @@ var APIClient = class {
205
205
  }
206
206
  // 发送辅助聊天请求
207
207
  async auxiliaryChat(messages) {
208
- const AuxiliaryPayload = this.createAuxiliaryPayload(messages);
208
+ const AuxiliaryPayload = this.createAuxiliaryPayload(messages, this.config.auxiliary_LLM);
209
209
  for (let i = 0; i < this.config.keys.length; i++) {
210
210
  try {
211
211
  return await this.tryRequest(this.config.auxiliary_LLM_URL, AuxiliaryPayload, this.config.auxiliary_LLM_key);
@@ -217,6 +217,34 @@ var APIClient = class {
217
217
  }
218
218
  }
219
219
  }
220
+ // 发送生成用户画像请求
221
+ async generateUserPortrait(user, messages) {
222
+ const enableUserKey = user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description == "on";
223
+ let keys;
224
+ let modle;
225
+ let baseURL;
226
+ if (enableUserKey) {
227
+ const key = user.items["地灵殿通行证"].metadata?.key;
228
+ keys = [key];
229
+ modle = user.items["地灵殿通行证"].metadata?.model;
230
+ baseURL = user.items["地灵殿通行证"].metadata?.baseURL;
231
+ } else {
232
+ keys = this.config.keys;
233
+ modle = this.config.appointModel;
234
+ baseURL = this.config.baseURL;
235
+ }
236
+ const payload = this.createAuxiliaryPayload(messages, modle);
237
+ for (let i = 0; i < keys.length; i++) {
238
+ try {
239
+ return await this.tryRequest(baseURL, payload, keys);
240
+ } catch (error) {
241
+ if (i == keys.length - 1) {
242
+ return this.handleAPIError(error);
243
+ }
244
+ this.rotateKey();
245
+ }
246
+ }
247
+ }
220
248
  // 生成请求体
221
249
  createPayload(messages, model) {
222
250
  return {
@@ -230,9 +258,9 @@ var APIClient = class {
230
258
  };
231
259
  }
232
260
  // 生成辅助请求体
233
- createAuxiliaryPayload(messages) {
261
+ createAuxiliaryPayload(messages, model) {
234
262
  return {
235
- model: this.config.auxiliary_LLM,
263
+ model,
236
264
  messages,
237
265
  temperature: 0.1
238
266
  };
@@ -360,7 +388,7 @@ var MemoryManager = class {
360
388
  }
361
389
  // 是否应当记忆
362
390
  shouldRemember(content) {
363
- return content.length >= this.config.remember_min_length && !this.config.memory_block_words.some((word) => content.includes(word));
391
+ return (content.length >= this.config.remember_min_length || content.includes("记住")) && !this.config.memory_block_words.some((word) => content.includes(word));
364
392
  }
365
393
  // 更新频道对话
366
394
  async updateChannelDialogue(session, prompt, name) {
@@ -987,7 +1015,7 @@ var Sat = class extends import_koishi5.Service {
987
1015
  import_koishi5.Schema.object({
988
1016
  alias: import_koishi5.Schema.array(String).default(["ai"]).description("触发命令;别名"),
989
1017
  authority: import_koishi5.Schema.number().role("slider").min(0).max(5).step(1).description("允许使用的最低权限").default(1),
990
- no_system_prompt: import_koishi5.Schema.boolean().default(false).description("是否将系统提示的system替换为user(用于一些特殊的api格式,例如硅基流动)"),
1018
+ no_system_prompt: import_koishi5.Schema.boolean().default(false).description("是否将系统提示的system替换为user(用于具有思维链的模型或一些特殊的api格式,例如硅基流动)"),
991
1019
  max_tokens: import_koishi5.Schema.number().description("最大请求长度(字符数)").default(100),
992
1020
  content_max_tokens: import_koishi5.Schema.number().description("最大回答长度(思维链+输出token)").default(4096),
993
1021
  content_max_length: import_koishi5.Schema.number().description("最大回答长度(仅输出,字符数)").default(100),
@@ -1031,7 +1059,9 @@ var Sat = class extends import_koishi5.Service {
1031
1059
  randnum: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0).description("在群聊中随机触发对话的概率,如需关闭可设置为 0"),
1032
1060
  sentences_divide: import_koishi5.Schema.boolean().default(true).description("是否分句发送"),
1033
1061
  time_interval: import_koishi5.Schema.number().default(1e3).description("每句话的时间间隔"),
1034
- reply_pointing: import_koishi5.Schema.boolean().default(true).description("是否在与多人同时对话时显示回复指向")
1062
+ reply_pointing: import_koishi5.Schema.boolean().default(true).description("是否在与多人同时对话时显示回复指向"),
1063
+ enable_user_portrait: import_koishi5.Schema.boolean().default(true).description("是否启用用户画像功能"),
1064
+ portrait_min_dialogues: import_koishi5.Schema.number().default(100).description("触发画像生成的最小对话条数")
1035
1065
  }).description("对话设置"),
1036
1066
  import_koishi5.Schema.object({
1037
1067
  enable_favorability: import_koishi5.Schema.boolean().default(false).description("是否开启好感度系统(每次对话默认+1好感度)"),
@@ -1056,11 +1086,7 @@ var Sat = class extends import_koishi5.Service {
1056
1086
  import_koishi5.Schema.object({
1057
1087
  enable_game: import_koishi5.Schema.boolean().default(false).description("是否开启游戏模块"),
1058
1088
  enable_gobang: import_koishi5.Schema.boolean().default(false).description("是否开启五子棋游戏")
1059
- }).description("拓展模块-游戏设置(开发中)"),
1060
- import_koishi5.Schema.object({
1061
- blockuser: import_koishi5.Schema.array(String).default([]).description("屏蔽的用户"),
1062
- blockchannel: import_koishi5.Schema.array(String).default([]).description("屏蔽的频道")
1063
- }).description("过滤器")
1089
+ }).description("拓展模块-游戏设置(开发中)")
1064
1090
  ]);
1065
1091
  })(Sat || (Sat = {}));
1066
1092
 
@@ -1084,6 +1110,7 @@ var SAT = class extends Sat {
1084
1110
  }
1085
1111
  apiClient;
1086
1112
  memoryManager;
1113
+ //private portraitManager: UserPortraitManager
1087
1114
  ChannelParallelCount = /* @__PURE__ */ new Map();
1088
1115
  onlineUsers = [];
1089
1116
  getAPIConfig() {
@@ -1239,10 +1266,6 @@ var SAT = class extends Sat {
1239
1266
  }
1240
1267
  // 前置检查
1241
1268
  performPreChecks(session, prompt) {
1242
- if (this.config.blockuser.includes(session.userId))
1243
- return "";
1244
- if (this.config.blockchannel.includes(session.channelId))
1245
- return "";
1246
1269
  if (!prompt)
1247
1270
  return session.text("commands.sat.messages.no-prompt");
1248
1271
  if (prompt.length > this.config.max_tokens)
@@ -1286,9 +1309,9 @@ var SAT = class extends Sat {
1286
1309
  }
1287
1310
  // 对话次数检查
1288
1311
  async checkUserDialogueCount(session, user, adjustment = 1) {
1312
+ const usage = await updateUserUsage(this.ctx, user, adjustment);
1289
1313
  if (user?.items?.["地灵殿通行证"]?.description && user.items["地灵殿通行证"].description === "on")
1290
1314
  return null;
1291
- const usage = await updateUserUsage(this.ctx, user, adjustment);
1292
1315
  const level = user.userlevel || 0;
1293
1316
  const usageLimit = this.config.max_usage[level] || 0;
1294
1317
  if (usage && usageLimit != 0 && usage > usageLimit) {
@@ -1380,7 +1403,7 @@ ${payload}`);
1380
1403
  if (this.config.enable_favorability) {
1381
1404
  systemPrompt += generateLevelPrompt(getFavorabilityLevel(user, this.getFavorabilityConfig()), this.getFavorabilityConfig(), user);
1382
1405
  }
1383
- if (this.config.personal_memory)
1406
+ if (this.config.no_system_prompt)
1384
1407
  systemPrompt += "如果你明白以上内容,请回复“已明确对话要求”";
1385
1408
  return systemPrompt;
1386
1409
  }
package/lib/types.d.ts CHANGED
@@ -189,6 +189,8 @@ export declare namespace Sat {
189
189
  time_interval: number;
190
190
  max_parallel_count: number;
191
191
  reply_pointing: boolean;
192
+ enable_user_portrait: boolean;
193
+ portrait_min_dialogues: number;
192
194
  enable_favorability: boolean;
193
195
  max_favorability_perday: number;
194
196
  input_censor_favorability: boolean;
@@ -207,8 +209,6 @@ export declare namespace Sat {
207
209
  prompt_3: string;
208
210
  favorability_div_4: number;
209
211
  prompt_4: string;
210
- blockuser: string[];
211
- blockchannel: string[];
212
212
  maxRetryTimes: number;
213
213
  retry_delay_time: number;
214
214
  }
@@ -0,0 +1,16 @@
1
+ import { Context, Session } from 'koishi';
2
+ import { Sat, User } from './types';
3
+ import { APIClient } from './api';
4
+ export declare class UserPortraitManager {
5
+ private ctx;
6
+ private config;
7
+ constructor(ctx: Context, config: Sat.Config);
8
+ private getPortraitPath;
9
+ hasPortrait(userId: string): boolean;
10
+ readPortrait(userId: string): string;
11
+ private processDialogues;
12
+ private buildPrompt;
13
+ generatePortrait(session: Session, user: User, apiClient: APIClient): Promise<void>;
14
+ enhanceSystemPrompt(session: Session): string;
15
+ private getFavorabilityConfig;
16
+ }
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.0-beta.2",
4
+ "version": "1.2.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "types": "lib/index.d.ts",