← Back to PRs

#20405: feat(ui): KaTeX math rendering, collapsible tool cards, image attach button & LaTeX→Unicode for channels

by ayaanngandhi open 2026-02-18 21:53 View on GitHub →
app: web-ui agents size: XL
## Summary - Problem: Webchat has no math rendering — LaTeX appears as raw `$...$` text. Tool cards take up too much vertical space. No way to attach images except paste. External channels (Discord/Telegram) receive raw LaTeX syntax. - Why it matters: Math-heavy conversations look broken. Tool-heavy sessions are noisy. Image UX is limited. - What changed: KaTeX rendering in webchat, collapsible tool cards via details/summary, + button for image attachments, LaTeX-to-Unicode conversion for outbound channel messages, skipLatex for tool output. Currency patterns like $50 are safely ignored. - What did NOT change (scope boundary): No server-side changes to chat.history, no changes to how images are stored/transmitted, no changes to TUI rendering logic (already had Unicode math). All changes run on the default control UI port — no new services or ports. ## Change Type - [x] Feature - [x] Refactor ## Scope - [x] Gateway / orchestration (deliver.ts — outbound LaTeX conversion) - [x] UI / DX (webchat KaTeX, tool cards, image button) ## Linked Issue/PR - N/A ## User-visible / Behavior Changes - Webchat renders `$...$` and `$$...$$` as formatted math via KaTeX - Tool call and result cards are collapsed by default with a chevron arrow — click to expand - New + button next to the message input opens an image file picker - Discord/Telegram/WhatsApp/Signal messages convert LaTeX to Unicode math (E=mc^2 → E=mc²) - Currency like $50 is left untouched — only content with LaTeX characters (\, ^, _, {, }) is processed - Tool sidebar content skips LaTeX rendering (dollar signs in tool output stay as-is) ## Security Impact (required) - New permissions/capabilities? No - Secrets/tokens handling changed? No - New/changed network calls? No - Command/tool execution surface changed? No - Data access scope changed? No ## Repro + Verification ### Environment - OS: Ubuntu 22.04 - Runtime/container: Node v22 - Model/provider: Anthropic Claude Opus 4.6 - Integration/channel: Discord, webchat (default control UI port) ### Steps 1. Open webchat 2. Send a message containing `$E = mc^2$` or `$$\frac{-b}{2a}$$` 3. Observe rendered math 4. Trigger a tool call — observe collapsed card with chevron 5. Click + button — file picker opens for images 6. Send a message with `$50` — verify it stays as currency, not LaTeX ### Expected - Math renders as formatted equations - Tool cards collapsed by default - + button opens native file picker - $50 stays as $50 ### Actual - All above confirmed working ## Evidence - KaTeX rendering confirmed: inline E=mc², display quadratic formula, Euler's identity, integrals, matrices - Tool cards collapsed with chevron, expand on click - Image picker tested on mobile browser - LaTeX→Unicode tested programmatically: - `$E=mc^2$` → `E=mc²` ✅ - `$\frac{a}{b}$` → `a⁄b` ✅ - `$\sqrt{x^2+y^2}$` → `√(x²+y²)` ✅ - `$\sum_{i=1}^{n} x_i$` → `∑ᵢ₌₁ⁿ xᵢ` ✅ - `$50 and $100` → `$50 and $100` (unchanged) ✅ - `Cost $50 but $E=mc^2$ is physics` → `Cost $50 but E=mc² is physics` ✅ ## Human Verification (required) - Verified: KaTeX inline + display math, tool card collapse/expand, image attach via + button, dollar signs in tool output not triggering LaTeX, currency patterns preserved, LaTeX→Unicode conversion - Edge cases checked: Nested fractions, matrices, summation notation, tool output with $ prices, mixed currency + LaTeX in same message ## Compatibility / Migration - Backward compatible? Yes - Config/env changes? No - Migration needed? No ## Failure Recovery (if this breaks) - Revert the commit or checkout main branch - No config changes to restore ## Risks and Mitigations - Risk: processLatexForTerminal() could mangle non-LaTeX $ text - Mitigation: Fixed — inline math now requires content to contain LaTeX characters (\, ^, _, {, }). Currency like $50 is ignored. Regex scanning resets on skipped matches so real LaTeX after currency still works. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds KaTeX math rendering in the webchat UI, converts tool cards from flat divs to collapsible `<details>`/`<summary>` elements, adds an image attach button, and introduces LaTeX-to-Unicode conversion for outbound messages to external channels (Discord, Telegram, etc.). - **Syntax error in `handleImagePick`**: `ui/src/ui/views/chat.ts` line 208 has `};` instead of `});`, missing the closing parenthesis for `addEventListener`. This will cause a compilation error. - **`htmlEscapeRenderer` bypass weakens HTML escape protection**: The KaTeX check in `ui/src/ui/markdown.ts` (lines 246–252) allows raw HTML through if it contains `class="katex"`, but this doesn't serve the placeholder-based pipeline and could be exploited to bypass the intentional HTML escaping (issue #13937). DOMPurify still provides the security boundary, but the bypass is unnecessary. - **LaTeX-to-Unicode conversion is well-implemented**: Currency patterns (`$50`) are correctly excluded, code blocks are skipped, and the conversion runs only on external channels (gated by `!isInternalMessageChannel` upstream). - **Collapsible tool cards** use native `<details>` elements with proper `stopPropagation` on the sidebar "View" button to avoid toggling the collapse when opening the sidebar. <h3>Confidence Score: 2/5</h3> - This PR has a syntax error that will prevent compilation and should be fixed before merging. - Score of 2 reflects a clear syntax error in `ui/src/ui/views/chat.ts` (missing closing parenthesis on `addEventListener`) that will break the build, plus a weaker but notable concern about the `htmlEscapeRenderer` bypass in `markdown.ts`. The rest of the changes — LaTeX-to-Unicode conversion, collapsible tool cards, system prompt hint — are well-structured. - `ui/src/ui/views/chat.ts` (syntax error), `ui/src/ui/markdown.ts` (HTML escape bypass) <sub>Last reviewed commit: eb341b7</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs