Skip to content

fix(chat): tool titles corrupt boundary emoji in long inputs#104464

Merged
steipete merged 3 commits into
openclaw:mainfrom
zhangguiping-xydt:fix/problem-tool-titles-utf16
Jul 11, 2026
Merged

fix(chat): tool titles corrupt boundary emoji in long inputs#104464
steipete merged 3 commits into
openclaw:mainfrom
zhangguiping-xydt:fix/problem-tool-titles-utf16

Conversation

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor
Additional instructions

MUST: Keep Allow edits from maintainers enabled for this PR so maintainers
can help update the branch when needed.

What Problem This Solves

Fixes an issue where users viewing a long command or generic tool call in Control UI could send corrupted text to the AI tool-title generator when an emoji crossed the existing 2,000-unit input limit.

Why This Change Was Made

Control UI now applies OpenClaw's canonical UTF-16-safe truncation to command text, raw string args, and serialized object args before hashing and scheduling chat.toolTitles. The Gateway independently applies the same boundary after full-input secret redaction, protecting other RPC clients before cache keys and utility-model prompts are built.

The security order remains unchanged: Gateway redacts the complete schema-bounded input first, then truncates. Existing 2,000-unit budgets, protocol limits, debounce/batching, cache scope, utility routing, and title output behavior remain unchanged. A fresh open-PR scan found no PR covering this UI-to-Gateway tool-title path.

User Impact

Model-generated purpose titles for long tool calls no longer receive a broken replacement glyph at an emoji boundary. Complete text within the current budget, secret redaction, cached titles, deterministic fallback labels, and all opt-in behavior stay the same.

Evidence

  • Before the fix, both owners failed at the exact boundary:

    Control UI: 1 failed | 16 passed (17)
    Gateway:    4 failed | 44 passed (48)
    Received suffix: ...�
    Boundary code unit: U+D83D
    
  • After the fix, a real isolated OpenClaw Gateway ran with tool titles enabled and a deterministic local utility-model endpoint. The proof sent one unsafe direct Gateway request and one separate request through the production Control UI debounce path:

    gatewayReady: true
    directGatewayRequestCompleted: true
    productionUiDebounceCompleted: true
    uiRequestInputUtf16Units: 1999
    uiRequestLoneSurrogate: false
    directUtilityPromptInputUtf16Units: 1999
    directUtilityPromptLoneSurrogate: false
    uiUtilityPromptInputUtf16Units: 1999
    uiUtilityPromptLoneSurrogate: false
    directSafePrefixPreserved: true
    uiSafePrefixPreserved: true
    renderedTitle: Checked UI boundary
    providerRequestCount: 2
    

    This exercises Control UI request eligibility and debounce, the real chat.toolTitles RPC handler, Gateway redaction/normalization/cache routing, utility-model HTTP requests, and the rendered title lookup.

  • Full affected test files:

    Control UI: 1 file passed, 17 tests passed
    Gateway:    4 files passed, 48 tests passed
    
  • pnpm ui:build passed with 1,097 modules transformed.

  • Targeted formatting passed for all four changed files.

  • Changed-surface checks passed, including core/core-test type checks, lint, dependency guards, database-first guard, runtime sidecar checks, and zero runtime import cycles.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime size: S labels Jul 11, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 1:38 PM ET / 17:38 UTC.

Summary
The PR replaces raw 2,000-code-unit slicing with truncateUtf16Safe for Control UI command/generic tool-title inputs and Gateway-normalized inputs, adding boundary regression tests.

PR surface: Source +1, Tests +32. Total +33 across 4 files.

Reproducibility: yes. Current main deterministically bisects the supplied emoji with raw .slice(0, 2000), and the regression cases cover command text, raw string arguments, serialized object arguments, and the Gateway utility-model prompt.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/chat-tool-titles.test.ts, serialized state: ui/src/pages/chat/tool-titles.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] The exact head currently has one failing compact CI test shard; logs were unavailable while the workflow was still running, so merge should wait for attribution or a green rerun even though no patch-related failure is evident.

Maintainer options:

  1. Decide the mitigation before merge
    Keep the existing 2,000-code-unit contract and land this shared-helper substitution at both the browser producer and Gateway trust boundary, retaining full redaction before Gateway truncation and the focused boundary tests.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No automated repair is identified; keep the active assigned PR open for normal maintainer landing after the remaining CI shard is green or proven unrelated.

Security
Cleared: The diff preserves complete-input redaction before truncation and adds no dependency, permission, credential, artifact-download, package-resolution, or code-execution surface.

Review details

Best possible solution:

Keep the existing 2,000-code-unit contract and land this shared-helper substitution at both the browser producer and Gateway trust boundary, retaining full redaction before Gateway truncation and the focused boundary tests.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main deterministically bisects the supplied emoji with raw .slice(0, 2000), and the regression cases cover command text, raw string arguments, serialized object arguments, and the Gateway utility-model prompt.

Is this the best way to solve the issue?

Yes. Reusing the repository's canonical browser-safe helper at the two independent input owners is the narrowest maintainable fix and avoids new APIs, fallback paths, configuration, or duplicate truncation logic.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against de8cfd2bf211.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR records an after-fix real isolated Gateway run and a separate production Control UI debounce request, showing both paths deliver well-formed 1,999-unit prefixes and render the generated title; later commits changed tests only.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR records an after-fix real isolated Gateway run and a separate production Control UI debounce request, showing both paths deliver well-formed 1,999-unit prefixes and render the generated title; later commits changed tests only.

Label justifications:

  • P2: The PR fixes a real but limited Unicode corruption in optional generated tool titles, while core chat and deterministic fallback labels remain functional.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR records an after-fix real isolated Gateway run and a separate production Control UI debounce request, showing both paths deliver well-formed 1,999-unit prefixes and render the generated title; later commits changed tests only.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR records an after-fix real isolated Gateway run and a separate production Control UI debounce request, showing both paths deliver well-formed 1,999-unit prefixes and render the generated title; later commits changed tests only.
Evidence reviewed

PR surface:

Source +1, Tests +32. Total +33 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 5 4 +1
Tests 2 32 0 +32
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 37 4 +33

What I checked:

  • Current-main reproduction: Current main uses raw .slice(0, 2000) in all four affected truncation paths, so a 1,999-unit ASCII prefix followed by an emoji returns a dangling high surrogate. (ui/src/pages/chat/tool-titles.ts:71, de8cfd2bf211)
  • Gateway security order: The exact PR head applies safe truncation only after redactToolPayloadText processes the complete schema-bounded input, preserving the existing secret-egress invariant before cache-key and prompt construction. (src/gateway/chat-tool-titles.ts:77, eec439970bff)
  • Canonical helper contract: The shared helper retains the existing UTF-16 code-unit limit and backs off one unit only when the truncation edge splits a valid surrogate pair. (packages/normalization-core/src/utf16-slice.ts:43, de8cfd2bf211)
  • Whole changed surface: Compared with the provided current-main SHA, the branch changes only the four declared tool-title implementation and regression-test files; it does not alter protocol, config, routing, cache schema, dependencies, or defaults. (src/gateway/chat-tool-titles.test.ts:136, eec439970bff)
  • Proof continuity: The two commits after the original implementation modify only the UI regression test, so the PR body's real Gateway and production UI debounce proof still covers the current production code. (ui/src/pages/chat/tool-titles.test.ts:53, eec439970bff)
  • Feature provenance: Current-main blame and history tie both tool-title modules to commit fe261b0, with Peter Steinberger as the feature author; he also refined the current PR's tests and is assigned to the review. (src/gateway/chat-tool-titles.ts:1, fe261b0f59aa)

Likely related people:

  • steipete: He introduced the current tool-title UI and Gateway modules in merged commit fe261b0, authored both current-head test refinements, is assigned to this PR, and therefore has the strongest history-based context for landing it. (role: feature introducer, recent reviewer, and likely follow-up owner; confidence: high; commits: fe261b0f59aa, 1a46690b9517, eec439970bff; files: src/gateway/chat-tool-titles.ts, src/gateway/chat-tool-titles.test.ts, ui/src/pages/chat/tool-titles.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-11T12:31:06.065Z sha ac91d51 :: needs maintainer review before merge. :: none

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(chat): tool titles corrupt boundary emoji in long inputs This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 11, 2026
@steipete

Copy link
Copy Markdown
Contributor

Land-ready maintainer proof for exact head eec439970bff5e5c550ec5c4d9d1f955c481288d:

  • Refactor review: Control UI and Gateway now use the canonical browser-safe UTF-16 truncation primitive at their respective ownership boundaries. Gateway still redacts the complete input before truncation, preserving the secret-boundary invariant.
  • Test cleanup: replaced the bespoke surrogate scanner with table-driven exact-prefix assertions for commands, raw string args, and serialized object args (23 net test lines removed).
  • Sanitized AWS Crabbox: cbx_f52a5050f62e, run run_3e1f3b7b8b7a — 48 Gateway tests and 19 Control UI tests passed.
  • Targeted oxlint and oxfmt --check passed.
  • Independent autoreview: clean, confidence 0.98.
  • Exact-head hosted CI: run 29161603674, attempt 2 green after retrying an unrelated timing-sensitive tooling shard.
  • Native OPENCLAW_TESTBOX=1 scripts/pr prepare-run 104464 passed with exact-head hosted evidence.

Known proof gaps: none for the touched behavior.

@steipete
steipete merged commit 04037e3 into openclaw:main Jul 11, 2026
183 of 191 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 12, 2026
…w#104464)

* fix(chat): tool titles corrupt boundary emoji in long inputs

* test(chat): simplify UTF-16 title boundary coverage

* test(chat): satisfy title boundary lint

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui gateway Gateway runtime P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants