fix(config): use truncateUtf16Safe for allowed-values hint text (#102512)

* fix(config): use truncateUtf16Safe for allowed-values hint text

Replace naive .slice(0, N) with truncateUtf16Safe() to prevent
surrogate pair splitting in config validation hint messages
shown to users.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(config): prove UTF-16 allowed-value hint boundary

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
lsr911
2026-07-09 16:28:25 +08:00
committed by GitHub
parent b23fdcfac9
commit 720aeb1547
2 changed files with 14 additions and 1 deletions

View File

@@ -23,6 +23,17 @@ describe("summarizeAllowedValues", () => {
});
});
it("counts the omitted UTF-16 units after preserving a surrogate pair", () => {
const prefix = "a".repeat(159);
const value = `${prefix}😀tail`;
expect(summarizeAllowedValues([value])).toStrictEqual({
formatted: `"${prefix}... (+6 chars)"`,
hiddenCount: 0,
values: [value],
});
});
it("returns empty label for undefined allowed value", () => {
const summary = summarizeAllowedValues([undefined]);
expect(summary).toStrictEqual({

View File

@@ -1,5 +1,6 @@
// Defines allowed-value metadata for config validation and docs.
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
const MAX_ALLOWED_VALUES_HINT = 12;
const MAX_ALLOWED_VALUE_CHARS = 160;
@@ -14,7 +15,8 @@ function truncateHintText(text: string, limit: number): string {
if (text.length <= limit) {
return text;
}
return `${text.slice(0, limit)}... (+${text.length - limit} chars)`;
const truncated = truncateUtf16Safe(text, limit);
return `${truncated}... (+${text.length - truncated.length} chars)`;
}
function safeStringify(value: unknown): string {