koishi-plugin-chatluna-think-viewer 2.0.1 → 2.1.1

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 (3) hide show
  1. package/README.md +10 -9
  2. package/index.js +25 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
  - 依赖 `chatluna-character` 存储的思考上下文,支持命令与前缀关键词调用。
7
7
  - 支持群聊使用(可配置是否允许私聊)。
8
8
  - **异常格式自动撤回/拦截**:默认检测 `<think>`、`<status>`、`<output>`、`<analysis>`、`<system>` 等块或调试 JSON、think/json/yaml 代码块;命中后可选择先发后撤回(recall)或直接阻止(block)。
9
- - **严格输出模式(可选)**:仅当开启 `guardStrictOutputOnly` 时,要求 `<output><message>…</message></output>` 结构;@ 仅允许数字 user_id,1~5 条 message。不开启则不做白名单校验,避免正常消息被误撤回。
9
+ - **关键词模式**(默认开启):`guardKeywordMode=true` 时按不区分大小写的子串匹配拦截;想用正则可把它关掉。
10
+ - **严格输出模式**(可选):仅当开启 `guardStrictOutputOnly` 时,要求 `<output><message>…</message></output>` 结构;@ 仅允许数字 user_id,1~5 条 message。默认关闭以避免误撤回。
10
11
 
11
12
  ## 安装
12
13
  ```bash
13
- # Koishi 控制台市场搜索 chatluna-think-viewer 安装
14
14
  npm install koishi-plugin-chatluna-think-viewer
15
15
  ```
16
16
 
@@ -24,21 +24,22 @@ plugins:
24
24
  - 查看思考
25
25
  allowPrivate: false
26
26
  emptyMessage: 暂时没有可用的思考记录。
27
- # 异常撤回/拦截
27
+ # 守卫配置
28
28
  guardEnabled: true
29
29
  guardMode: recall # recall | block
30
30
  guardDelay: 1 # 撤回延迟(秒),block 模式忽略
31
- guardStrictOutputOnly: false # 默认关闭严格模式,避免误撤回
32
- guardStrictPattern: '^\s*<output>\s*(<message>(?:<at>\d+<\/at>\s*)?(?:<sticker>[^<]*<\/sticker>|[^<]*)<\/message>\s*){1,5}<\/output>\s*$'
31
+ guardKeywordMode: true # 子串匹配关键词(默认)
32
+ guardStrictOutputOnly: false # 严格格式校验默认关闭
33
33
  guardForbiddenPatterns:
34
- - '<think>[\\s\\S]*?<\\/think>'
35
- - '<status>[\\s\\S]*?<\\/status>'
36
- - '```\\s*think[\\s\\S]*?```'
34
+ - '<think>'
35
+ - '<status>'
36
+ - '<output>'
37
+ - '```think'
37
38
  ```
38
39
 
39
40
  ## 使用
40
41
  - 群聊里发送 `think` 或配置的关键词查看最近一次 `<think>` 内容;`think 2` 查看倒数第 2 条。
41
- - 异常/严格模式:当 bot 发送的消息命中禁用规则或不符合严格输出结构时,记录日志并撤回(或直接阻止发送)。
42
+ - 守卫:当 bot 发送的消息命中禁用规则(或在你开启严格模式时不符合格式)会记录日志并阻止/撤回发送。
42
43
 
43
44
  ## 依赖
44
45
  - koishi >= 4.18.0
package/index.js CHANGED
@@ -42,6 +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(\u4e0d\u533a\u5206\u5927\u5c0f\u5199)\uff0cfalse \u65f6\u6309\u6b63\u5219\u5339\u914d'),
45
46
  guardForbiddenPatterns: Schema.array(Schema.string())
46
47
  .default(defaultForbidden)
47
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'),
@@ -162,11 +163,17 @@ function getLatestRawThink(temp) {
162
163
  return '';
163
164
  }
164
165
 
165
- function compileRegex(list) {
166
+ function compileMatchers(list, keywordMode = true) {
166
167
  return (list || [])
167
168
  .map((p) => {
169
+ const source = String(p || '');
170
+ if (keywordMode) {
171
+ const needle = source.toLowerCase();
172
+ return { test: (text = '') => text.toLowerCase().includes(needle) };
173
+ }
168
174
  try {
169
- return new RegExp(p, 'i');
175
+ const re = new RegExp(source, 'i');
176
+ return { test: (text = '') => re.test(text) };
170
177
  } catch (err) {
171
178
  return null;
172
179
  }
@@ -176,11 +183,17 @@ function compileRegex(list) {
176
183
 
177
184
  function detectAbnormal(text, forbidden, allowed, strictMode = false) {
178
185
  if (!text) return null;
179
- for (const re of forbidden) {
180
- if (re.test(text)) return `\u547d\u4e2d\u7981\u6b62\u6a21\u5f0f: /${re.source}/`;
186
+ for (const m of forbidden) {
187
+ if (m.test(text)) return '??????';
188
+ }
189
+ if (strictMode) {
190
+ if (!allowed.length || !allowed.some((m) => m.test(text))) {
191
+ return '?????????';
192
+ }
193
+ return null;
181
194
  }
182
- if (allowed.length && !allowed.some((re) => re.test(text))) {
183
- return '\u672a\u5339\u914d\u4efb\u4f55\u5141\u8bb8\u6a21\u5f0f';
195
+ if (allowed.length && !allowed.some((m) => m.test(text))) {
196
+ return '?????????';
184
197
  }
185
198
  return null;
186
199
  }
@@ -204,10 +217,12 @@ function shouldGuard(config, options) {
204
217
  function applyGuard(ctx, config) {
205
218
  if (!config.guardEnabled) return;
206
219
  const logger = ctx.logger(`${name}:guard`);
207
- const forbidden = compileRegex(config.guardForbiddenPatterns);
208
- const allowed = config.guardStrictOutputOnly
209
- ? compileRegex([config.guardStrictPattern || strictOutputPattern])
210
- : compileRegex(config.guardAllowedPatterns);
220
+ const strictMode = !!config.guardStrictOutputOnly;
221
+ const keywordMode = config.guardKeywordMode !== false;
222
+ const forbidden = compileMatchers(config.guardForbiddenPatterns, keywordMode);
223
+ const allowed = strictMode
224
+ ? compileMatchers([config.guardStrictPattern || strictOutputPattern], false)
225
+ : compileMatchers(config.guardAllowedPatterns, keywordMode);
211
226
  const original = Bot.prototype.sendMessage;
212
227
 
213
228
  Bot.prototype.sendMessage = async function patched(channelId, content, referrer, options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-chatluna-think-viewer",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "main": "index.js",
5
5
  "description": "View chatluna <think> blocks and auto recall abnormal formatted replies.",
6
6
  "license": "MIT",