koishi-plugin-chatluna-character 0.0.74 → 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";
@@ -255,6 +72,9 @@ function parseResponse(response, useAt = true) {
255
72
  /<message_part>\s*(.*?)\s*<\/message_part>/s
256
73
  )?.[1];
257
74
  status = response.match(/<status>(.*?)<\/status>/s)?.[1];
75
+ if (rawMessage == null) {
76
+ rawMessage = response.match(/<message[\s\S]*?<\/message>/)?.[0];
77
+ }
258
78
  if (rawMessage == null) {
259
79
  throw new Error("Failed to parse response: " + response);
260
80
  }
@@ -278,7 +98,7 @@ function parseResponse(response, useAt = true) {
278
98
  const before = rawMessage.substring(lastAtIndex, at.start);
279
99
  if (before.length > 0) {
280
100
  parsedMessage += before;
281
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(before));
101
+ currentElements.push(...transform(before));
282
102
  }
283
103
  if (useAt) {
284
104
  currentElements.push(import_koishi.h.at(at.at));
@@ -288,11 +108,11 @@ function parseResponse(response, useAt = true) {
288
108
  const after = rawMessage.substring(lastAtIndex);
289
109
  if (after.length > 0) {
290
110
  parsedMessage += after;
291
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(after));
111
+ currentElements.push(...transform(after));
292
112
  }
293
113
  } else {
294
114
  parsedMessage = rawMessage;
295
- currentElements.push(...(0, import_koishi_plugin_markdown.transform)(rawMessage));
115
+ currentElements.push(...transform(rawMessage));
296
116
  }
297
117
  const forEachElement = /* @__PURE__ */ __name((elements) => {
298
118
  for (let i = 0; i < elements.length; i++) {
@@ -310,7 +130,12 @@ function parseResponse(response, useAt = true) {
310
130
  continue;
311
131
  }
312
132
  }
313
- 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(
314
139
  (x) => x.length > 0
315
140
  );
316
141
  for (const match of matchArray) {
@@ -339,32 +164,6 @@ function parseResponse(response, useAt = true) {
339
164
  };
340
165
  }
341
166
  __name(parseResponse, "parseResponse");
342
- function parseXmlToObject(xml) {
343
- const messageRegex = /<message\s+(.*?)>(.*?)<\/message>/s;
344
- const match = xml.match(messageRegex);
345
- if (!match) {
346
- throw new Error("Failed to parse response: " + xml);
347
- }
348
- const [, attributes, content] = match;
349
- const getAttr = /* @__PURE__ */ __name((name3) => {
350
- const attrRegex = new RegExp(`${name3}=['"]?([^'"]+)['"]?`);
351
- const attrMatch = attributes.match(attrRegex);
352
- if (!attrMatch) {
353
- logger.warn(`Failed to parse ${name3} attribute: ${xml}`);
354
- return "";
355
- }
356
- return attrMatch[1];
357
- }, "getAttr");
358
- const name2 = getAttr("name");
359
- const id = getAttr("id");
360
- const type = getAttr("type") || "text";
361
- const sticker = getAttr("sticker");
362
- if (content === void 0) {
363
- throw new Error("Failed to parse content: " + xml);
364
- }
365
- return { name: name2, id, type, sticker, content };
366
- }
367
- __name(parseXmlToObject, "parseXmlToObject");
368
167
  function splitSentence(text) {
369
168
  if (isOnlyPunctuation(text)) {
370
169
  return [text];
@@ -456,6 +255,33 @@ function matchAt(str) {
456
255
  });
457
256
  }
458
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");
459
285
  async function formatCompletionMessages(messages, humanMessage, config, model) {
460
286
  const maxTokens = config.maxTokens - 600;
461
287
  const systemMessage = messages.shift();
@@ -480,34 +306,277 @@ async function formatCompletionMessages(messages, humanMessage, config, model) {
480
306
  return result;
481
307
  }
482
308
  __name(formatCompletionMessages, "formatCompletionMessages");
483
- async function formatMessage(messages, config, model, systemPrompt, historyPrompt) {
484
- const maxTokens = config.maxTokens - 300;
485
- let currentTokens = 0;
486
- currentTokens += await model.getNumTokens(systemPrompt);
487
- currentTokens += await model.getNumTokens(historyPrompt);
488
- const calculatedMessages = [];
489
- const random = new import_koishi.Random();
490
- for (let i = messages.length - 1; i >= 0; i--) {
491
- const message = messages[i];
492
- const voiceProbability = random.int(1, 10) > 8 ? "voice" : "text";
493
- const xmlMessage = `<message type='${voiceProbability}' name='${message.name}' id='${message.id}'>${message.content}</message>`;
494
- const xmlMessageToken = await model.getNumTokens(xmlMessage);
495
- if (currentTokens + xmlMessageToken > maxTokens - 4) {
496
- 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 "";
497
322
  }
498
- currentTokens += xmlMessageToken;
499
- 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);
500
331
  }
501
- const lastMessage = calculatedMessages.pop();
502
- if (lastMessage === void 0) {
503
- throw new Error(
504
- "lastMessage is undefined, please set the max token to be bigger"
505
- );
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
+ }
506
365
  }
507
- return [calculatedMessages, lastMessage];
366
+ return (0, import_koishi.h)("text", { content: token.raw });
508
367
  }
509
- __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");
510
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;
511
580
 
512
581
  // src/plugins/filter.ts
513
582
  var groupInfos = {};
@@ -515,7 +584,7 @@ async function apply2(ctx, config) {
515
584
  const maxMessages = config.messageInterval;
516
585
  const service = ctx.chatluna_character;
517
586
  const preset = service.preset;
518
- const logger2 = service.logger;
587
+ const logger3 = service.logger;
519
588
  const globalPreset = await preset.getPreset(config.defaultPreset);
520
589
  const presetPool = {};
521
590
  service.addFilter((session, message) => {
@@ -538,7 +607,7 @@ async function apply2(ctx, config) {
538
607
  })();
539
608
  }
540
609
  let { messageCount, messageSendProbability } = info;
541
- logger2.debug(
610
+ logger3.debug(
542
611
  `messageCount: ${messageCount}, messageSendProbability: ${messageSendProbability}. content: ${JSON.stringify(
543
612
  message
544
613
  )}`
@@ -566,7 +635,7 @@ async function apply2(ctx, config) {
566
635
  (value) => message.content.includes(value)
567
636
  );
568
637
  if (needMute) {
569
- logger2.debug(`mute content: ${message.content}`);
638
+ logger3.debug(`mute content: ${message.content}`);
570
639
  service.mute(session, config.muteTime);
571
640
  }
572
641
  }
@@ -622,20 +691,20 @@ function apply3(ctx, config) {
622
691
  __name(apply3, "apply");
623
692
 
624
693
  // src/plugins/config.ts
625
- var import_koishi2 = require("koishi");
694
+ var import_koishi3 = require("koishi");
626
695
  var import_types = require("koishi-plugin-chatluna/llm-core/platform/types");
627
696
  async function apply4(ctx, config) {
628
697
  ctx.on("chatluna/model-added", (service) => {
629
- ctx.schema.set("model", import_koishi2.Schema.union(getModelNames(service)));
698
+ ctx.schema.set("model", import_koishi3.Schema.union(getModelNames(service)));
630
699
  });
631
700
  ctx.on("chatluna/model-removed", (service) => {
632
- ctx.schema.set("model", import_koishi2.Schema.union(getModelNames(service)));
701
+ ctx.schema.set("model", import_koishi3.Schema.union(getModelNames(service)));
633
702
  });
634
- 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)));
635
704
  }
636
705
  __name(apply4, "apply");
637
706
  function getModelNames(service) {
638
- 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));
639
708
  }
640
709
  __name(getModelNames, "getModelNames");
641
710
 
@@ -683,14 +752,14 @@ __name(plugins, "plugins");
683
752
 
684
753
  // src/service/message.ts
685
754
  var import_events = __toESM(require("events"), 1);
686
- var import_koishi5 = require("koishi");
755
+ var import_koishi6 = require("koishi");
687
756
  var import_logger = require("koishi-plugin-chatluna/utils/logger");
688
757
 
689
758
  // src/preset.ts
690
759
  var import_prompts = require("@langchain/core/prompts");
691
760
  var import_promises = __toESM(require("fs/promises"), 1);
692
761
  var import_js_yaml = require("js-yaml");
693
- var import_koishi3 = require("koishi");
762
+ var import_koishi4 = require("koishi");
694
763
  var import_error = require("koishi-plugin-chatluna/utils/error");
695
764
  var import_path = __toESM(require("path"), 1);
696
765
  var import_url = require("url");
@@ -728,8 +797,8 @@ var Preset = class {
728
797
  }
729
798
  this.ctx.schema.set(
730
799
  "character-preset",
731
- import_koishi3.Schema.union(
732
- 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))
733
802
  )
734
803
  );
735
804
  this.ctx.emit("chatluna_character/preset_updated");
@@ -856,7 +925,7 @@ function loadPreset(text) {
856
925
  __name(loadPreset, "loadPreset");
857
926
 
858
927
  // src/service/sticker.ts
859
- var import_koishi4 = require("koishi");
928
+ var import_koishi5 = require("koishi");
860
929
  var import_path2 = __toESM(require("path"), 1);
861
930
  var import_promises2 = __toESM(require("fs/promises"), 1);
862
931
  var import_url2 = require("url");
@@ -916,7 +985,7 @@ var StickerService = class {
916
985
  this._ctx.root.chatluna_character.logger.debug(
917
986
  `send sticker: ${sticker}`
918
987
  );
919
- 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)}`);
920
989
  }
921
990
  async randomStick() {
922
991
  const allStickers = Object.values(this._stickers).flat();
@@ -928,7 +997,7 @@ var StickerService = class {
928
997
  this._ctx.root.chatluna_character.logger.debug(
929
998
  `send sticker: ${sticker}`
930
999
  );
931
- 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)}`);
932
1001
  }
933
1002
  };
934
1003
  function getFileType(path3) {
@@ -941,7 +1010,7 @@ function getFileType(path3) {
941
1010
  __name(getFileType, "getFileType");
942
1011
 
943
1012
  // src/service/message.ts
944
- var MessageCollector = class extends import_koishi5.Service {
1013
+ var MessageCollector = class extends import_koishi6.Service {
945
1014
  constructor(ctx, _config) {
946
1015
  super(ctx, "chatluna_character");
947
1016
  this.ctx = ctx;
@@ -1077,7 +1146,7 @@ var MessageCollector = class extends import_koishi5.Service {
1077
1146
  const groupId = session.guildId;
1078
1147
  const maxMessageSize = this._config.maxMessages;
1079
1148
  const groupArray = this._messages[groupId] ? this._messages[groupId] : [];
1080
- 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)];
1081
1150
  const content = mapElementToString(session, session.content, elements);
1082
1151
  if (content.length < 1) {
1083
1152
  await this._unlock(session);
@@ -1098,7 +1167,7 @@ var MessageCollector = class extends import_koishi5.Service {
1098
1167
  session,
1099
1168
  session.quote.content,
1100
1169
  session.quote.elements ?? [
1101
- import_koishi5.h.text(session.quote.content)
1170
+ import_koishi6.h.text(session.quote.content)
1102
1171
  ]
1103
1172
  ),
1104
1173
  name: session.quote.user.name,
@@ -1220,57 +1289,57 @@ var inject2 = {
1220
1289
  required: false
1221
1290
  }
1222
1291
  };
1223
- var Config = import_koishi6.Schema.intersect([
1224
- import_koishi6.Schema.object({
1225
- applyGroup: import_koishi6.Schema.array(import_koishi6.Schema.string()).description("应用到的群组"),
1226
- maxMessages: import_koishi6.Schema.number().description("存储在内存里的最大消息数量").default(10).min(3).role("slider").max(100),
1227
- disableChatLuna: import_koishi6.Schema.boolean().default(true).description("在使用此插件的群聊里,是否禁用 ChatLuna 主功能"),
1228
- 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(
1229
1298
  "在使用此插件时,不禁用 ChatLuna 主功能的群聊列表"
1230
1299
  )
1231
1300
  }).description("基础配置"),
1232
- import_koishi6.Schema.object({
1233
- model: import_koishi6.Schema.dynamic("model").description("使用的模型"),
1234
- modelOverride: import_koishi6.Schema.array(
1235
- import_koishi6.Schema.object({
1236
- groupId: import_koishi6.Schema.string().required().description("群组 ID"),
1237
- 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("模型")
1238
1307
  })
1239
1308
  ).description("针对某个群的模型设置,会覆盖上面的配置"),
1240
- 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 数")
1241
1310
  }).description("模型配置"),
1242
- import_koishi6.Schema.object({
1243
- isNickname: import_koishi6.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1244
- 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(
1245
1314
  "是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)"
1246
1315
  ).default(true),
1247
- isAt: import_koishi6.Schema.boolean().description("是否允许 bot 艾特他人").default(true),
1248
- splitVoice: import_koishi6.Schema.boolean().description("是否分段发送语言").default(false),
1249
- messageInterval: import_koishi6.Schema.number().default(14).min(0).role("slider").max(100).description("随机发送消息的间隔"),
1250
- messageProbability: import_koishi6.Schema.number().default(0.1).min(0).max(4).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1251
- coolDownTime: import_koishi6.Schema.number().default(10).min(1).max(60 * 24).description("冷却发言时间(秒)"),
1252
- typingTime: import_koishi6.Schema.number().default(440).min(100).role("slider").max(1500).description("模拟打字时的间隔(毫秒)"),
1253
- muteTime: import_koishi6.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1254
- sendStickerProbability: import_koishi6.Schema.number().default(0.6).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1255
- 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("旧梦旧念")
1256
1325
  }).description("对话设置"),
1257
- import_koishi6.Schema.object({
1258
- configs: import_koishi6.Schema.dict(
1259
- import_koishi6.Schema.object({
1260
- maxTokens: import_koishi6.Schema.number().default(4e3).min(1024).max(2e4).description("使用聊天的最大 token 数"),
1261
- isAt: import_koishi6.Schema.boolean().description("是否启用@").default(true),
1262
- splitVoice: import_koishi6.Schema.boolean().description("是否分段发送语言").default(false),
1263
- isNickname: import_koishi6.Schema.boolean().description("允许 bot 配置中的昵称引发回复").default(true),
1264
- 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(
1265
1334
  "是否启用强制禁言(当聊天涉及到关键词时则会禁言,关键词需要在预设文件里配置)"
1266
1335
  ).default(true),
1267
- messageInterval: import_koishi6.Schema.number().default(10).min(0).role("slider").max(50).description("随机发送消息的间隔"),
1268
- messageProbability: import_koishi6.Schema.number().default(0.1).min(0).max(1).role("slider").step(1e-5).description("发送消息的叠加概率(线性增长)"),
1269
- coolDownTime: import_koishi6.Schema.number().default(10).min(1).max(60 * 24 * 24).description("冷却发言时间(秒)"),
1270
- typingTime: import_koishi6.Schema.number().default(440).min(100).role("slider").max(1700).description("模拟打字时的间隔(毫秒)"),
1271
- muteTime: import_koishi6.Schema.number().default(1e3 * 60).min(1e3).max(1e3 * 60 * 10 * 10).description("闭嘴时的禁言时间(毫秒)"),
1272
- sendStickerProbability: import_koishi6.Schema.number().default(0.2).min(0).max(1).role("slider").step(0.01).description("发送表情的概率"),
1273
- 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("煕")
1274
1343
  })
1275
1344
  ).role("table").description("分群配置,会覆盖上面的默认配置(键填写群号)")
1276
1345
  }).description("分群配置")