fix(qa-matrix): keep shared reply previews UTF-16 safe (#102656)

* fix(qa-matrix): keep reply body preview truncation UTF-16 safe

Replace `.slice(0, 200)` with `truncateUtf16Safe(replyBody, 200)` in
buildMatrixReplyArtifact to prevent surrogate pair corruption.

Ref. lsr911 pattern — mechanical substitution, no behavior change.

* test(qa-matrix): preserve reply preview semantics

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
huangjianxiong 2026-07-09 21:41:54 +08:00 committed by GitHub
parent f6b9901243
commit 0e626690cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 2 deletions

View file

@ -1,6 +1,9 @@
// Qa Matrix tests cover scenario runtime shared plugin behavior.
import { afterEach, describe, expect, it, vi } from "vitest";
import { resolveMatrixQaNoReplyWindowMs } from "./scenario-runtime-shared.js";
import {
buildMatrixReplyArtifact,
resolveMatrixQaNoReplyWindowMs,
} from "./scenario-runtime-shared.js";
describe("matrix scenario runtime shared", () => {
afterEach(() => {
@ -19,4 +22,18 @@ describe("matrix scenario runtime shared", () => {
expect(resolveMatrixQaNoReplyWindowMs(30_000)).toBe(8_000);
}
});
it("keeps reply previews UTF-16 safe without changing empty-body artifacts", () => {
const event = {
kind: "message" as const,
roomId: "!room:matrix-qa.test",
eventId: "$event",
sender: "@sut:matrix-qa.test",
type: "m.room.message",
};
const prefix = "a".repeat(199);
expect(buildMatrixReplyArtifact({ ...event, body: `${prefix}😀tail` }).bodyPreview).toBe(prefix);
expect(buildMatrixReplyArtifact({ ...event, body: " " }).bodyPreview).toBe("");
});
});

View file

@ -1,5 +1,6 @@
// Qa Matrix plugin module implements scenario runtime shared behavior.
import { randomUUID } from "node:crypto";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import { createMatrixQaClient, type MatrixQaRoomObserver } from "../../substrate/client.js";
import type { MatrixQaObservedEvent } from "../../substrate/events.js";
import type { MatrixQaFaultProxyObserver } from "../../substrate/fault-proxy.js";
@ -189,7 +190,7 @@ export function buildMatrixReplyArtifact(
): MatrixQaReplyArtifact {
const replyBody = event.body?.trim();
return {
bodyPreview: replyBody?.slice(0, 200),
bodyPreview: replyBody === undefined ? undefined : truncateUtf16Safe(replyBody, 200),
eventId: event.eventId,
mentions: event.mentions,
relatesTo: event.relatesTo,