fix(tui): inject VS16 so text-default emoji render as color glyphs#13253
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a TUI-side normalization step to force emoji presentation for “text-default” emoji codepoints by injecting VS16 (U+FE0F), improving how LLM-emitted symbols render in terminals.
Changes:
- Introduces
ensureEmojiPresentation(text)to append VS16 for a curated set of text-default emoji codepoints. - Applies the normalization to markdown-rendered output by calling it at the start of
Mdparsing. - Adds unit tests covering pass-through, injection, idempotence, and a few special sequences.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| ui-tui/src/lib/emoji.ts | New normalization utility that injects VS16 for selected codepoints. |
| ui-tui/src/components/markdown.tsx | Applies normalization to markdown-rendered text before line parsing. |
| ui-tui/src/tests/emoji.test.ts | Adds test coverage for the new normalization behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
445c436 to
f60faf4
Compare
Models frequently emit bare codepoints like U+26A0 (⚠), U+2139 (ℹ), U+2764 (❤), U+2714 (✔), U+2600 (☀), U+263A (☺) which, per Unicode, have Emoji_Presentation=No and render as monochrome text-style glyphs in terminals unless followed by VS16 (U+FE0F). Agent output leaked through the TUI like `⚠ careful` instead of `⚠️ careful`. Added `ensureEmojiPresentation` (lib/emoji.ts): scans for the curated set of text-default codepoints and appends VS16 when the next char is not already VS16, ZWJ, or a keycap-enclosing mark. Idempotent and fast-pathed by a Unicode-range regex so ASCII-heavy text is untouched. Applied once at the top of `Md`'s line parse. Hermes-ink's stringWidth already accounts for VS16, so cursor/layout stays correct.
f60faf4 to
136519a
Compare
ulasbilgen
pushed a commit
to ulasbilgen/hermes-adhd-agent
that referenced
this pull request
May 1, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
aj-nt
pushed a commit
to aj-nt/hermes-agent
that referenced
this pull request
May 1, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
Luminet2023
pushed a commit
to Luminet2023/hermes-agent
that referenced
this pull request
May 1, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
…vs16-injection fix(tui): inject VS16 so text-default emoji render as color glyphs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #13204. LLMs emit bare text-default emoji codepoints (
⚠,ℹ,❤,✔,☀,☺,☎, etc.) which per Unicode haveEmoji_Presentation=Noand render as monochrome text-style glyphs in terminals unless followed by VS16 (U+FE0F). Result: TUI shows a washed-out⚠ carefulinstead of the familiar color⚠️ careful.The terminal actually has the color glyph — it just needs the VS16 signal. Hermes-ink's
stringWidthalready knows about VS16 (log-update.tshasneedsWidthCompensationcovering exactly this), so cursor/layout stays correct once VS16 is present.Fix
New
ensureEmojiPresentation(text)inui-tui/src/lib/emoji.ts:Setof ~95 text-default codepoints (the ones that actually show up in LLM chat output — symbols, hearts, hands, weather, tools, hazards, suits, astrology, arrows).U+20E3), appendU+FE0F.Applied once at the top of
Md'suseMemoline parse, so all markdown-rendered assistant output benefits. User input and tool preview lines are untouched — intentional, those paths don't go throughMd.Test plan
npm test— 116/116 passing, 7 new cases inemoji.test.ts.tsc --noEmitclean.eslintclean on touched files.Before → After
Already-VS16 text and emoji-default codepoints (
🚀,😀,🔥) pass through untouched.Deliberately not included
:rocket:→ 🚀): different feature, different scope.Md: tool-result previews and raw user input stay untouched for now; only the markdown-rendered surface gets VS16 injection.