koishi-plugin-chatluna-think-viewer 1.0.0
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/README.md +40 -0
- package/index.js +88 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# koishi-plugin-chatluna-think-viewer
|
|
2
|
+
|
|
3
|
+
通过命令或快捷关键词查看 `chatluna-character` 最近一次回复中的 `<think>` 思考内容,便于调试和复盘。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
- 复用 `chatluna-character` 内存,不额外占用数据库。
|
|
7
|
+
- 支持命令与无前缀关键词触发。
|
|
8
|
+
- 群聊可用,默认禁止私聊(可配置)。
|
|
9
|
+
|
|
10
|
+
## 安装
|
|
11
|
+
```bash
|
|
12
|
+
# 使用 Koishi 控制台市场搜索「chatluna-think-viewer」安装
|
|
13
|
+
# 或者 npm/yarn 安装:
|
|
14
|
+
npm install koishi-plugin-chatluna-think-viewer
|
|
15
|
+
# 或
|
|
16
|
+
yarn add koishi-plugin-chatluna-think-viewer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 配置示例 (koishi.yml)
|
|
20
|
+
```yaml
|
|
21
|
+
plugins:
|
|
22
|
+
chatluna-character: {}
|
|
23
|
+
chatluna-think-viewer:
|
|
24
|
+
command: think
|
|
25
|
+
keywords:
|
|
26
|
+
- 查看思考
|
|
27
|
+
- 上次思考
|
|
28
|
+
allowPrivate: false
|
|
29
|
+
emptyMessage: 暂时没有可用的思考记录。
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 使用
|
|
33
|
+
- 群聊中发送 `think`(按你的命令前缀)或关键词“查看思考”/“上次思考”,返回上一条回复的 `<think>` 内容。
|
|
34
|
+
|
|
35
|
+
## 依赖
|
|
36
|
+
- koishi >= 4.18.0
|
|
37
|
+
- koishi-plugin-chatluna-character >= 0.0.180
|
|
38
|
+
|
|
39
|
+
## 协议
|
|
40
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const { Schema } = require('koishi');
|
|
2
|
+
|
|
3
|
+
const name = 'chatluna-think-viewer';
|
|
4
|
+
|
|
5
|
+
const inject = {
|
|
6
|
+
chatluna_character: { required: true },
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Config = Schema.object({
|
|
10
|
+
command: Schema.string().default('think').description('命令名称'),
|
|
11
|
+
keywords: Schema.array(Schema.string()).default(['查看思考', '上次思考']).description('无需前缀即可触发的关键词'),
|
|
12
|
+
allowPrivate: Schema.boolean().default(false).description('是否允许在私聊中使用'),
|
|
13
|
+
emptyMessage: Schema.string().default('暂时没有可用的思考记录。').description('没有记录时的提示文案'),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function extractText(content) {
|
|
17
|
+
if (typeof content === 'string') return content;
|
|
18
|
+
if (Array.isArray(content)) {
|
|
19
|
+
return content
|
|
20
|
+
.map((part) => {
|
|
21
|
+
if (typeof part === 'string') return part;
|
|
22
|
+
if (part && typeof part === 'object') {
|
|
23
|
+
return part.text || part.content || part.value || '';
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
})
|
|
27
|
+
.join('');
|
|
28
|
+
}
|
|
29
|
+
if (content && typeof content === 'object') {
|
|
30
|
+
if (typeof content.text === 'string') return content.text;
|
|
31
|
+
if (typeof content.content === 'string') return content.content;
|
|
32
|
+
if (typeof content.value === 'string') return content.value;
|
|
33
|
+
}
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function extractThink(text) {
|
|
38
|
+
const match = text.match(/<think>([\s\S]*?)<\/think>/i);
|
|
39
|
+
return match?.[1]?.trim() ?? '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getLastAiMessage(messages) {
|
|
43
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
44
|
+
const msg = messages[i];
|
|
45
|
+
const type = typeof msg?._getType === 'function' ? msg._getType() : msg?.type || msg?.role;
|
|
46
|
+
if (type === 'ai' || type === 'assistant') return msg;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function apply(ctx, config) {
|
|
52
|
+
const cmd = ctx.command(config.command, '获取上一条回复中的 <think> 内容');
|
|
53
|
+
|
|
54
|
+
for (const keyword of config.keywords || []) {
|
|
55
|
+
cmd.shortcut(keyword, { prefix: false });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
cmd.action(async ({ session }) => {
|
|
59
|
+
if (!config.allowPrivate && !session.guildId) {
|
|
60
|
+
return '仅支持在群聊中查询。';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const service = ctx.chatluna_character;
|
|
64
|
+
if (!service) return 'chatluna-character 未启用。';
|
|
65
|
+
|
|
66
|
+
const temp = await service.getTemp(session);
|
|
67
|
+
const messages = temp?.completionMessages || [];
|
|
68
|
+
if (!messages.length) return config.emptyMessage;
|
|
69
|
+
|
|
70
|
+
const lastAi = getLastAiMessage(messages);
|
|
71
|
+
if (!lastAi) return config.emptyMessage;
|
|
72
|
+
|
|
73
|
+
const text = extractText(lastAi.content);
|
|
74
|
+
if (!text) return '未找到可解析的回复内容。';
|
|
75
|
+
|
|
76
|
+
const think = extractThink(text);
|
|
77
|
+
if (!think) return '上一次回复中没有 <think> 字段。';
|
|
78
|
+
|
|
79
|
+
return `上一条思考:\n${think}`;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = {
|
|
84
|
+
name,
|
|
85
|
+
apply,
|
|
86
|
+
Config,
|
|
87
|
+
inject,
|
|
88
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "koishi-plugin-chatluna-think-viewer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"description": "通过命令/关键词查看 chatluna-character 最近一次回复中的 <think> 思考内容。",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"koishi",
|
|
9
|
+
"chatluna",
|
|
10
|
+
"character",
|
|
11
|
+
"think"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/your-name/koishi-plugin-chatluna-think-viewer",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/your-name/koishi-plugin-chatluna-think-viewer.git"
|
|
17
|
+
},
|
|
18
|
+
"contributors": [
|
|
19
|
+
"Your Name <you@example.com>"
|
|
20
|
+
],
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"koishi": "^4.18.0",
|
|
23
|
+
"koishi-plugin-chatluna-character": "^0.0.180"
|
|
24
|
+
},
|
|
25
|
+
"koishi": {
|
|
26
|
+
"description": {
|
|
27
|
+
"zh": "通过命令/关键词查看 chatluna-character 最近一次回复的 <think> 思考内容。",
|
|
28
|
+
"en": "Expose a command/shortcut to read the last <think> block from chatluna-character."
|
|
29
|
+
},
|
|
30
|
+
"service": {
|
|
31
|
+
"required": [
|
|
32
|
+
"chatluna_character"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"index.js",
|
|
38
|
+
"README.md"
|
|
39
|
+
]
|
|
40
|
+
}
|