Skip to content

fix(tui): inject VS16 so text-default emoji render as color glyphs#13253

Merged
OutThisLife merged 1 commit into
mainfrom
bb/tui-emoji-vs16-injection
Apr 21, 2026
Merged

fix(tui): inject VS16 so text-default emoji render as color glyphs#13253
OutThisLife merged 1 commit into
mainfrom
bb/tui-emoji-vs16-injection

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #13204. LLMs emit bare text-default emoji codepoints (, , , , , , , etc.) which per Unicode have Emoji_Presentation=No and render as monochrome text-style glyphs in terminals unless followed by VS16 (U+FE0F). Result: TUI shows a washed-out ⚠ careful instead of the familiar color ⚠️ careful.

The terminal actually has the color glyph — it just needs the VS16 signal. Hermes-ink's stringWidth already knows about VS16 (log-update.ts has needsWidthCompensation covering exactly this), so cursor/layout stays correct once VS16 is present.

Fix

New ensureEmojiPresentation(text) in ui-tui/src/lib/emoji.ts:

  • Curated Set of ~95 text-default codepoints (the ones that actually show up in LLM chat output — symbols, hearts, hands, weather, tools, hazards, suits, astrology, arrows).
  • If the codepoint is in the set and not already followed by VS16, ZWJ, or a keycap-enclosing mark (U+20E3), append U+FE0F.
  • Fast-pathed by a Unicode-range regex: pure ASCII / already-correct text short-circuits with a single scan and no allocation.
  • Idempotent.

Applied once at the top of Md's useMemo line parse, so all markdown-rendered assistant output benefits. User input and tool preview lines are untouched — intentional, those paths don't go through Md.

Test plan

  • npm test — 116/116 passing, 7 new cases in emoji.test.ts.
  • tsc --noEmit clean.
  • eslint clean on touched files.

Before → After

⚠ careful            → ⚠️ careful
ℹ note               → ℹ️ note
love ❤ you           → love ❤️ you
✔ done               → ✔️ done
☀ sunny              → ☀️ sunny

Already-VS16 text and emoji-default codepoints (🚀, 😀, 🔥) pass through untouched.

Deliberately not included

  • Shortcode conversion (:rocket: → 🚀): different feature, different scope.
  • Global application outside Md: tool-result previews and raw user input stay untouched for now; only the markdown-rendered surface gets VS16 injection.
  • Presentation downgrade (emoji → text): terminals that lack emoji fonts are not hurt by VS16; it's the narrow opposite signal that was missing.

@OutThisLife OutThisLife requested a review from Copilot April 21, 2026 19:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Md parsing.
  • 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.

Comment thread ui-tui/src/lib/emoji.ts Outdated
Comment thread ui-tui/src/lib/emoji.ts Outdated
Comment thread ui-tui/src/lib/emoji.ts Outdated
Comment thread ui-tui/src/__tests__/emoji.test.ts Outdated
@OutThisLife OutThisLife force-pushed the bb/tui-emoji-vs16-injection branch from 445c436 to f60faf4 Compare April 21, 2026 19:50
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Apr 21, 2026
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.
@OutThisLife OutThisLife force-pushed the bb/tui-emoji-vs16-injection branch from f60faf4 to 136519a Compare April 21, 2026 20:53
@OutThisLife OutThisLife merged commit eacf313 into main Apr 21, 2026
8 of 9 checks passed
@OutThisLife OutThisLife deleted the bb/tui-emoji-vs16-injection branch April 21, 2026 20:53
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants