@tencent-weixin/openclaw-weixin 2.1.7 → 2.1.8

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/LICENSE CHANGED
@@ -1,21 +1,27 @@
1
- MIT License
1
+ Tencent is pleased to support the open source community by making openclaw-weixin available.
2
2
 
3
- Copyright (c) 2026 Tencent Inc.
3
+ Copyright (C) 2026 Tencent. All rights reserved.
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ openclaw-weixin is licensed under the MIT.
11
6
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
7
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
8
+ Terms of the MIT:
9
+ --------------------------------------------------------------------
10
+ Permission is hereby granted, free of charge, to any person obtaining
11
+ a copy of this software and associated documentation files (the
12
+ "Software"), to deal in the Software without restriction, including
13
+ without limitation the rights to use, copy, modify, merge, publish,
14
+ distribute, sublicense, and/or sell copies of the Software, and to
15
+ permit persons to whom the Software is furnished to do so, subject to
16
+ the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "openclaw-weixin",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "channels": [
5
5
  "openclaw-weixin"
6
6
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-weixin/openclaw-weixin",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "OpenClaw Weixin channel",
5
5
  "license": "MIT",
6
6
  "author": "Tencent",
@@ -6,9 +6,22 @@
6
6
  * holding back the minimum characters needed for pattern disambiguation
7
7
  * (e.g. a trailing `*` that might become `***`).
8
8
  *
9
+ * Constructs passed through (not filtered):
10
+ * - Code fences (```)
11
+ * - Inline code (`)
12
+ * - Tables (|...|)
13
+ * - Horizontal rules (---, ***, ___)
14
+ * - Bold (**)
15
+ * - Italic/bold-italic wrapping non-CJK content
16
+ *
17
+ * Constructs filtered (markers stripped, content kept):
18
+ * - Italic/bold-italic wrapping CJK content
19
+ * - Headings H5/H6 (#####, ######)
20
+ * - Images (![alt](url)) — removed entirely
21
+ *
9
22
  * States:
10
23
  * - **sol** (start-of-line): checks for line-start patterns (```, >, #####, indent)
11
- * - **body**: scans for inline patterns (`, ![, ~~, ***) and outputs safe chars
24
+ * - **body**: scans for inline patterns (![, ~~, ***) and outputs safe chars
12
25
  * - **fence**: inside a fenced code block, passes through until closing ```
13
26
  * - **inline**: accumulating content inside an inline marker pair
14
27
  */
@@ -16,7 +29,7 @@ export class StreamingMarkdownFilter {
16
29
  private buf = "";
17
30
  private fence = false;
18
31
  private sol = true;
19
- private inl: { type: "code" | "image" | "strike" | "bold3" | "italic" | "ubold3" | "uitalic" | "table"; acc: string } | null = null;
32
+ private inl: { type: "image" | "bold3" | "italic" | "ubold3" | "uitalic"; acc: string } | null = null;
20
33
 
21
34
  feed(delta: string): string {
22
35
  this.buf += delta;
@@ -45,26 +58,32 @@ export class StreamingMarkdownFilter {
45
58
  }
46
59
 
47
60
  if (eof && this.inl) {
48
- if (this.inl.type === "table") {
49
- out += StreamingMarkdownFilter.extractTableRow(this.inl.acc);
50
- } else {
51
- const markers: Record<string, string> = { code: "`", image: "![", strike: "~~", bold3: "***", italic: "*", ubold3: "___", uitalic: "_" };
52
- out += (markers[this.inl.type] ?? "") + this.inl.acc;
53
- }
61
+ const markers: Record<string, string> = { image: "![", bold3: "***", italic: "*", ubold3: "___", uitalic: "_" };
62
+ out += (markers[this.inl.type] ?? "") + this.inl.acc;
54
63
  this.inl = null;
55
64
  }
56
65
  return out;
57
66
  }
58
67
 
59
- /** Inside a code fence: pass content through, watch for closing ``` at SOL. */
68
+ /** Inside a code fence: pass content and markers through verbatim. */
60
69
  private pumpFence(eof: boolean): string {
61
70
  if (this.sol) {
62
71
  if (this.buf.length < 3 && !eof) return "";
63
72
  if (this.buf.startsWith("```")) {
64
- this.fence = false;
65
73
  const nl = this.buf.indexOf("\n", 3);
66
- this.buf = nl !== -1 ? this.buf.slice(nl + 1) : "";
67
- this.sol = true;
74
+ if (nl !== -1) {
75
+ this.fence = false;
76
+ const line = this.buf.slice(0, nl + 1);
77
+ this.buf = this.buf.slice(nl + 1);
78
+ this.sol = true;
79
+ return line;
80
+ }
81
+ if (eof) {
82
+ this.fence = false;
83
+ const line = this.buf;
84
+ this.buf = "";
85
+ return line;
86
+ }
68
87
  return "";
69
88
  }
70
89
  this.sol = false;
@@ -93,10 +112,18 @@ export class StreamingMarkdownFilter {
93
112
  if (b[0] === "`") {
94
113
  if (b.length < 3 && !eof) return "";
95
114
  if (b.startsWith("```")) {
96
- this.fence = true;
97
115
  const nl = b.indexOf("\n", 3);
98
- this.buf = nl !== -1 ? b.slice(nl + 1) : "";
99
- this.sol = true;
116
+ if (nl !== -1) {
117
+ this.fence = true;
118
+ const line = b.slice(0, nl + 1);
119
+ this.buf = b.slice(nl + 1);
120
+ this.sol = true;
121
+ return line;
122
+ }
123
+ if (eof) {
124
+ this.buf = "";
125
+ return b;
126
+ }
100
127
  return "";
101
128
  }
102
129
  this.sol = false;
@@ -104,8 +131,6 @@ export class StreamingMarkdownFilter {
104
131
  }
105
132
 
106
133
  if (b[0] === ">") {
107
- if (b.length < 2 && !eof) return "";
108
- this.buf = b.length >= 2 && b[1] === " " ? b.slice(2) : b.slice(1);
109
134
  this.sol = false;
110
135
  return "";
111
136
  }
@@ -123,13 +148,6 @@ export class StreamingMarkdownFilter {
123
148
  return "";
124
149
  }
125
150
 
126
- if (b[0] === "|") {
127
- this.buf = b.slice(1);
128
- this.inl = { type: "table", acc: "" };
129
- this.sol = false;
130
- return "";
131
- }
132
-
133
151
  if (b[0] === " " || b[0] === "\t") {
134
152
  if (b.search(/[^ \t]/) === -1 && !eof) return "";
135
153
  this.sol = false;
@@ -145,9 +163,13 @@ export class StreamingMarkdownFilter {
145
163
  let count = 0;
146
164
  for (let k = 0; k < j; k++) if (b[k] === ch) count++;
147
165
  if (count >= 3) {
148
- this.buf = j < b.length ? b.slice(j + 1) : "";
149
- this.sol = true;
150
- return "";
166
+ if (j < b.length) {
167
+ this.buf = b.slice(j + 1);
168
+ this.sol = true;
169
+ return b.slice(0, j + 1);
170
+ }
171
+ this.buf = "";
172
+ return b;
151
173
  }
152
174
  }
153
175
  this.sol = false;
@@ -170,23 +192,15 @@ export class StreamingMarkdownFilter {
170
192
  this.sol = true;
171
193
  return out;
172
194
  }
173
- if (c === "`") {
174
- out += this.buf.slice(0, i);
175
- this.buf = this.buf.slice(i + 1);
176
- this.inl = { type: "code", acc: "" };
177
- return out;
178
- }
179
195
  if (c === "!" && i + 1 < this.buf.length && this.buf[i + 1] === "[") {
180
196
  out += this.buf.slice(0, i);
181
197
  this.buf = this.buf.slice(i + 2);
182
198
  this.inl = { type: "image", acc: "" };
183
199
  return out;
184
200
  }
185
- if (c === "~" && i + 1 < this.buf.length && this.buf[i + 1] === "~") {
186
- out += this.buf.slice(0, i);
187
- this.buf = this.buf.slice(i + 2);
188
- this.inl = { type: "strike", acc: "" };
189
- return out;
201
+ if (c === "~") {
202
+ i++;
203
+ continue;
190
204
  }
191
205
  if (c === "*") {
192
206
  if (i + 2 < this.buf.length && this.buf[i + 1] === "*" && this.buf[i + 2] === "*") {
@@ -237,7 +251,6 @@ export class StreamingMarkdownFilter {
237
251
  else if (this.buf.endsWith("__")) hold = 2;
238
252
  else if (this.buf.endsWith("*")) hold = 1;
239
253
  else if (this.buf.endsWith("_")) hold = 1;
240
- else if (this.buf.endsWith("~")) hold = 1;
241
254
  else if (this.buf.endsWith("!")) hold = 1;
242
255
  }
243
256
  out += this.buf.slice(0, this.buf.length - hold);
@@ -252,41 +265,14 @@ export class StreamingMarkdownFilter {
252
265
  this.buf = "";
253
266
 
254
267
  switch (this.inl.type) {
255
- case "code": {
256
- const idx = this.inl.acc.indexOf("`");
257
- if (idx !== -1) {
258
- const content = this.inl.acc.slice(0, idx);
259
- this.buf = this.inl.acc.slice(idx + 1);
260
- this.inl = null;
261
- return content;
262
- }
263
- const nl = this.inl.acc.indexOf("\n");
264
- if (nl !== -1) {
265
- const r = "`" + this.inl.acc.slice(0, nl + 1);
266
- this.buf = this.inl.acc.slice(nl + 1);
267
- this.inl = null;
268
- this.sol = true;
269
- return r;
270
- }
271
- return "";
272
- }
273
- case "strike": {
274
- const idx = this.inl.acc.indexOf("~~");
275
- if (idx !== -1) {
276
- const content = this.inl.acc.slice(0, idx);
277
- this.buf = this.inl.acc.slice(idx + 2);
278
- this.inl = null;
279
- return content;
280
- }
281
- return "";
282
- }
283
268
  case "bold3": {
284
269
  const idx = this.inl.acc.indexOf("***");
285
270
  if (idx !== -1) {
286
271
  const content = this.inl.acc.slice(0, idx);
287
272
  this.buf = this.inl.acc.slice(idx + 3);
288
273
  this.inl = null;
289
- return content;
274
+ if (StreamingMarkdownFilter.containsCJK(content)) return content;
275
+ return `***${content}***`;
290
276
  }
291
277
  return "";
292
278
  }
@@ -296,7 +282,8 @@ export class StreamingMarkdownFilter {
296
282
  const content = this.inl.acc.slice(0, idx);
297
283
  this.buf = this.inl.acc.slice(idx + 3);
298
284
  this.inl = null;
299
- return content;
285
+ if (StreamingMarkdownFilter.containsCJK(content)) return content;
286
+ return `___${content}___`;
300
287
  }
301
288
  return "";
302
289
  }
@@ -317,7 +304,8 @@ export class StreamingMarkdownFilter {
317
304
  const content = this.inl.acc.slice(0, j);
318
305
  this.buf = this.inl.acc.slice(j + 1);
319
306
  this.inl = null;
320
- return content;
307
+ if (StreamingMarkdownFilter.containsCJK(content)) return content;
308
+ return `*${content}*`;
321
309
  }
322
310
  }
323
311
  return "";
@@ -339,7 +327,8 @@ export class StreamingMarkdownFilter {
339
327
  const content = this.inl.acc.slice(0, j);
340
328
  this.buf = this.inl.acc.slice(j + 1);
341
329
  this.inl = null;
342
- return content;
330
+ if (StreamingMarkdownFilter.containsCJK(content)) return content;
331
+ return `_${content}_`;
343
332
  }
344
333
  }
345
334
  return "";
@@ -362,30 +351,11 @@ export class StreamingMarkdownFilter {
362
351
  }
363
352
  return "";
364
353
  }
365
- case "table": {
366
- const nl = this.inl.acc.indexOf("\n");
367
- if (nl !== -1) {
368
- const line = this.inl.acc.slice(0, nl);
369
- this.buf = this.inl.acc.slice(nl + 1);
370
- this.inl = null;
371
- this.sol = true;
372
- const row = StreamingMarkdownFilter.extractTableRow(line);
373
- return row ? row + "\n" : "";
374
- }
375
- return "";
376
- }
377
354
  }
378
355
  return "";
379
356
  }
380
357
 
381
- /** Extract cell contents from a table row, or return "" for separator rows. */
382
- private static extractTableRow(line: string): string {
383
- if (/^[\s|:\-]+$/.test(line) && line.includes("-")) return "";
384
- const parts = line.split("|").map(c => c.trim());
385
- const cells = parts.slice(
386
- parts[0] === "" ? 1 : 0,
387
- parts[parts.length - 1] === "" ? parts.length - 1 : parts.length,
388
- );
389
- return cells.join("\t");
358
+ private static containsCJK(text: string): boolean {
359
+ return /[\u2E80-\u9FFF\uAC00-\uD7AF\uF900-\uFAFF]/.test(text);
390
360
  }
391
361
  }