fix(qqbot): use UTF-16-safe truncation for messaging outbound previews#101410
fix(qqbot): use UTF-16-safe truncation for messaging outbound previews#101410wangmiao0668000666 wants to merge 3 commits into
Conversation
|
Codex review: needs changes before merge. Reviewed July 7, 2026, 4:48 AM ET / 08:48 UTC. Summary PR surface: Source +2, Tests +91. Total +93 across 4 files. Reproducibility: yes. Current main uses raw Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Fix the test string construction lint error, keep the narrow helper substitution, and let the related QQBot UTF-16 cleanup PRs cover their separate surfaces. Do we have a high-confidence way to reproduce the issue? Yes. Current main uses raw Is this the best way to solve the issue? Yes. Reusing the existing plugin SDK UTF-16-safe helper is the narrow maintainable fix for these preview/error caps; the branch needs the added test lint error fixed before it is merge-ready. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 24330a82b44a. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +2, Tests +91. Total +93 across 4 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (1 earlier review cycle)
|
|
@clawsweeper re-review PR 1a now has focused runtime proof + cap-precise boundary tests. Two commits since last review:
Total diff for this PR remains small (1 prod import swap already shipped earlier; runtime proof is +54 LoC in the existing test file, no new test files, no committed repro script). Pre-flight checks (all green locally on Node 22.22.0):
Ready for re-review. Thanks. |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Superseded by the canonical QQBot bounded-preview cleanup in PR #101516, landed as ccbd9eb. That replacement includes this messaging scope, the gateway/API sibling sites, focused boundary tests, and preserves @wangmiao0668000666 as co-author. Thanks for identifying and proving the UTF-16 boundary issue. |
Summary
.slice(0, N)so emoji and CJK surrogate pairs in sent-chunk previews and media-path error messages are not split mid-pair.truncateUtf16Safe(text, N)helper fromopenclaw/plugin-sdk/text-utility-runtime.outbound.tssites (those will follow in PR 1b).Linked context
engine/tools/remind-logic.ts(llagy009 #96575) all use the sametruncateUtf16Safehelper. QQBot outbound-deliver / outbound-media-send is the new addition.Real behavior proof (required for external PRs)
Sent text chunk ...,Sent text-only chunk ...,Extracted HTTP image from markdown,Extracted bare image URL,Forwarded tool media,Formatted HTTP image,Updated image with size,Sent image via sendPhoto,Collected media URL) and outbound-media-send error returns (Failed to download image,Unsupported image source,Failed to download audio/video/file,fallback: download also failed) now truncate on a UTF-16 code-unit boundary instead of splitting emoji/CJK surrogate pairs.node scripts/run-vitest.mjs extensions/qqbot/src/engine/messaging/outbound-deliver.test.ts extensions/qqbot/src/engine/messaging/outbound-media-send.test.ts --run.outbound-media-send.ts:460.outbound-media-sendruntime test):.slice(0, 80)on the same input, the resulting user-facingFailed to download image:error message contains a lone 0xD83D HIGH surrogate that no JSON encoder, terminal renderer, or emoji parser can round-trip. Replacing withtruncateUtf16Safekeeps the surrogate pair atomic: the trailing 🎉 is dropped at the cap boundary instead of being half-emptied into the user-visible error string.Tests and validation
node scripts/run-vitest.mjs extensions/qqbot/src/engine/messaging/outbound-deliver.test.ts extensions/qqbot/src/engine/messaging/outbound-media-send.test.ts --runit()blocks across the two existing test files).node scripts/run-oxlint-shards.mjs --threads=4clean.pnpm tsgo:extensionsclean.Risk checklist
outbound-deliver.tserror-return and debugLog paths insendText/parseAndSendMediaTags/sendPlainReply;outbound-media-send.tserror-return paths insendPhoto/sendVoice/sendVideoMsg/sendDocument..slice(0, N)fortruncateUtf16Safe(text, N); the helper preserves identical behavior for ASCII, CJK (BMP), and all inputs without surrogate pairs, and only ever trims at most 1 code unit when a surrogate pair straddles the cap. Inline tests assert both the cap and the absence of lone surrogates. The companionengine/utils/log.tssanitizeDebugLogValuesite, theengine/tools/remind-logic.tssite, and theoutbound.tsbarrel re-exports are out of scope and will follow in PR 1b / PR 2 / PR 3.Current review state