fix(matrix): truncate reply context on code-point boundaries (#97471) · openclaw/openclaw@55d7b5b
ly-wang19
·
2026-06-29
·
via Recent Commits to openclaw:main
File tree
extensions/matrix/src/matrix/monitor
| Original file line number | Diff line number | Diff line change |
|---|
@@ -39,6 +39,30 @@ describe("matrix reply context", () => {
|
39 | 39 | expect(result.endsWith("...")).toBe(true); |
40 | 40 | }); |
41 | 41 | |
| 42 | +it("truncates on a code-point boundary without orphaning a surrogate half", () => { |
| 43 | +// Body is 496 'a' + 😀 (U+1F600, a surrogate pair at UTF-16 indices 496-497) |
| 44 | +// + "bcd". Raw `.slice(0, 497)` would split the emoji and leave a lone high |
| 45 | +// surrogate (\uD83D) before the ellipsis. The fix must drop the half emoji. |
| 46 | +const body = `${"a".repeat(496)}😀bcd`; |
| 47 | +expect(body.length).toBe(501); |
| 48 | +const result = summarizeMatrixReplyEvent({ |
| 49 | +event_id: "$original", |
| 50 | +sender: "@alice:example.org", |
| 51 | +type: "m.room.message", |
| 52 | +origin_server_ts: Date.now(), |
| 53 | +content: { |
| 54 | +msgtype: "m.text", |
| 55 | + body, |
| 56 | +}, |
| 57 | +} as MatrixRawEvent); |
| 58 | +if (result === undefined) { |
| 59 | +throw new Error("expected truncated reply context"); |
| 60 | +} |
| 61 | +expect(result).toBe(`${"a".repeat(496)}...`); |
| 62 | +// No dangling high surrogate should survive the truncation. |
| 63 | +expect(result.includes("\uD83D")).toBe(false); |
| 64 | +}); |
| 65 | + |
42 | 66 | it("handles media-only reply events", () => { |
43 | 67 | expect( |
44 | 68 | summarizeMatrixReplyEvent({ |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | // Matrix plugin module implements reply context behavior. |
| 2 | +import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime"; |
2 | 3 | import type { MatrixClient } from "../sdk.js"; |
3 | 4 | import { summarizeMatrixMessageContextEvent, trimMatrixMaybeString } from "./context-summary.js"; |
4 | 5 | import type { MatrixRawEvent } from "./types.js"; |
@@ -16,7 +17,7 @@ function truncateReplyBody(value: string): string {
|
16 | 17 | if (value.length <= MAX_REPLY_BODY_LENGTH) { |
17 | 18 | return value; |
18 | 19 | } |
19 | | -return `${value.slice(0, MAX_REPLY_BODY_LENGTH - 3)}...`; |
| 20 | +return `${sliceUtf16Safe(value, 0, MAX_REPLY_BODY_LENGTH - 3)}...`; |
20 | 21 | } |
21 | 22 | |
22 | 23 | export function summarizeMatrixReplyEvent(event: MatrixRawEvent): string | undefined { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。