mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-19 03:11:40 +00:00
fix(diagnostics-otel): preserve JSON Unicode boundaries (#103646)
* fix(diagnostics-otel): preserve JSON Unicode boundaries * test(diagnostics-otel): consolidate Unicode boundary coverage * docs(changelog): credit OTEL Unicode fix --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -49,7 +49,7 @@ Docs: https://docs.openclaw.ai
|
||||
- **Apple timeout recovery:** return promptly from shared operation deadlines and caller cancellation even when platform work ignores cancellation, while isolating late Gateway handshakes and cleaning up location and permission waiters. (#103066) Thanks @NianJiuZst.
|
||||
- **Claude CLI warm sessions:** preserve managed stdio continuity when Claude writes no native transcript, fall back to bounded OpenClaw history only when the exact live child disappears or changes, and keep stateless runs from persisting CLI bindings. (#96841) Thanks @bradreaves.
|
||||
- **CLI plugin listing:** skip state-migration runtime loading when no legacy inputs exist, reducing packaged cold-start memory while preserving migrations for legacy plugin indexes and configured session stores.
|
||||
- **Unicode-safe bounded text:** preserve complete UTF-16 surrogate pairs when shortening previews, prompts, diagnostics, labels, session keys, link metadata, and identity values across Control UI, CLI, Gateway, plugins, QA, memory, and Android surfaces. (#102625, #102626, #102627, #102656, #102816, #102823, #102833, #102877, #102949, #102963, #102969, #102988, #103010, #103034, #103210, #103341, #103487, #103543, #103580) Thanks @zhangguiping-xydt, @wings1029, @wangyan2026, @Pandah97, @MoerAI, @SunnyShu0925, @zhangqueping, @zw-xysk, @cxbAsDev, @lzyyzznl, @coder-master-0915, @LeonidasLux, @mushuiyu886, @ly85206559, @Simon-XYDT, and @lsr911.
|
||||
- **Unicode-safe bounded text:** preserve complete UTF-16 surrogate pairs when shortening previews, prompts, diagnostics, labels, session keys, link metadata, and identity values across Control UI, CLI, Gateway, plugins, QA, memory, and Android surfaces. (#102625, #102626, #102627, #102656, #102816, #102823, #102833, #102877, #102949, #102963, #102969, #102988, #103010, #103034, #103210, #103341, #103487, #103543, #103580, #103646) Thanks @zhangguiping-xydt, @wings1029, @wangyan2026, @Pandah97, @MoerAI, @SunnyShu0925, @zhangqueping, @zw-xysk, @cxbAsDev, @lzyyzznl, @coder-master-0915, @LeonidasLux, @mushuiyu886, @ly85206559, @Simon-XYDT, and @lsr911.
|
||||
- **CLI model tables:** sanitize, truncate, and pad model-list cells by rendered terminal width so emoji, CJK, and other wide graphemes keep columns aligned. (#102819) Thanks @Kevin23-design and @vincentkoc.
|
||||
- **Skills prompt compaction:** preserve every included skill identity before using the remaining prompt budget for shortened, UTF-16-safe descriptions, retaining trigger guidance without exceeding the hard limit. (#88426) Thanks @abel-zer0.
|
||||
- **Channel Markdown code tables:** size columns by rendered display width so CJK, emoji, and mixed-width cells stay aligned across shared Telegram and Discord output. (#55596, #55512) Thanks @sparkyrider.
|
||||
|
||||
@@ -5321,6 +5321,9 @@ describe("diagnostics-otel service", () => {
|
||||
});
|
||||
await service.start(ctx);
|
||||
|
||||
// The 8,192-character candidate budget leaves an 8,178-character text prefix;
|
||||
// place a surrogate pair across that boundary so serialized JSON must stay valid.
|
||||
const surrogateBoundaryPrefix = "x".repeat(8177);
|
||||
emitTrustedModelCallCompletedWithContent(
|
||||
{
|
||||
runId: "run-1",
|
||||
@@ -5333,7 +5336,9 @@ describe("diagnostics-otel service", () => {
|
||||
inputMessages: [
|
||||
{
|
||||
role: "user",
|
||||
content: `single-message-${"x".repeat(MAX_TEST_OTEL_CONTENT_ATTRIBUTE_CHARS)}`,
|
||||
content: `${surrogateBoundaryPrefix}🚀${"y".repeat(
|
||||
MAX_TEST_OTEL_CONTENT_ATTRIBUTE_CHARS,
|
||||
)}`,
|
||||
},
|
||||
],
|
||||
toolDefinitions: [
|
||||
@@ -5364,13 +5369,14 @@ describe("diagnostics-otel service", () => {
|
||||
const toolDefinitions = stringAttribute(attrs, "gen_ai.tool.definitions");
|
||||
expect(genAiInput.length).toBeLessThanOrEqual(MAX_TEST_OTEL_CONTENT_ATTRIBUTE_CHARS);
|
||||
expect(toolDefinitions.length).toBeLessThanOrEqual(MAX_TEST_OTEL_CONTENT_ATTRIBUTE_CHARS);
|
||||
expect(genAiInput).not.toContain("\\ud83d");
|
||||
expect(JSON.parse(genAiInput)).toEqual([
|
||||
{
|
||||
role: "user",
|
||||
parts: [
|
||||
{
|
||||
type: "text",
|
||||
content: expect.stringContaining("single-message-"),
|
||||
content: `${surrogateBoundaryPrefix}...(truncated)`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -935,7 +935,7 @@ function truncateJsonTextForOtelAttribute(value: string, maxChars: number): stri
|
||||
}
|
||||
const suffixBudget = Math.min(TRUNCATED_JSON_TEXT_SUFFIX.length, maxChars);
|
||||
const prefixBudget = Math.max(0, maxChars - suffixBudget);
|
||||
return `${redacted.slice(0, prefixBudget)}${TRUNCATED_JSON_TEXT_SUFFIX.slice(
|
||||
return `${truncateUtf16Safe(redacted, prefixBudget)}${TRUNCATED_JSON_TEXT_SUFFIX.slice(
|
||||
TRUNCATED_JSON_TEXT_SUFFIX.length - suffixBudget,
|
||||
)}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user