mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-06 07:51:53 +00:00
fix(tui): width-aware markdown table rendering with vertical fallback (#26195)
* refactor(tui): thread cols through Md/StreamingMd/renderTable, update cache key
* feat(tui): three-tier width calc + full-line string rendering in renderTable
Replaces the old renderTable (L203-244) with:
- Empty table guard
- Ragged row normalization
- Three-tier column width calculation (ideal → proportional shrink → hard scale)
- Rounding remainder distribution
- Full-line string rendering (one <Text> per row, not per cell)
- wrap=truncate-end on all table lines
- All cells rendered as plain text via stripInlineMarkup
No wrapping or vertical fallback yet — those come in Phase 3 and 4.
* feat(tui): wrapCell with grapheme-safe hard-break + multi-line row rendering
Adds:
- Intl.Segmenter-based grapheme splitting (fallback to [...word])
- wrapCell() for width-correct word wrapping on stripped text
- Multi-line row rendering with LineEntry metadata (header/separator/body)
- Post-render safety condition (maxLineWidth computed, vertical fallback in Task 4)
- Non-wrapping path preserved for tables that fit at ideal widths
* feat(tui): vertical key-value fallback with scaled threshold + safety check
Wires:
- Scaled row-height threshold (numCols<=3: 8, <=6: 5, else: 4)
- Post-render safety check (maxLineWidth > available space)
- Header-only edge case
- Vertical format: bold headers, stripped cell text, clamped separator width
- Iterates headers (not rows) for consistent key-value fields on ragged rows
* test(tui): pass cols to Md in test helpers, add width-overflow assertions
- renderAtWidth now passes cols={columns} to <Md> so width-aware code paths
are exercised in tests
- tableFuzz: every rendered line must fit within allocated width (stringWidth)
- tableRepro: separator regex updated to match truncation ellipsis
- stringWidth imported from @hermes/ink for CJK-correct assertions
* fix(tui): address adversarial review — comment tier 3 budget overshoot, eliminate redundant wrapCell
- Add comment on Tier 3 MIN_COL_WIDTH clamp exceeding budget (self-heals via safetyOverflow)
- Track tallestBodyRow during allEntries build pass instead of re-wrapping every cell
in a second traversal (eliminates O(cells) of redundant stripInlineMarkup+stringWidth)
* fix(tui): pass cols to recursive fenced-markdown Md, fix test frame extraction
- Thread cols into <Md> for fenced markdown blocks (L734) so nested
tables use the width-aware renderer instead of max-content path
- Fix renderAtWidth helpers to extract final Ink repaint frame instead
of concatenating all intermediate frames (REPAINT_RE split)
- Add fenced-markdown-table fixture to tableFuzz (exercises the nested path)
* chore: remove repro test suites and tmux driver script
These were scaffolding for development/reproduction — not needed in the PR.
This commit is contained in:
parent
006937f7d0
commit
55c9f32060
3 changed files with 295 additions and 47 deletions
|
|
@ -139,13 +139,15 @@ export const MessageLine = memo(function MessageLine({
|
|||
}
|
||||
|
||||
if (msg.role === 'assistant') {
|
||||
const bodyWidth = transcriptBodyWidth(cols, msg.role, t.brand.prompt)
|
||||
|
||||
return isStreaming ? (
|
||||
// Incremental markdown: split at the last stable block boundary so
|
||||
// only the in-flight tail re-tokenizes per delta. See
|
||||
// streamingMarkdown.tsx for the cost model.
|
||||
<StreamingMd compact={compact} t={t} text={boundedLiveRenderText(msg.text)} />
|
||||
<StreamingMd cols={bodyWidth} compact={compact} t={t} text={boundedLiveRenderText(msg.text)} />
|
||||
) : (
|
||||
<Md compact={compact} t={t} text={limitHistoryRender ? boundedHistoryRenderText(msg.text) : msg.text} />
|
||||
<Md cols={bodyWidth} compact={compact} t={t} text={limitHistoryRender ? boundedHistoryRenderText(msg.text) : msg.text} />
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue