koishi-plugin-chatluna-character 0.0.75 → 0.0.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs CHANGED
@@ -37,200 +37,17 @@ __export(src_exports, {
37
37
  name: () => name
38
38
  });
39
39
  module.exports = __toCommonJS(src_exports);
40
- var import_koishi6 = require("koishi");
40
+ var import_koishi7 = require("koishi");
41
41
 
42
42
  // src/plugins/chat.ts
43
43
  var import_messages = require("@langchain/core/messages");
44
- var import_koishi = require("koishi");
44
+ var import_koishi2 = require("koishi");
45
45
  var import_count_tokens = require("koishi-plugin-chatluna/llm-core/utils/count_tokens");
46
- var import_koishi_plugin_markdown = require("koishi-plugin-markdown");
47
- async function apply(ctx, config) {
48
- const service = ctx.chatluna_character;
49
- const preset = service.preset;
50
- const stickerService = service.stickerService;
51
- logger = service.logger;
52
- const modelPool = {};
53
- const [platform, modelName] = (0, import_count_tokens.parseRawModelName)(config.model);
54
- await ctx.chatluna.awaitLoadPlatform(platform);
55
- const globalModel = await ctx.chatluna.createChatModel(
56
- platform,
57
- modelName
58
- );
59
- logger.info("global model loaded %c", config.model);
60
- if (config.modelOverride?.length > 0) {
61
- for (const override of config.modelOverride) {
62
- modelPool[override.groupId] = (async () => {
63
- const [platform2, modelName2] = (0, import_count_tokens.parseRawModelName)(override.model);
64
- await ctx.chatluna.awaitLoadPlatform(platform2);
65
- const loadedModel = await ctx.chatluna.createChatModel(
66
- platform2,
67
- modelName2
68
- );
69
- logger.info(
70
- "override model loaded %c for group %c",
71
- override.model,
72
- override.groupId
73
- );
74
- modelPool[override.groupId] = Promise.resolve(loadedModel);
75
- return loadedModel;
76
- })();
77
- }
78
- }
79
- let globalPreset = preset.getPresetForCache(config.defaultPreset);
80
- let presetPool = {};
81
- ctx.on("chatluna_character/preset_updated", () => {
82
- globalPreset = preset.getPresetForCache(config.defaultPreset);
83
- presetPool = {};
84
- });
85
- service.collect(async (session, messages) => {
86
- const guildId = session.event.guild?.id ?? session.guildId;
87
- const model = await (modelPool[guildId] ?? Promise.resolve(globalModel));
88
- const currentGuildConfig = config.configs[guildId];
89
- let copyOfConfig = Object.assign({}, config);
90
- let currentPreset = globalPreset;
91
- if (currentGuildConfig != null) {
92
- copyOfConfig = Object.assign({}, copyOfConfig, currentGuildConfig);
93
- currentPreset = presetPool[guildId] ?? await (async () => {
94
- const template = preset.getPresetForCache(
95
- currentGuildConfig.preset
96
- );
97
- presetPool[guildId] = template;
98
- return template;
99
- })();
100
- }
101
- const [recentMessage, lastMessage] = await formatMessage(
102
- messages,
103
- copyOfConfig,
104
- model,
105
- currentPreset.system.template,
106
- currentPreset.system.template
107
- );
108
- const temp = await service.getTemp(session);
109
- const formattedSystemPrompt = await currentPreset.system.format({
110
- time: (/* @__PURE__ */ new Date()).toLocaleString(),
111
- status: temp.status ?? currentPreset.status ?? "",
112
- stickers: JSON.stringify(stickerService.getAllStickTypes())
113
- });
114
- logger.debug("messages_new: " + JSON.stringify(recentMessage));
115
- logger.debug("messages_last: " + JSON.stringify(lastMessage));
116
- const humanMessage = new import_messages.HumanMessage(
117
- await currentPreset.input.format({
118
- history_new: recentMessage,
119
- history_last: lastMessage,
120
- time: (/* @__PURE__ */ new Date()).toLocaleString(),
121
- stickers: JSON.stringify(stickerService.getAllStickTypes()),
122
- status: temp.status ?? currentPreset.status ?? ""
123
- })
124
- );
125
- const completionMessages = await formatCompletionMessages(
126
- [new import_messages.SystemMessage(formattedSystemPrompt)].concat(
127
- temp.completionMessages
128
- ),
129
- humanMessage,
130
- copyOfConfig,
131
- model
132
- );
133
- logger.debug(
134
- "completion message: " + JSON.stringify(completionMessages.map((it) => it.content))
135
- );
136
- let responseMessage;
137
- let parsedResponse;
138
- let retryCount = 0;
139
- while (retryCount < 3) {
140
- retryCount++;
141
- try {
142
- responseMessage = await model.invoke(completionMessages);
143
- } catch (e) {
144
- logger.error("model requests failed", e);
145
- retryCount = 3;
146
- break;
147
- }
148
- try {
149
- logger.debug("model response: " + responseMessage.content);
150
- parsedResponse = parseResponse(
151
- responseMessage.content,
152
- copyOfConfig.isAt
153
- );
154
- break;
155
- } catch (e) {
156
- await (0, import_koishi.sleep)(3e3);
157
- }
158
- }
159
- if (retryCount >= 3) {
160
- return;
161
- }
162
- temp.status = parsedResponse.status;
163
- if (parsedResponse.elements.length < 1) {
164
- service.mute(session, copyOfConfig.muteTime);
165
- return;
166
- }
167
- temp.completionMessages.push(humanMessage, responseMessage);
168
- if (temp.completionMessages.length > 5) {
169
- temp.completionMessages.length = 0;
170
- }
171
- const random = new import_koishi.Random();
172
- for (const elements of parsedResponse.elements) {
173
- const text = elements.map((element) => element.attrs.content ?? "").join("");
174
- const emoticonStatement = isEmoticonStatement(text, elements);
175
- if (elements.length < 1) {
176
- continue;
177
- }
178
- let maxTime = text.length * copyOfConfig.typingTime + 100;
179
- if (parsedResponse.messageType === "voice" && emoticonStatement !== "text") {
180
- continue;
181
- }
182
- if (config.splitVoice !== true && parsedResponse.messageType === "voice") {
183
- maxTime = parsedResponse.rawMessage.length * copyOfConfig.typingTime + 100;
184
- await (0, import_koishi.sleep)(random.int(maxTime / 4, maxTime / 2));
185
- try {
186
- await session.send(
187
- await ctx.vits.say({ input: parsedResponse.rawMessage })
188
- );
189
- } catch (e) {
190
- logger.error(e);
191
- await session.send(elements);
192
- }
193
- continue;
194
- }
195
- try {
196
- if (emoticonStatement !== "emo") {
197
- await (0, import_koishi.sleep)(random.int(maxTime / 2, maxTime));
198
- } else {
199
- await (0, import_koishi.sleep)(random.int(maxTime / 8, maxTime / 2));
200
- }
201
- switch (parsedResponse.messageType) {
202
- case "text":
203
- await session.send(elements);
204
- break;
205
- case "voice":
206
- await session.send(
207
- await ctx.vits.say({
208
- input: text
209
- })
210
- );
211
- break;
212
- default:
213
- await session.send(elements);
214
- break;
215
- }
216
- } catch (e) {
217
- logger.error(e);
218
- await session.send(elements);
219
- }
220
- }
221
- const randomNumber = Math.random();
222
- if (randomNumber < config.sendStickerProbability) {
223
- const sticker = await stickerService.randomStickByType(
224
- parsedResponse.sticker
225
- );
226
- await (0, import_koishi.sleep)(random.int(500, 2e3));
227
- await session.send(sticker);
228
- }
229
- service.mute(session, copyOfConfig.coolDownTime * 1e3);
230
- await service.broadcastOnBot(session, parsedResponse.elements.flat());
231
- });
232
- }
233
- __name(apply, "apply");
46
+
47
+ // src/utils.ts
48
+ var import_koishi = require("koishi");
49
+ var import_marked = require("marked");
50
+ var import_he = __toESM(require("he"), 1);
234
51
  function isEmoticonStatement(text, elements) {
235
52
  if (elements.length === 1 && elements[0].attrs["emo"]) {
236
53
  return "emo";
@@ -281,7 +98,7 @@ function parseResponse(response, useAt = true) {
281
98
  const before = rawMessage.substring(lastAtIndex, at.start);
282
99
  if (before.length > 0) {
283
100
  parsedMessage += before;
284
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(before));
101
+ currentElements.push(...transform(before));
285
102
  }
286
103
  if (useAt) {
287
104
  currentElements.push(import_koishi.h.at(at.at));
@@ -291,11 +108,11 @@ function parseResponse(response, useAt = true) {
291
108
  const after = rawMessage.substring(lastAtIndex);
292
109
  if (after.length > 0) {
293
110
  parsedMessage += after;
294
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(after));
111
+ currentElements.push(...transform(after));
295
112
  }
296
113
  } else {
297
114
  parsedMessage = rawMessage;
298
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(rawMessage));
115
+ currentElements.push(...transform(rawMessage));
299
116
  }
300
117
  const forEachElement = /* @__PURE__ */ __name((elements) => {
301
118
  for (let i = 0; i < elements.length; i++) {
@@ -313,7 +130,12 @@ function parseResponse(response, useAt = true) {
313
130
  continue;
314
131
  }
315
132
  }
316
- const matchArray = splitSentence(text).filter(
133
+ console.log(element);
134
+ if (element.attrs["code"]) {
135
+ resultElements.push([element]);
136
+ continue;
137
+ }
138
+ const matchArray = splitSentence(import_he.default.decode(text)).filter(
317
139
  (x) => x.length > 0
318
140
  );
319
141
  for (const match of matchArray) {
@@ -342,32 +164,6 @@ function parseResponse(response, useAt = true) {
342
164
  };
343
165
  }
344
166
  __name(parseResponse, "parseResponse");
345
- function parseXmlToObject(xml) {
346
- const messageRegex = /<message\s+(.*?)>(.*?)<\/message>/s;
347
- const match = xml.match(messageRegex);
348
- if (!match) {
349
- throw new Error("Failed to parse response: " + xml);
350
- }
351
- const [, attributes, content] = match;
352
- const getAttr = /* @__PURE__ */ __name((name3) => {
353
- const attrRegex = new RegExp(`${name3}=['"]?([^'"]+)['"]?`);
354
- const attrMatch = attributes.match(attrRegex);
355
- if (!attrMatch) {
356
- logger.warn(`Failed to parse ${name3} attribute: ${xml}`);
357
- return "";
358
- }
359
- return attrMatch[1];
360
- }, "getAttr");
361
- const name2 = getAttr("name");
362
- const id = getAttr("id");
363
- const type = getAttr("type") || "text";
364
- const sticker = getAttr("sticker");
365
- if (content === void 0) {
366
- throw new Error("Failed to parse content: " + xml);
367
- }
368
- return { name: name2, id, type, sticker, content };
369
- }
370
- __name(parseXmlToObject, "parseXmlToObject");
371
167
  function splitSentence(text) {
372
168
  if (isOnlyPunctuation(text)) {
373
169
  return [text];
@@ -459,6 +255,33 @@ function matchAt(str) {
459
255
  });
460
256
  }
461
257
  __name(matchAt, "matchAt");
258
+ async function formatMessage(messages, config, model, systemPrompt, historyPrompt) {
259
+ const maxTokens = config.maxTokens - 300;
260
+ let currentTokens = 0;
261
+ currentTokens += await model.getNumTokens(systemPrompt);
262
+ currentTokens += await model.getNumTokens(historyPrompt);
263
+ const calculatedMessages = [];
264
+ const random = new import_koishi.Random();
265
+ for (let i = messages.length - 1; i >= 0; i--) {
266
+ const message = messages[i];
267
+ const voiceProbability = random.int(1, 10) > 8 ? "voice" : "text";
268
+ const xmlMessage = `<message type='${voiceProbability}' name='${message.name}' id='${message.id}'>${message.content}</message>`;
269
+ const xmlMessageToken = await model.getNumTokens(xmlMessage);
270
+ if (currentTokens + xmlMessageToken > maxTokens - 4) {
271
+ break;
272
+ }
273
+ currentTokens += xmlMessageToken;
274
+ calculatedMessages.unshift(xmlMessage);
275
+ }
276
+ const lastMessage = calculatedMessages.pop();
277
+ if (lastMessage === void 0) {
278
+ throw new Error(
279
+ "lastMessage is undefined, please set the max token to be bigger"
280
+ );
281
+ }
282
+ return [calculatedMessages, lastMessage];
283
+ }
284
+ __name(formatMessage, "formatMessage");
462
285
  async function formatCompletionMessages(messages, humanMessage, config, model) {
463
286
  const maxTokens = config.maxTokens - 600;
464
287
  const systemMessage = messages.shift();
@@ -483,34 +306,277 @@ async function formatCompletionMessages(messages, humanMessage, config, model) {
483
306
  return result;
484
307
  }
485
308
  __name(formatCompletionMessages, "formatCompletionMessages");
486
- async function formatMessage(messages, config, model, systemPrompt, historyPrompt) {
487
- const maxTokens = config.maxTokens - 300;
488
- let currentTokens = 0;
489
- currentTokens += await model.getNumTokens(systemPrompt);
490
- currentTokens += await model.getNumTokens(historyPrompt);
491
- const calculatedMessages = [];
492
- const random = new import_koishi.Random();
493
- for (let i = messages.length - 1; i >= 0; i--) {
494
- const message = messages[i];
495
- const voiceProbability = random.int(1, 10) > 8 ? "voice" : "text";
496
- const xmlMessage = `<message type='${voiceProbability}' name='${message.name}' id='${message.id}'>${message.content}</message>`;
497
- const xmlMessageToken = await model.getNumTokens(xmlMessage);
498
- if (currentTokens + xmlMessageToken > maxTokens - 4) {
499
- break;
309
+ function parseXmlToObject(xml) {
310
+ const messageRegex = /<message\s+(.*?)>(.*?)<\/message>/s;
311
+ const match = xml.match(messageRegex);
312
+ if (!match) {
313
+ throw new Error("Failed to parse response: " + xml);
314
+ }
315
+ const [, attributes, content] = match;
316
+ const getAttr = /* @__PURE__ */ __name((name3) => {
317
+ const attrRegex = new RegExp(`${name3}=['"]?([^'"]+)['"]?`);
318
+ const attrMatch = attributes.match(attrRegex);
319
+ if (!attrMatch) {
320
+ logger.warn(`Failed to parse ${name3} attribute: ${xml}`);
321
+ return "";
500
322
  }
501
- currentTokens += xmlMessageToken;
502
- calculatedMessages.unshift(xmlMessage);
323
+ return attrMatch[1];
324
+ }, "getAttr");
325
+ const name2 = getAttr("name");
326
+ const id = getAttr("id");
327
+ const type = getAttr("type") || "text";
328
+ const sticker = getAttr("sticker");
329
+ if (content === void 0) {
330
+ throw new Error("Failed to parse content: " + xml);
503
331
  }
504
- const lastMessage = calculatedMessages.pop();
505
- if (lastMessage === void 0) {
506
- throw new Error(
507
- "lastMessage is undefined, please set the max token to be bigger"
508
- );
332
+ return { name: name2, id, type, sticker, content };
333
+ }
334
+ __name(parseXmlToObject, "parseXmlToObject");
335
+ var tagRegExp = /^<(\/?)([^!\s>/]+)([^>]*?)\s*(\/?)>$/;
336
+ function renderToken(token) {
337
+ if (token.type === "code") {
338
+ return (0, import_koishi.h)("text", { code: true, content: token.text + "\n" });
339
+ } else if (token.type === "paragraph") {
340
+ return (0, import_koishi.h)("p", render(token.tokens));
341
+ } else if (token.type === "image") {
342
+ return import_koishi.h.image(token.href);
343
+ } else if (token.type === "blockquote") {
344
+ return (0, import_koishi.h)("text", { content: token.text + "\n" });
345
+ } else if (token.type === "text") {
346
+ return (0, import_koishi.h)("text", { content: token.text });
347
+ } else if (token.type === "em") {
348
+ return (0, import_koishi.h)("em", render(token.tokens));
349
+ } else if (token.type === "strong") {
350
+ return (0, import_koishi.h)("strong", render(token.tokens));
351
+ } else if (token.type === "del") {
352
+ return (0, import_koishi.h)("del", render(token.tokens));
353
+ } else if (token.type === "link") {
354
+ return (0, import_koishi.h)("a", { href: token.href }, render(token.tokens));
355
+ } else if (token.type === "html") {
356
+ const cap = tagRegExp.exec(token.text);
357
+ if (!cap) {
358
+ return (0, import_koishi.h)("text", { content: token.text });
359
+ }
360
+ if (cap[2] === "img") {
361
+ if (cap[1]) return;
362
+ const src = cap[3].match(/src="([^"]+)"/);
363
+ if (src) return import_koishi.h.image(src[1]);
364
+ }
509
365
  }
510
- return [calculatedMessages, lastMessage];
366
+ return (0, import_koishi.h)("text", { content: token.raw });
511
367
  }
512
- __name(formatMessage, "formatMessage");
368
+ __name(renderToken, "renderToken");
369
+ function render(tokens) {
370
+ return tokens.map(renderToken).filter(Boolean);
371
+ }
372
+ __name(render, "render");
373
+ function transform(source, ...args) {
374
+ if (!source) return [];
375
+ if (Array.isArray(source)) {
376
+ source = args.map((arg, index) => source[index] + arg).join("") + source[args.length];
377
+ }
378
+ return render(import_marked.marked.lexer(source));
379
+ }
380
+ __name(transform, "transform");
513
381
  var logger;
382
+ function setLogger(setLogger2) {
383
+ logger = setLogger2;
384
+ }
385
+ __name(setLogger, "setLogger");
386
+
387
+ // src/plugins/chat.ts
388
+ async function apply(ctx, config) {
389
+ const service = ctx.chatluna_character;
390
+ const preset = service.preset;
391
+ const stickerService = service.stickerService;
392
+ logger2 = service.logger;
393
+ setLogger(logger2);
394
+ const modelPool = {};
395
+ const [platform, modelName] = (0, import_count_tokens.parseRawModelName)(config.model);
396
+ await ctx.chatluna.awaitLoadPlatform(platform);
397
+ const globalModel = await ctx.chatluna.createChatModel(
398
+ platform,
399
+ modelName
400
+ );
401
+ logger2.info("global model loaded %c", config.model);
402
+ if (config.modelOverride?.length > 0) {
403
+ for (const override of config.modelOverride) {
404
+ modelPool[override.groupId] = (async () => {
405
+ const [platform2, modelName2] = (0, import_count_tokens.parseRawModelName)(override.model);
406
+ await ctx.chatluna.awaitLoadPlatform(platform2);
407
+ const loadedModel = await ctx.chatluna.createChatModel(
408
+ platform2,
409
+ modelName2
410
+ );
411
+ logger2.info(
412
+ "override model loaded %c for group %c",
413
+ override.model,
414
+ override.groupId
415
+ );
416
+ modelPool[override.groupId] = Promise.resolve(loadedModel);
417
+ return loadedModel;
418
+ })();
419
+ }
420
+ }
421
+ let globalPreset = preset.getPresetForCache(config.defaultPreset);
422
+ let presetPool = {};
423
+ ctx.on("chatluna_character/preset_updated", () => {
424
+ globalPreset = preset.getPresetForCache(config.defaultPreset);
425
+ presetPool = {};
426
+ });
427
+ service.collect(async (session, messages) => {
428
+ const guildId = session.event.guild?.id ?? session.guildId;
429
+ const model = await (modelPool[guildId] ?? Promise.resolve(globalModel));
430
+ const currentGuildConfig = config.configs[guildId];
431
+ let copyOfConfig = Object.assign({}, config);
432
+ let currentPreset = globalPreset;
433
+ if (currentGuildConfig != null) {
434
+ copyOfConfig = Object.assign({}, copyOfConfig, currentGuildConfig);
435
+ currentPreset = presetPool[guildId] ?? await (async () => {
436
+ const template = preset.getPresetForCache(
437
+ currentGuildConfig.preset
438
+ );
439
+ presetPool[guildId] = template;
440
+ return template;
441
+ })();
442
+ }
443
+ const [recentMessage, lastMessage] = await formatMessage(
444
+ messages,
445
+ copyOfConfig,
446
+ model,
447
+ currentPreset.system.template,
448
+ currentPreset.system.template
449
+ );
450
+ const temp = await service.getTemp(session);
451
+ const formattedSystemPrompt = await currentPreset.system.format({
452
+ time: (/* @__PURE__ */ new Date()).toLocaleString(),
453
+ status: temp.status ?? currentPreset.status ?? "",
454
+ stickers: JSON.stringify(stickerService.getAllStickTypes())
455
+ });
456
+ logger2.debug("messages_new: " + JSON.stringify(recentMessage));
457
+ logger2.debug("messages_last: " + JSON.stringify(lastMessage));
458
+ const humanMessage = new import_messages.HumanMessage(
459
+ await currentPreset.input.format({
460
+ history_new: recentMessage,
461
+ history_last: lastMessage,
462
+ time: (/* @__PURE__ */ new Date()).toLocaleString(),
463
+ stickers: JSON.stringify(stickerService.getAllStickTypes()),
464
+ status: temp.status ?? currentPreset.status ?? ""
465
+ })
466
+ );
467
+ const completionMessages = await formatCompletionMessages(
468
+ [new import_messages.SystemMessage(formattedSystemPrompt)].concat(
469
+ temp.completionMessages
470
+ ),
471
+ humanMessage,
472
+ copyOfConfig,
473
+ model
474
+ );
475
+ logger2.debug(
476
+ "completion message: " + JSON.stringify(completionMessages.map((it) => it.content))
477
+ );
478
+ let responseMessage;
479
+ let parsedResponse;
480
+ let retryCount = 0;
481
+ while (retryCount < 3) {
482
+ retryCount++;
483
+ try {
484
+ responseMessage = await model.invoke(completionMessages);
485
+ } catch (e) {
486
+ logger2.error("model requests failed", e);
487
+ retryCount = 3;
488
+ break;
489
+ }
490
+ try {
491
+ logger2.debug("model response: " + responseMessage.content);
492
+ parsedResponse = parseResponse(
493
+ responseMessage.content,
494
+ copyOfConfig.isAt
495
+ );
496
+ break;
497
+ } catch (e) {
498
+ await (0, import_koishi2.sleep)(3e3);
499
+ }
500
+ }
501
+ if (retryCount >= 3) {
502
+ return;
503
+ }
504
+ temp.status = parsedResponse.status;
505
+ if (parsedResponse.elements.length < 1) {
506
+ service.mute(session, copyOfConfig.muteTime);
507
+ return;
508
+ }
509
+ temp.completionMessages.push(humanMessage, responseMessage);
510
+ if (temp.completionMessages.length > 5) {
511
+ temp.completionMessages.length = 0;
512
+ }
513
+ const random = new import_koishi2.Random();
514
+ for (const elements of parsedResponse.elements) {
515
+ const text = elements.map((element) => element.attrs.content ?? "").join("");
516
+ const emoticonStatement = isEmoticonStatement(text, elements);
517
+ if (elements.length < 1) {
518
+ continue;
519
+ }
520
+ let maxTime = text.length * copyOfConfig.typingTime + 100;
521
+ if (elements.length === 1 && elements[0].attrs["code"] === true) {
522
+ maxTime = 10;
523
+ }
524
+ if (parsedResponse.messageType === "voice" && emoticonStatement !== "text") {
525
+ continue;
526
+ }
527
+ if (config.splitVoice !== true && parsedResponse.messageType === "voice") {
528
+ maxTime = parsedResponse.rawMessage.length * copyOfConfig.typingTime + 100;
529
+ await (0, import_koishi2.sleep)(random.int(maxTime / 4, maxTime / 2));
530
+ try {
531
+ await session.send(
532
+ await ctx.vits.say({ input: parsedResponse.rawMessage })
533
+ );
534
+ } catch (e) {
535
+ logger2.error(e);
536
+ await session.send(elements);
537
+ }
538
+ continue;
539
+ }
540
+ try {
541
+ if (emoticonStatement !== "emo") {
542
+ await (0, import_koishi2.sleep)(random.int(maxTime / 2, maxTime));
543
+ } else {
544
+ await (0, import_koishi2.sleep)(random.int(maxTime / 8, maxTime / 2));
545
+ }
546
+ switch (parsedResponse.messageType) {
547
+ case "text":
548
+ await session.send(elements);
549
+ break;
550
+ case "voice":
551
+ await session.send(
552
+ await ctx.vits.say({
553
+ input: text
554
+ })
555
+ );
556
+ break;
557
+ default:
558
+ await session.send(elements);
559
+ break;
560
+ }
561
+ } catch (e) {
562
+ logger2.error(e);
563
+ await session.send(elements);
564
+ }
565
+ }
566
+ const randomNumber = Math.random();
567
+ if (randomNumber < config.sendStickerProbability) {
568
+ const sticker = await stickerService.randomStickByType(
569
+ parsedResponse.sticker
570
+ );
571
+ await (0, import_koishi2.sleep)(random.int(500, 2e3));
572
+ await session.send(sticker);
573
+ }
574
+ service.mute(session, copyOfConfig.coolDownTime * 1e3);
575
+ await service.broadcastOnBot(session, parsedResponse.elements.flat());
576
+ });
577
+ }
578
+ __name(apply, "apply");
579
+ var logger2;
514
580
 
515
581
  // src/plugins/filter.ts
516
582
  var groupInfos = {};
@@ -518,7 +584,7 @@ async function apply2(ctx, config) {
518
584
  const maxMessages = config.messageInterval;
519
585
  const service = ctx.chatluna_character;
520
586
  const preset = service.preset;
521
- const logger2 = service.logger;
587
+ const logger3 = service.logger;
522
588
  const globalPreset = await preset.getPreset(config.defaultPreset);
523
589
  const presetPool = {};
524
590
  service.addFilter((session, message) => {
@@ -541,7 +607,7 @@ async function apply2(ctx, config) {
541
607
  })();
542
608
  }
543
609
  let { messageCount, messageSendProbability } = info;
544
- logger2.debug(
610
+ logger3.debug(
545
611
  `messageCount: ${messageCount}, messageSendProbability: ${messageSendProbability}. content: ${JSON.stringify(
546
612
  message
547
613
  )}`
@@ -569,7 +635,7 @@ async function apply2(ctx, config) {
569
635
  (value) => message.content.includes(value)
570
636
  );
571
637
  if (needMute) {
572
- logger2.debug(`mute content: ${message.content}`);
638
+ logger3.debug(`mute content: ${message.content}`);
573
639
  service.mute(session, config.muteTime);
574
640
  }
575
641
  }
@@ -625,20 +691,20 @@ function apply3(ctx, config) {
625
691
  __name(apply3, "apply");
626
692
 
627
693
  // src/plugins/config.ts
628
- var import_koishi2 = require("koishi");
694
+ var import_koishi3 = require("koishi");
629
695
  var import_types = require("koishi-plugin-chatluna/llm-core/platform/types");
630
696
  async function apply4(ctx, config) {
631
697
  ctx.on("chatluna/model-added", (service) => {
632
- ctx.schema.set("model", import_koishi2.Schema.union(getModelNames(service)));
698
+ ctx.schema.set("model", import_koishi3.Schema.union(getModelNames(service)));
633
699
  });
634
700
  ctx.on("chatluna/model-removed", (service) => {
635
- ctx.schema.set("model", import_koishi2.Schema.union(getModelNames(service)));
701
+ ctx.schema.set("model", import_koishi3.Schema.union(getModelNames(service)));
636
702
  });
637
- ctx.schema.set("model", import_koishi2.Schema.union(getModelNames(ctx.chatluna.platform)));
703
+ ctx.schema.set("model", import_koishi3.Schema.union(getModelNames(ctx.chatluna.platform)));
638
704
  }
639
705
  __name(apply4, "apply");
640
706
  function getModelNames(service) {
641
- return service.getAllModels(import_types.ModelType.llm).map((m) => import_koishi2.Schema.const(m));
707
+ return service.getAllModels(import_types.ModelType.llm).map((m) => import_koishi3.Schema.const(m));
642
708
  }
643
709
  __name(getModelNames, "getModelNames");
644
710
 
@@ -686,14 +752,14 @@ __name(plugins, "plugins");
686
752
 
687
753
  // src/service/message.ts
688
754
  var import_events = __toESM(require("events"), 1);
689
- var import_koishi5 = require("koishi");
755
+ var import_koishi6 = require("koishi");
690
756
  var import_logger = require("koishi-plugin-chatluna/utils/logger");
691
757
 
692
758
  // src/preset.ts
693
759
  var import_prompts = require("@langchain/core/prompts");
694
760
  var import_promises = __toESM(require("fs/promises"), 1);
695
761
  var import_js_yaml = require("js-yaml");
696
- var import_koishi3 = require("koishi");
762
+ var import_koishi4 = require("koishi");
697
763
  var import_error = require("koishi-plugin-chatluna/utils/error");
698
764
  var import_path = __toESM(require("path"), 1);
699
765
  var import_url = require("url");
@@ -731,8 +797,8 @@ var Preset = class {
731
797
  }
732
798
  this.ctx.schema.set(
733
799
  "character-preset",
734
- import_koishi3.Schema.union(
735
- this._presets.map((preset) => preset.name).concat("无").map((name2) => import_koishi3.Schema.const(name2))
800
+ import_koishi4.Schema.union(
801
+ this._presets.map((preset) => preset.name).concat("无").map((name2) => import_koishi4.Schema.const(name2))
736
802
  )
737
803
  );
738
804
  this.ctx.emit("chatluna_character/preset_updated");
@@ -859,7 +925,7 @@ function loadPreset(text) {
859
925
  __name(loadPreset, "loadPreset");
860
926
 
861
927
  // src/service/sticker.ts
862
- var import_koishi4 = require("koishi");
928
+ var import_koishi5 = require("koishi");
863
929
  var import_path2 = __toESM(require("path"), 1);
864
930
  var import_promises2 = __toESM(require("fs/promises"), 1);
865
931
  var import_url2 = require("url");
@@ -919,7 +985,7 @@ var StickerService = class {
919
985
  this._ctx.root.chatluna_character.logger.debug(
920
986
  `send sticker: ${sticker}`
921
987
  );
922
- return import_koishi4.h.image(await (0, import_promises2.readFile)(sticker), `image/${getFileType(sticker)}`);
988
+ return import_koishi5.h.image(await (0, import_promises2.readFile)(sticker), `image/${getFileType(sticker)}`);
923
989
  }
924
990
  async randomStick() {
925
991
  const allStickers = Object.values(this._stickers).flat();
@@ -931,7 +997,7 @@ var StickerService = class {
931
997
  this._ctx.root.chatluna_character.logger.debug(
932
998
  `send sticker: ${sticker}`
933
999
  );
934
- return import_koishi4.h.image(await (0, import_promises2.readFile)(sticker), `image/${getFileType(sticker)}`);
1000
+ return import_koishi5.h.image(await (0, import_promises2.readFile)(sticker), `image/${getFileType(sticker)}`);
935
1001
  }
936
1002
  };
937
1003
  function getFileType(path3) {
@@ -944,7 +1010,7 @@ function getFileType(path3) {
944
1010
  __name(getFileType, "getFileType");
945
1011
 
946
1012
  // src/service/message.ts
947
- var MessageCollector = class extends import_koishi5.Service {
1013
+ var MessageCollector = class extends import_koishi6.Service {
948
1014
  constructor(ctx, _config) {
949
1015
  super(ctx, "chatluna_character");
950
1016
  this.ctx = ctx;
@@ -1080,7 +1146,7 @@ var MessageCollector = class extends import_koishi5.Service {
1080
1146
  const groupId = session.guildId;
1081
1147
  const maxMessageSize = this._config.maxMessages;
1082
1148
  const groupArray = this._messages[groupId] ? this._messages[groupId] : [];
1083
- const elements = session.elements ? session.elements : [import_koishi5.h.text(session.content)];
1149
+ const elements = session.elements ? session.elements : [import_koishi6.h.text(session.content)];
1084
1150
  const content = mapElementToString(session, session.content, elements);
1085
1151
  if (content.length < 1) {
1086
1152
  await this._unlock(session);
@@ -1101,7 +1167,7 @@ var MessageCollector = class extends import_koishi5.Service {
1101
1167
  session,
1102
1168
  session.quote.content,
1103
1169
  session.quote.elements ?? [
1104
- import_koishi5.h.text(session.quote.content)
1170
+ import_koishi6.h.text(session.quote.content)
1105
1171
  ]
1106
1172
  ),
1107
1173
  name: session.quote.user.name,
@@ -1223,57 +1289,57 @@ var inject2 = {
1223
1289
  required: false
1224
1290
  }
1225
1291
  };
1226
- var Config = import_koishi6.Schema.intersect([
1227
- import_koishi6.Schema.object({
1228
- applyGroup: import_koishi6.Schema.array(import_koishi6.Schema.string()).description("应用到的群组"),
1229
- maxMessages: import_koishi6.Schema.number().description("存储在内存里的最大消息数量").default(10).min(3).role("slider").max(100),
1230
- disableChatLuna: import_koishi6.Schema.boolean().default(true).description("在使用此插件的群聊里,是否禁用 ChatLuna 主功能"),
1231
- whiteListDisableChatLuna: import_koishi6.Schema.array(import_koishi6.Schema.string()).description(
1292
+ var Config = import_koishi7.Schema.intersect([
1293
+ import_koishi7.Schema.object({
1294
+ applyGroup: import_koishi7.Schema.array(import_koishi7.Schema.string()).description("应用到的群组"),
1295
+ maxMessages: import_koishi7.Schema.number().description("存储在内存里的最大消息数量").default(10).min(3).role("slider").max(100),
1296
+ disableChatLuna: import_koishi7.Schema.boolean().default(true).description("在使用此插件的群聊里,是否禁用 ChatLuna 主功能"),
1297
+ whiteListDisableChatLuna: import_koishi7.Schema.array(import_koishi7.Schema.string()).description(
1232
1298
  "在使用此插件时,不禁用 ChatLuna 主功能的群聊列表"
1233
1299
  )
1234
1300
  }).description("基础配置"),
1235
- import_koishi6.Schema.object({
1236
- model: import_koishi6.Schema.dynamic("model").description("使用的模型"),
1237
- modelOverride: import_koishi6.Schema.array(
1238
- import_koishi6.Schema.object({
1239
- groupId: import_koishi6.Schema.string().required().description("群组 ID"),
1240
- model: import_koishi6.Schema.dynamic("model").description("模型")
1301
+ import_koishi7.Schema.object({
1302
+ model: import_koishi7.Schema.dynamic("model").description("使用的模型"),
1303
+ modelOverride: import_koishi7.Schema.array(
1304
+ import_koishi7.Schema.object({
1305
+ groupId: import_koishi7.Schema.string().required().description("群组 ID"),
1306
+ model: import_koishi7.Schema.dynamic("model").description("模型")
1241
1307
  })
1242
1308
  ).description("针对某个群的模型设置,会覆盖上面的配置"),
1243
- maxTokens: import_koishi6.Schema.number().default(5e3).min(1024).max(32e3).description("使用聊天的最大 token 数")
1309
+ maxTokens: import_koishi7.Schema.number().default(5e3).min(1024).max(32e3).description("使用聊天的最大 token 数")
1244
1310
  }).description("模型配置"),
1245
- import_koishi6.Schema.object({
1246
- isNickname: import_koishi6.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1247
- isForceMute: import_koishi6.Schema.boolean().description(
1311
+ import_koishi7.Schema.object({
1312
+ isNickname: import_koishi7.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1313
+ isForceMute: import_koishi7.Schema.boolean().description(
1248
1314
  "是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)"
1249
1315
  ).default(true),
1250
- isAt: import_koishi6.Schema.boolean().description("是否允许 bot 艾特他人").default(true),
1251
- splitVoice: import_koishi6.Schema.boolean().description("是否分段发送语言").default(false),
1252
- messageInterval: import_koishi6.Schema.number().default(14).min(0).role("slider").max(100).description("随机发送消息的间隔"),
1253
- messageProbability: import_koishi6.Schema.number().default(0.1).min(0).max(4).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1254
- coolDownTime: import_koishi6.Schema.number().default(10).min(1).max(60 * 24).description("冷却发言时间(秒)"),
1255
- typingTime: import_koishi6.Schema.number().default(440).min(100).role("slider").max(1500).description("模拟打字时的间隔(毫秒)"),
1256
- muteTime: import_koishi6.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1257
- sendStickerProbability: import_koishi6.Schema.number().default(0.6).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1258
- defaultPreset: import_koishi6.Schema.dynamic("character-preset").description("使用的伪装预设").default("旧梦旧念")
1316
+ isAt: import_koishi7.Schema.boolean().description("是否允许 bot 艾特他人").default(true),
1317
+ splitVoice: import_koishi7.Schema.boolean().description("是否分段发送语言").default(false),
1318
+ messageInterval: import_koishi7.Schema.number().default(14).min(0).role("slider").max(100).description("随机发送消息的间隔"),
1319
+ messageProbability: import_koishi7.Schema.number().default(0.1).min(0).max(4).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1320
+ coolDownTime: import_koishi7.Schema.number().default(10).min(1).max(60 * 24).description("冷却发言时间(秒)"),
1321
+ typingTime: import_koishi7.Schema.number().default(440).min(100).role("slider").max(1500).description("模拟打字时的间隔(毫秒)"),
1322
+ muteTime: import_koishi7.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1323
+ sendStickerProbability: import_koishi7.Schema.number().default(0.6).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1324
+ defaultPreset: import_koishi7.Schema.dynamic("character-preset").description("使用的伪装预设").default("旧梦旧念")
1259
1325
  }).description("对话设置"),
1260
- import_koishi6.Schema.object({
1261
- configs: import_koishi6.Schema.dict(
1262
- import_koishi6.Schema.object({
1263
- maxTokens: import_koishi6.Schema.number().default(4e3).min(1024).max(2e4).description("使用聊天的最大 token 数"),
1264
- isAt: import_koishi6.Schema.boolean().description("是否启用@").default(true),
1265
- splitVoice: import_koishi6.Schema.boolean().description("是否分段发送语言").default(false),
1266
- isNickname: import_koishi6.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1267
- isForceMute: import_koishi6.Schema.boolean().description(
1326
+ import_koishi7.Schema.object({
1327
+ configs: import_koishi7.Schema.dict(
1328
+ import_koishi7.Schema.object({
1329
+ maxTokens: import_koishi7.Schema.number().default(4e3).min(1024).max(2e4).description("使用聊天的最大 token 数"),
1330
+ isAt: import_koishi7.Schema.boolean().description("是否启用@").default(true),
1331
+ splitVoice: import_koishi7.Schema.boolean().description("是否分段发送语言").default(false),
1332
+ isNickname: import_koishi7.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1333
+ isForceMute: import_koishi7.Schema.boolean().description(
1268
1334
  "是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)"
1269
1335
  ).default(true),
1270
- messageInterval: import_koishi6.Schema.number().default(10).min(0).role("slider").max(50).description("随机发送消息的间隔"),
1271
- messageProbability: import_koishi6.Schema.number().default(0.1).min(0).max(1).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1272
- coolDownTime: import_koishi6.Schema.number().default(10).min(1).max(60 * 24 * 24).description("冷却发言时间(秒)"),
1273
- typingTime: import_koishi6.Schema.number().default(440).min(100).role("slider").max(1700).description("模拟打字时的间隔(毫秒)"),
1274
- muteTime: import_koishi6.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1275
- sendStickerProbability: import_koishi6.Schema.number().default(0.2).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1276
- preset: import_koishi6.Schema.dynamic("character-preset").description("使用的伪装预设").default("煕")
1336
+ messageInterval: import_koishi7.Schema.number().default(10).min(0).role("slider").max(50).description("随机发送消息的间隔"),
1337
+ messageProbability: import_koishi7.Schema.number().default(0.1).min(0).max(1).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1338
+ coolDownTime: import_koishi7.Schema.number().default(10).min(1).max(60 * 24 * 24).description("冷却发言时间(秒)"),
1339
+ typingTime: import_koishi7.Schema.number().default(440).min(100).role("slider").max(1700).description("模拟打字时的间隔(毫秒)"),
1340
+ muteTime: import_koishi7.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1341
+ sendStickerProbability: import_koishi7.Schema.number().default(0.2).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1342
+ preset: import_koishi7.Schema.dynamic("character-preset").description("使用的伪装预设").default("煕")
1277
1343
  })
1278
1344
  ).role("table").description("分群配置,会覆盖上面的默认配置(键填写群号)")
1279
1345
  }).description("分群配置")