koishi-plugin-chatluna-think-viewer 1.0.8 → 1.0.10

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.
Files changed (2) hide show
  1. package/index.js +32 -21
  2. package/package.json +5 -5
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const { Schema } = require('koishi');
1
+ const { Schema } = require('koishi');
2
2
 
3
3
  const name = 'chatluna-think-viewer';
4
4
 
@@ -53,12 +53,26 @@ function formatThink(text) {
53
53
  const filtered = lines.filter((l, idx, arr) => !(l === '' && arr[idx - 1] === ''));
54
54
  const nonEmpty = filtered.filter((l) => l.trim().length > 0);
55
55
  const minIndent = nonEmpty.length
56
- ? Math.min(...nonEmpty.map((l) => l.match(/^(\s*)/)?.[1]?.length ?? 0))
56
+ ? Math.min(
57
+ ...nonEmpty.map((l) => {
58
+ const m = l.match(/^(\s*)/);
59
+ return m ? m[1].length : 0;
60
+ }),
61
+ )
57
62
  : 0;
58
63
  return filtered.map((l) => l.slice(minIndent)).join('\n');
59
64
  }
60
65
  }
61
66
 
67
+ function parseIndex(rawIndex) {
68
+ if (!rawIndex) return 1;
69
+ if (typeof rawIndex === 'number' && Number.isFinite(rawIndex) && rawIndex > 0) return Math.floor(rawIndex);
70
+ const match = String(rawIndex).match(/\d+/);
71
+ if (!match) return 1;
72
+ const num = parseInt(match[0], 10);
73
+ return Number.isFinite(num) && num > 0 ? num : 1;
74
+ }
75
+
62
76
  function getNthAiMessage(messages, n = 1) {
63
77
  if (!Array.isArray(messages) || n < 1) return null;
64
78
  let count = 0;
@@ -66,7 +80,7 @@ function getNthAiMessage(messages, n = 1) {
66
80
  const msg = messages[i];
67
81
  const type = typeof msg?._getType === 'function' ? msg._getType() : msg?.type || msg?.role;
68
82
  if (type === 'ai' || type === 'assistant') {
69
- count++;
83
+ count += 1;
70
84
  if (count === n) return msg;
71
85
  }
72
86
  }
@@ -75,14 +89,14 @@ function getNthAiMessage(messages, n = 1) {
75
89
 
76
90
  function apply(ctx, config) {
77
91
  const cmd = ctx
78
- .command(`${config.command} [index:number]`, '获取上一条回复中的 <think> 内容(可指定倒数第 N 条)')
79
- .usage('不带参数默认读取最近一条;例如 think 2 读取倒数第二条 AI 回复的思考。');
92
+ .command(`${config.command} [index:string]`, '获取上一条回复中的 <think> 内容(可指定倒数第 N 条)')
93
+ .usage('不带参数默认读取最近一条;例如 think 2 读取倒数第二条 AI 回复的思考');
80
94
 
81
95
  for (const keyword of config.keywords || []) {
82
96
  cmd.shortcut(keyword, { prefix: false });
83
97
  }
84
98
 
85
- cmd.action(async ({ session }, rawIndex) => {
99
+ cmd.action(async ({ session, args }, rawIndex) => {
86
100
  if (!config.allowPrivate && !session.guildId) {
87
101
  return '仅支持在群聊中查询。';
88
102
  }
@@ -94,26 +108,23 @@ function apply(ctx, config) {
94
108
  const messages = temp?.completionMessages || [];
95
109
  if (!messages.length) return config.emptyMessage;
96
110
 
97
- let targetIndex = parseInt(rawIndex, 10);
98
- if (!Number.isFinite(targetIndex) || targetIndex < 1) targetIndex = 1;
111
+ const targetIndex = parseIndex(rawIndex ?? args?.[0]);
99
112
 
100
- const targetAi = getNthAiMessage(messages, targetIndex);
101
- if (!targetAi) return `找不到倒数第 ${targetIndex} 条 AI 回复的记录。`;
113
+ const targetMessage = getNthAiMessage(messages, targetIndex);
114
+ if (!targetMessage) return config.emptyMessage;
102
115
 
103
- const text = extractText(targetAi.content);
104
- if (!text) return '未找到可解析的回复内容。';
105
-
106
- const think = formatThink(extractThink(text));
107
- if (!think) return config.emptyMessage || '上一次回复中没有 <think> 字段。';
116
+ const think = formatThink(extractThink(extractText(targetMessage.content)));
117
+ if (!think) return config.emptyMessage;
108
118
 
109
119
  if (config.renderImage && ctx.chatluna?.renderer) {
110
120
  try {
111
121
  const title = `### 上一条思考(倒数第 ${targetIndex} 条)`;
112
- const rendered = await ctx.chatluna.renderer.render({
113
- content: [
114
- { type: 'text', text: `${title}\n\n\`\`\`\n${think}\n\`\`\`` },
115
- ],
116
- }, { type: 'image', session });
122
+ const rendered = await ctx.chatluna.renderer.render(
123
+ {
124
+ content: [{ type: 'text', text: `${title}\n\n\`\`\`\n${think}\n\`\`\`` }],
125
+ },
126
+ { type: 'image', session },
127
+ );
117
128
  if (rendered?.length) return rendered.map((r) => r.element);
118
129
  } catch (err) {
119
130
  ctx.logger?.warn?.('[think-viewer] image render failed, fallback text', err);
@@ -129,4 +140,4 @@ module.exports = {
129
140
  apply,
130
141
  Config,
131
142
  inject,
132
- };
143
+ };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
- {
1
+ {
2
2
  "name": "koishi-plugin-chatluna-think-viewer",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "main": "index.js",
5
- "description": "通过命令/关键词查阅 chatluna-character 最近一次回复中的 <think> 思考内容。",
5
+ "description": "通过命令/关键词查看 chatluna-character 最近一次回复中的 <think> 思考内容。",
6
6
  "license": "MIT",
7
7
  "keywords": [
8
8
  "koishi",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "koishi": {
26
26
  "description": {
27
- "zh": "通过命令/关键词查阅 chatluna-character 最近一次回复的 <think> 思考内容。",
27
+ "zh": "通过命令/关键词查看 chatluna-character 最近一次回复的 <think> 思考内容。",
28
28
  "en": "Expose a command/shortcut to read the last <think> block from chatluna-character."
29
29
  },
30
30
  "service": {
@@ -37,4 +37,4 @@
37
37
  "index.js",
38
38
  "README.md"
39
39
  ]
40
- }
40
+ }