mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 05:53:55 +00:00
fix(acp): use truncateUtf16Safe for event mapper error text truncation (#101535)
* fix(acp): use truncateUtf16Safe for event mapper error text truncation .slice(0, 100) on ACP event argument values can split surrogate pairs from emoji or CJK text, producing U+FFFD in error/warning notices shown to operators. Co-Authored-By: Claude <noreply@anthropic.com> * test(acp): cover UTF-16-safe tool titles * refactor(acp): keep event mapper import leaf-only --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/** Tests ACP tool-call location extraction limits. */
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { extractToolCallLocations } from "./event-mapper.js";
|
||||
import { extractToolCallLocations, formatToolTitle } from "./event-mapper.js";
|
||||
|
||||
describe("extractToolCallLocations", () => {
|
||||
it("enforces the global node visit cap across nested structures", () => {
|
||||
@@ -18,3 +18,13 @@ describe("extractToolCallLocations", () => {
|
||||
expect(locations).toEqual([{ path: "/tmp/file-0.txt" }, { path: "/tmp/file-1.txt" }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatToolTitle", () => {
|
||||
it("does not split surrogate pairs when truncating argument values", () => {
|
||||
const title = formatToolTitle("exec", {
|
||||
command: `${"x".repeat(99)}🚀tail`,
|
||||
});
|
||||
|
||||
expect(title).toBe(`exec: command: ${"x".repeat(99)}...`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
normalizeOptionalString,
|
||||
readStringValue,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
|
||||
|
||||
type GatewayAttachment = {
|
||||
type: string;
|
||||
@@ -309,7 +310,7 @@ export function formatToolTitle(
|
||||
}
|
||||
const parts = Object.entries(args).map(([key, value]) => {
|
||||
const raw = typeof value === "string" ? value : JSON.stringify(value);
|
||||
const safe = raw.length > 100 ? `${raw.slice(0, 100)}...` : raw;
|
||||
const safe = raw.length > 100 ? `${truncateUtf16Safe(raw, 100)}...` : raw;
|
||||
return `${key}: ${safe}`;
|
||||
});
|
||||
// Sanitize at the source so session updates and permission requests never
|
||||
|
||||
Reference in New Issue
Block a user