koishi-plugin-chatluna-think-viewer 2.2.4 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +72 -30
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { Schema, h } = require('koishi');
|
|
1
|
+
const { Schema, h } = require('koishi');
|
|
2
2
|
const { Bot } = require('@satorijs/core');
|
|
3
3
|
|
|
4
4
|
const name = 'chatluna-think-viewer';
|
|
@@ -8,8 +8,8 @@ const inject = {
|
|
|
8
8
|
chatluna: { required: false },
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const defaultForbidden = [
|
|
12
|
-
'<think>[\\s\\S]*?<\\/think>',
|
|
11
|
+
const defaultForbidden = [
|
|
12
|
+
'<think>[\\s\\S]*?<\\/think>',
|
|
13
13
|
'<status>[\\s\\S]*?<\\/status>',
|
|
14
14
|
'<output>[\\s\\S]*?<\\/output>',
|
|
15
15
|
'<analysis>[\\s\\S]*?<\\/analysis>',
|
|
@@ -19,16 +19,16 @@ const defaultForbidden = [
|
|
|
19
19
|
'"role"\\s*:\\s*"assistant"',
|
|
20
20
|
'"analysis"\\s*:',
|
|
21
21
|
'"thought"\\s*:',
|
|
22
|
-
'(?:human_relations
|
|
23
|
-
'(?:memory
|
|
22
|
+
'(?:human_relations|浜洪檯鍏崇郴)\\s*[:=]',
|
|
23
|
+
'(?:memory|璁板繂|璁板繂鐐箌鎬荤粨)\\s*[:=]',
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
-
//
|
|
27
|
-
//
|
|
26
|
+
// 涓ユ牸 <output><message>... 缁撴瀯锛氬厑璁告枃鏈?/ <at>user_id</at> 鏂囨湰 / <sticker>url</sticker>
|
|
27
|
+
// 仅允许 1~5 条 <message>,@ 只接受纯数字的 user_id
|
|
28
28
|
const strictOutputPattern =
|
|
29
29
|
'^\\s*<output>\\s*(<message>(?:<at>\\d+<\\/at>\\s*)?(?:<sticker>[^<]*<\\/sticker>|[^<]*)<\\/message>\\s*){1,5}<\\/output>\\s*$';
|
|
30
30
|
|
|
31
|
-
const Config = Schema.intersect([
|
|
31
|
+
const Config = Schema.intersect([
|
|
32
32
|
Schema.object({
|
|
33
33
|
command: Schema.string().default('think').description('\u67e5\u770b\u601d\u8003\u5185\u5bb9\u7684\u6307\u4ee4\u540d'),
|
|
34
34
|
keywords: Schema.array(Schema.string()).default(['\u67e5\u770b\u601d\u8003', '\u4e0a\u6b21\u601d\u8003']).description('\u53ef\u65e0\u524d\u7f00\u89e6\u53d1\u7684\u5173\u952e\u8bcd'),
|
|
@@ -42,7 +42,7 @@ const Config = Schema.intersect([
|
|
|
42
42
|
guardDelay: Schema.number().default(1).min(0).max(60).description('\u64a4\u56de\u5ef6\u8fdf\uff08\u79d2\uff09'),
|
|
43
43
|
guardAllowPrivate: Schema.boolean().default(true).description('\u662f\u5426\u5728\u79c1\u804a\u4e2d\u4e5f\u542f\u7528\u62e6\u622a'),
|
|
44
44
|
guardGroups: Schema.array(Schema.string()).default([]).description('\u53ea\u5728\u8fd9\u4e9b\u7fa4\u751f\u6548\uff0c\u7559\u7a7a\u8868\u793a\u5168\u90e8'),
|
|
45
|
-
guardKeywordMode: Schema.boolean().default(true).description('true \u65f6\u6309\u5173\u952e\u8bcd\u5b50\u4e32\u5339\u914d
|
|
45
|
+
guardKeywordMode: Schema.boolean().default(true).description('true \u65f6\u6309\u5173\u952e\u8bcd\u5b50\u4e32\u5339\u914d锛圽u4e0d\u533a\u5206\u5927\u5c0f\u5199锛塡uff0cfalse \u65f6\u6309\u6b63\u5219\u5339\u914d'),
|
|
46
46
|
guardForbiddenPatterns: Schema.array(Schema.string())
|
|
47
47
|
.default(defaultForbidden)
|
|
48
48
|
.description('\u547d\u4e2d\u5373\u89c6\u4e3a\u5f02\u5e38\u7684\u6a21\u5f0f\uff0c\u7528\u4e8e\u907f\u514d\u601d\u8003\u6cc4\u9732\u6216\u0020\u004a\u0053\u004f\u004e\u0020\u751f\u51fa'),
|
|
@@ -60,23 +60,33 @@ const Config = Schema.intersect([
|
|
|
60
60
|
}).description('\u5f02\u5e38\u8f93\u51fa\u81ea\u52a8\u5904\u7406'),
|
|
61
61
|
]);
|
|
62
62
|
|
|
63
|
-
function extractText(content) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
63
|
+
function extractText(content) {
|
|
64
|
+
// Normalize varied content types to plain text so we can regex <think>.
|
|
65
|
+
if (content == null) return '';
|
|
66
|
+
if (typeof content === 'string') return content;
|
|
67
|
+
if (Array.isArray(content)) return content.map(extractText).join('');
|
|
68
|
+
|
|
69
|
+
const parts = [];
|
|
70
|
+
// Try koishi segment normalization first.
|
|
71
|
+
try {
|
|
72
|
+
for (const el of h.normalize([content])) {
|
|
73
|
+
if (typeof el === 'string') {
|
|
74
|
+
parts.push(el);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(el.children) && el.children.length) {
|
|
78
|
+
parts.push(extractText(el.children));
|
|
79
|
+
}
|
|
80
|
+
const textLike = el.attrs?.content ?? el.attrs?.text ?? el.children?.join?.('') ?? '';
|
|
81
|
+
if (textLike) parts.push(textLike);
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
// Fallback for plain objects (e.g., LangChain AIMessage with {text, content})
|
|
85
|
+
const candidate = content.text ?? content.content;
|
|
86
|
+
if (candidate) parts.push(String(candidate));
|
|
87
|
+
}
|
|
88
|
+
return parts.join('');
|
|
89
|
+
}
|
|
80
90
|
|
|
81
91
|
function extractThink(text) {
|
|
82
92
|
// \u67d0\u4e9b\u6a21\u578b/\u4e2d\u95f4\u4ef6\u4f1a\u5728\u540c\u4e00\u6761\u6d88\u606f\u91cc\u591a\u6b21\u51fa\u73b0 <think>\uff0c\u53d6\u6700\u540e\u4e00\u6b21
|
|
@@ -313,10 +323,42 @@ function apply(ctx, config) {
|
|
|
313
323
|
});
|
|
314
324
|
|
|
315
325
|
// \u5f02\u5e38\u8f93\u51fa\u81ea\u52a8\u5904\u7406
|
|
316
|
-
applyGuard(ctx, config);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
326
|
+
applyGuard(ctx, config);
|
|
327
|
+
|
|
328
|
+
// Hot-fix chatluna-character completionMessages trimming bug:
|
|
329
|
+
// it used to drop newest messages; we wrap getTemp to trim from the head.
|
|
330
|
+
const service = ctx.chatluna_character;
|
|
331
|
+
if (service && typeof service.getTemp === 'function') {
|
|
332
|
+
const originalGetTemp = service.getTemp.bind(service);
|
|
333
|
+
service.getTemp = async function patchedGetTemp(session) {
|
|
334
|
+
const temp = await originalGetTemp(session);
|
|
335
|
+
const limit = () => {
|
|
336
|
+
const c = service._config?.modelCompletionCount ?? 3;
|
|
337
|
+
return Math.max(2, c * 2);
|
|
338
|
+
};
|
|
339
|
+
if (Array.isArray(temp.completionMessages) && !temp.completionMessages._thinkViewerPatched) {
|
|
340
|
+
const arr = temp.completionMessages;
|
|
341
|
+
const originalPush = arr.push;
|
|
342
|
+
arr.push = function patchedPush(...args) {
|
|
343
|
+
const res = originalPush.apply(this, args);
|
|
344
|
+
const max = limit();
|
|
345
|
+
if (this.length > max) {
|
|
346
|
+
this.splice(0, this.length - max);
|
|
347
|
+
}
|
|
348
|
+
return res;
|
|
349
|
+
};
|
|
350
|
+
Object.defineProperty(arr, '_thinkViewerPatched', { value: true, enumerable: false });
|
|
351
|
+
}
|
|
352
|
+
return temp;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
ctx.on('dispose', () => {
|
|
356
|
+
service.getTemp = originalGetTemp;
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
module.exports = {
|
|
320
362
|
name,
|
|
321
363
|
apply,
|
|
322
364
|
Config,
|