Skip to content

fix(export): prevent broken emoji in HTML tool call previews#104054

Merged
hxy91819 merged 1 commit into
openclaw:mainfrom
zhangguiping-xydt:fix/problem-html-tool-preview-emoji
Jul 19, 2026
Merged

fix(export): prevent broken emoji in HTML tool call previews#104054
hxy91819 merged 1 commit into
openclaw:mainfrom
zhangguiping-xydt:fix/problem-html-tool-preview-emoji

Conversation

@zhangguiping-xydt

@zhangguiping-xydt zhangguiping-xydt commented Jul 11, 2026

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 exporting a session to HTML could see a broken replacement glyph in compact tool-call previews when a bash command or serialized tool argument was truncated through an emoji.

The corrupted preview was written into the standalone HTML artifact, so it remained visible when the export was saved or shared.

Why This Change Was Made

The standalone viewer truncated compact sidebar strings at raw UTF-16 code-unit boundaries. The change uses one surrogate-safe helper for the 50-code-unit assistant bash preview, the 40-code-unit generic argument preview, and the shared sidebar truncation path used by persisted bashExecution records. It preserves the existing limits and ellipsis behavior while dropping a boundary surrogate half instead of emitting invalid text.

This is a root-cause, display-layer fix. It does not alter the stored transcript, embedded session data, full tool-call rendering, model input, schema, configuration, or wire format.

User Impact

Exported HTML transcripts now show stable compact tool labels when long commands or arguments contain emoji at a truncation boundary. Existing ASCII previews and their length limits remain unchanged.

Evidence

After resolving the current-main conflict, the complete export template test file passes:

Test Files  1 passed (1)
Tests       17 passed (17)
[test] passed 1 Vitest shard

Fresh end-to-end proof used the built production /export-session command handler with an isolated canonical SQLite session store and five transcript entries. It wrote a 362,241-byte standalone HTML file inside the agent workspace, opened it in Chromium, and asserted the rendered sidebar labels:

seeded_transcript_entries=5
✅ Session exported!
📊 Entries: 5
result: {
  'actual': [
    '[bash: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...]',
    '[custom: {"value":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb...]',
    '[bash]: ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc...'
  ],
  'replacementCharacterPresent': False
}
Browser closed

A 764,811-byte full-page screenshot was captured during the same browser run. Additional fresh checks passed:

  • node scripts/run-oxlint.mjs on the two changed files
  • git diff --check on the two changed files
  • pnpm build, including the export HTML asset copy step

@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 19, 2026, 4:47 AM ET / 08:47 UTC.

Summary
The branch adds surrogate-safe truncation for compact bash, generic tool-argument, and persisted bash-execution labels in exported HTML, plus emoji-boundary regression tests.

PR surface: Source +5, Tests +92. Total +97 across 2 files.

Reproducibility: yes. from source inspection: the production export template slices preview strings at UTF-16 code-unit boundaries, so an emoji placed across the boundary leaves an unpaired surrogate; the reported production export and Chromium proof show the corrected path.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/auto-reply/reply/export-html/template.js. 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:

  • [P2] Let the existing exact-head automerge flow revalidate required checks and the real merge result against current main.

Risk before merge

  • [P1] The branch is behind current main; merge automation must continue to validate the exact reviewed head and actual merge result rather than rewriting the contributor branch solely for base drift.

Maintainer options:

  1. Decide the mitigation before merge
    Merge the focused local canonical-equivalent helper and regression coverage through the exact-head automerge gates, preserving existing preview limits and ellipsis behavior.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] No repair lane is needed: the patch has no actionable defect, and the remaining action is the existing member-sponsored exact-head automerge gate.

Security
Cleared: The diff is confined to local HTML display truncation and regression tests; it adds no dependencies, permissions, secrets, build hooks, publishing behavior, or external code execution.

Review details

Best possible solution:

Merge the focused local canonical-equivalent helper and regression coverage through the exact-head automerge gates, preserving existing preview limits and ellipsis behavior.

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

Yes from source inspection: the production export template slices preview strings at UTF-16 code-unit boundaries, so an emoji placed across the boundary leaves an unpaired surrogate; the reported production export and Chromium proof show the corrected path.

Is this the best way to solve the issue?

Yes. A small local helper that matches the canonical UTF-16 boundary algorithm is the narrowest maintainable fix because the standalone browser asset cannot directly import the TypeScript helper.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Sufficient (live_output): The PR supplies after-fix output from the production export command and Chromium-rendered sidebar labels with no replacement character; redact any private workspace or endpoint details in future evidence.
  • remove proof: 📸 screenshot: Current real behavior proof evidence kind is live_output.

Label justifications:

  • P2: This fixes bounded user-visible corruption in exported HTML previews without changing stored data, configuration, or runtime availability.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Sufficient (live_output): The PR supplies after-fix output from the production export command and Chromium-rendered sidebar labels with no replacement character; redact any private workspace or endpoint details in future evidence.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR supplies after-fix output from the production export command and Chromium-rendered sidebar labels with no replacement character; redact any private workspace or endpoint details in future evidence.
Evidence reviewed

PR surface:

Source +5, Tests +92. Total +97 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 25 20 +5
Tests 1 92 0 +92
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 117 20 +97

What I checked:

  • Current defect and production boundary: The current export renderer’s compact tool-preview and shared sidebar paths use raw UTF-16 slicing, while the export-session command embeds this standalone template into the generated HTML; an emoji straddling a fixed boundary can therefore produce a lone surrogate in a saved export. (src/auto-reply/reply/export-html/template.js:666, f50293c9e73b)
  • Canonical contract and proposed implementation: The repository UTF-16 helper backs up one code unit only when a high surrogate would be separated from its following low surrogate. The PR reproduces that algorithm locally because the standalone browser template cannot import the TypeScript package helper. (packages/normalization-core/src/utf16-slice.ts:43, f50293c9e73b)
  • Complete affected-surface coverage: The patch applies the same safe truncation rule to bash previews, generic serialized arguments, and the shared sidebar truncation path, preserving their existing numeric limits and ellipsis conditions. (src/auto-reply/reply/export-html/template.js:643, 4b72ae36324b)
  • Regression coverage: The added export-template test places emoji at the 50-, 40-, and 100-code-unit cut boundaries and asserts the rendered labels do not contain a replacement character. (src/auto-reply/reply/export-html/template.security.test.ts:801, 4b72ae36324b)
  • Real behavior proof and maintainer intent: The PR body records a production export-session run rendered in Chromium with no replacement characters, and a repository member repeatedly requested exact-head automerge/approval for this branch; the item is mergeable and only behind current main. (src/auto-reply/reply/commands-export-session.ts:123, 4b72ae36324b)
  • Feature provenance: History recorded in the prior exact-head review traces the bundled export-session HTML renderer to the original renderer introduction and subsequent security hardening on the same template surface. (src/auto-reply/reply/export-html/template.js:1, f70b3a2e6878)

Likely related people:

  • boris721: Introduced the bundled export-session HTML renderer that established the production template and command boundary affected here. (role: introduced behavior; confidence: high; commits: f70b3a2e6878; files: src/auto-reply/reply/export-html/template.js, src/auto-reply/reply/commands-export-session.ts)
  • steipete: Authored later standalone export-renderer hardening and the renderer-bundling refactor history on this same template path. (role: recent rendering and security contributor; confidence: high; commits: f8524ec77a39, e578521ef493, f70b3a2e6878; files: src/auto-reply/reply/export-html/template.js)
  • obviyus: Recently changed and reviewed image-rendering behavior in the same standalone export template. (role: recent adjacent contributor; confidence: medium; commits: 4bf902de5851, d25b493c7f79; files: src/auto-reply/reply/export-html/template.js)
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 (11 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-18T22:15:37.092Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-18T23:59:48.793Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T01:02:00.460Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T02:51:18.808Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T04:13:51.130Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T05:20:53.705Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T06:19:03.502Z sha 4b72ae3 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-19T07:50:24.700Z sha 4b72ae3 :: needs maintainer review before merge. :: none

@knoal

knoal commented Jul 12, 2026

Copy link
Copy Markdown

A/B verified locally against base SHA. Ran vitest with the PR's test file against the PR's fix (B) and against the base's fix (A).

Result: CLEAN A/B

A (PR test + base fix): FAIL - 1 test failed
B (PR test + PR fix):   PASS

The new test truncates tool previews without splitting emoji fails on base (the truncation cuts emoji grapheme clusters in half), passes with the fix. Failing-first signature is correct. Looks ready to merge.

@zhangguiping-xydt
zhangguiping-xydt force-pushed the fix/problem-html-tool-preview-emoji branch from d7205d8 to 4b72ae3 Compare July 16, 2026 18:29
@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

@clawsweeper

clawsweeper Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper automerge is enabled.

  • Head: 4b72ae36324b
  • Label: clawsweeper:automerge (pause labels cleared)
  • Action: exact-head review queued (workflow sweep.yml, event repository_dispatch).
  • Flow: review this head, repair/rebase only if needed, then re-review the exact repaired head before merge.

Draft PRs stay fix-only until GitHub marks them ready for review. Pause with /clawsweeper stop.

Automerge progress:

  • 2026-07-18 23:56:15 UTC review queued 4b72ae36324b (queued)
  • 2026-07-19 00:58:45 UTC review queued 4b72ae36324b (queued)
  • 2026-07-19 00:56:37 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 23:53:55 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 22:10:31 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 21:22:08 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 14:14:23 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 11:00:59 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-18 00:25:19 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-17 13:28:47 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-17 10:34:17 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-19 06:15:52 UTC review queued 4b72ae36324b (queued)
  • 2026-07-19 08:51:01 UTC review passed 4b72ae36324b (- [P2] No repair lane is needed: the patch has no actionable defect, and the re...)
  • 2026-07-19 08:41:45 UTC review queued 4b72ae36324b (queued)
  • 2026-07-19 06:13:19 UTC review result reused 4b72ae36324b (complete)
  • 2026-07-19 12:52:12 UTC review queued 4b72ae36324b (queued)

Re-review progress:

@clawsweeper clawsweeper Bot added the clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge label Jul 17, 2026
@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

Retry the exact current head 4b72ae3 after ClawSweeper main merged openclaw/clawsweeper#670, #671, and #672. Keep the existing fail-closed validation boundaries and use the production automerge path.

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

Retry the exact current head 4b72ae3 after openclaw/clawsweeper#679 merged. Use the production direct-behind path, preserve exact-head/check/review gates, and do not rewrite the contributor branch solely for base drift.

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper re-review

Refresh the exact-head verdict after openclaw/clawsweeper#679 landed. Automerge is already enabled; preserve the current head and let the trusted exact-head verdict resume the production direct-behind path.

@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. clawsweeper:human-review Needs maintainer review before ClawSweeper can continue and removed 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 18, 2026
@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

🦞✅
ClawSweeper is pausing this repair loop for human review.

Source: clawsweeper[bot]
Reason: - [P2] No repair lane is needed: the patch has no actionable finding and the remaining step is the already sponsored exact-head automerge gate.; Cleared: The diff changes only deterministic display-string truncation and tests; it adds no dependency, workflow, permission, secret, network, or package-execution surface. (sha=4b72ae36324b21eba8e37b6439c7815b32a59a4c)

Why human review is needed:
This item has security-sensitive risk. ClawSweeper is pausing instead of making an autonomous change that could affect trust, credentials, permissions, or exposure.

What the maintainer can do as a next step:
If the maintainer accepts the current risk and wants ClawSweeper to continue merge gates, comment @clawsweeper approve. If the security-sensitive detail still needs changes, describe the safe path or push the fix, then comment @clawsweeper automerge. If the risk should not be automated, keep the PR paused for manual review or comment @clawsweeper stop.

I added clawsweeper:human-review and left the final call with a maintainer.

@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

Resume the exact current head after openclaw/clawsweeper#680 landed.

@clawsweeper clawsweeper Bot added rating: 🦀 challenger crab Exceptional PR readiness: strong proof, clean patch, and convincing validation. status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. clawsweeper:human-review Needs maintainer review before ClawSweeper can continue and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jul 19, 2026
@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper approve

@clawsweeper clawsweeper Bot added clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed clawsweeper:human-review Needs maintainer review before ClawSweeper can continue rating: 🦀 challenger crab Exceptional PR readiness: strong proof, clean patch, and convincing validation. status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed labels Jul 19, 2026
@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

@clawsweeper clawsweeper Bot added status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed and removed clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. labels Jul 19, 2026
@clawsweeper clawsweeper Bot added clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed and removed clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed labels Jul 19, 2026
@hxy91819

Copy link
Copy Markdown
Member

@clawsweeper automerge

Resume the exact current head after openclaw/clawsweeper#702 merged. If the protected merge gate reports the head behind base, route it through the existing cloud rebase repair lane; preserve all exact-head review, CAS, immutable-ledger, and merge safety gates.

@clawsweeper clawsweeper Bot removed the clawsweeper:merge-ready ClawSweeper found the PR merge-ready but a human gate is still closed label Jul 19, 2026
@hxy91819
hxy91819 merged commit 7ea4e67 into openclaw:main Jul 19, 2026
443 of 474 checks passed
@hxy91819

Copy link
Copy Markdown
Member

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge 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: S status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants