diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d32a23cc590..8a8c13909470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai ### Fixes - **Source build portability:** keep tsdown configuration self-contained so builds do not depend on resolving the tsdown package from unrun's temporary module directory. +- **Agent tool-call decoding:** preserve surrogate-range numeric HTML entities as literal text while still decoding valid supplementary-plane values, preventing malformed model output from injecting lone UTF-16 surrogates into tool arguments. (#99564) Thanks @mikasa0818. - **Gateway event dispatch:** catch and log lazy subscriber setup and handler failures instead of leaking unhandled promise rejections. (#100401) Thanks @cxbAsDev. - **Diffs rendering:** render viewer and image output from one SSR preload, preserve language-pack highlighting through hydration, normalize language hints case-insensitively, skip identical before/after inputs with an explicit `changed` result, report truthful file-render and input errors, cache hash-pinned viewer runtimes, and prefer canonical file settings over stale aliases. (#100487) - **Remote browser reliability:** bound persistent Playwright tab enumeration by the existing remote CDP timeout budget and retire timed-out connection attempts so late completions cannot restore a stuck connection. (#80147, #58968) Thanks @HemantSudarshan and @KeaneYan. diff --git a/src/agents/embedded-agent-runner/tool-call-argument-decoding.test.ts b/src/agents/embedded-agent-runner/tool-call-argument-decoding.test.ts index 45176faab2ea..3597bf55e88e 100644 --- a/src/agents/embedded-agent-runner/tool-call-argument-decoding.test.ts +++ b/src/agents/embedded-agent-runner/tool-call-argument-decoding.test.ts @@ -11,11 +11,13 @@ describe("decodeHtmlEntitiesInObject", () => { expect( decodeHtmlEntitiesInObject({ query: "Rock & Roll A 'ok' 'hex'", + emoji: "ok 😀", args: ["--flag="value"", "<input>"], nested: { deep: "a & b" }, }), ).toEqual({ query: "Rock & Roll A 'ok' 'hex'", + emoji: "ok 😀", args: ['--flag="value"', ""], nested: { deep: "a & b" }, }); @@ -32,10 +34,10 @@ describe("decodeHtmlEntitiesInObject", () => { it("preserves invalid numeric HTML entities", () => { expect( decodeHtmlEntitiesInObject({ - query: "bad � and �", + query: "bad � and � and � and �", }), ).toEqual({ - query: "bad � and �", + query: "bad � and � and � and �", }); }); }); diff --git a/src/agents/embedded-agent-runner/tool-call-argument-decoding.ts b/src/agents/embedded-agent-runner/tool-call-argument-decoding.ts index b4d5defe0091..073fef293d45 100644 --- a/src/agents/embedded-agent-runner/tool-call-argument-decoding.ts +++ b/src/agents/embedded-agent-runner/tool-call-argument-decoding.ts @@ -17,7 +17,12 @@ const HTML_ENTITY_RE = /&(?:amp|lt|gt|quot|apos|#39|#x[0-9a-f]+|#\d+);/i; function decodeHtmlEntities(value: string): string { const decodeNumericEntity = (raw: string, radix: 10 | 16): string => { const codePoint = Number.parseInt(raw, radix); - return Number.isFinite(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff + const isValidCodePoint = + Number.isInteger(codePoint) && + codePoint >= 0 && + codePoint <= 0x10ffff && + (codePoint < 0xd800 || codePoint > 0xdfff); + return isValidCodePoint ? String.fromCodePoint(codePoint) : `&#${radix === 16 ? "x" : ""}${raw};`; };