fix(ui): keep event payload previews UTF-16 safe (#102625)

* fix(ui): keep event payload previews UTF-16 safe

* chore: use shared utf16 truncator in presenter

* fix(ui): use canonical utf16 truncator import

* refactor(ui): reuse canonical text truncation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
xingzhou 2026-07-09 22:01:17 +08:00 committed by GitHub
parent 3ba72f624a
commit 763ef215e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 2 deletions

View file

@ -0,0 +1,39 @@
/* @vitest-environment jsdom */
import { render } from "lit";
import { describe, expect, it } from "vitest";
import { formatEventPayload } from "../../lib/presenter.ts";
import { renderOverviewEventLog } from "./event-log.ts";
function createBoundaryPayload() {
const emptyPayload = formatEventPayload({ message: "" });
const valueStart = emptyPayload.indexOf('""') + 1;
return { message: `${"a".repeat(119 - valueStart)}🙂tail` };
}
describe("renderOverviewEventLog", () => {
it("keeps payload previews UTF-16 safe at the truncation boundary", () => {
const payload = createBoundaryPayload();
const formatted = formatEventPayload(payload);
const oldPreview = formatted.slice(0, 120);
expect(oldPreview.charCodeAt(oldPreview.length - 1)).toBe(0xd83d);
const container = document.createElement("div");
render(
renderOverviewEventLog({
events: [
{
ts: 1,
event: "agent.message",
payload,
},
],
}),
container,
);
const preview = container.querySelector(".ov-event-log-payload")?.textContent ?? "";
expect(preview).toBe(formatted.slice(0, 119));
expect(preview.charCodeAt(preview.length - 1)).not.toBe(0xd83d);
});
});

View file

@ -3,7 +3,7 @@ import { html, nothing } from "lit";
import type { EventLogEntry } from "../../api/event-log.ts";
import { icons } from "../../components/icons.ts";
import { t } from "../../i18n/index.ts";
import { formatTimeMs } from "../../lib/format.ts";
import { formatTimeMs, truncateText } from "../../lib/format.ts";
import { formatEventPayload } from "../../lib/presenter.ts";
type OverviewEventLogProps = {
@ -32,7 +32,7 @@ export function renderOverviewEventLog(props: OverviewEventLogProps) {
<span class="ov-event-log-name">${entry.event}</span>
${entry.payload
? html`<span class="ov-event-log-payload muted"
>${formatEventPayload(entry.payload).slice(0, 120)}</span
>${truncateText(formatEventPayload(entry.payload), 120).text}</span
>`
: nothing}
</div>