@tencent-weixin/openclaw-weixin 2.1.4 → 2.1.5

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "openclaw-weixin",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
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.4",
3
+ "version": "2.1.5",
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
  }