mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
CJK and emoji glyphs render as two terminal cells but JS String#length and the model's own padding count them as one, so any markdown table with Chinese / Japanese / Korean cells drifts right per row when a real terminal renders it. Both surfaces fix this with a display-cell width measurement (wcswidth on the Python side, stringWidth on the TUI side). Changes: - agent/markdown_tables.py: new helper. realign_markdown_tables(text) detects markdown table blocks (header + |---| divider) and rewrites the row padding using wcwidth.wcswidth so every pipe and dash lines up across rows. No-op on text without tables. - cli.py: hook the helper into _render_final_assistant_content for strip / render modes (raw passes through untouched), and into the streaming line emitter so live token-by-token rendering also produces aligned tables. A small two-buffer state machine in _emit_stream_text holds table rows until the block ends, then flushes them through the realigner so all rows pad to a single per-column width. - ui-tui/src/components/markdown.tsx: renderTable now uses stringWidth (Bun.stringWidth fast path + East-Asian-width-aware fallback, already memoised in @hermes/ink) instead of UTF-16 String#length for both column-width measurement and per-cell padding. Drops the comment that documented the bug as a deliberate limitation. Validation: - New tests/agent/test_markdown_tables.py (11): every rebuilt block shares pipe column offsets across rows for pure CJK, mixed CJK+emoji, ragged-row, and multi-table inputs. - Updated tests/cli/test_cli_markdown_rendering.py: the existing strip-mode test asserted exact whitespace; rewritten to assert the alignment contract (cell content survives + every rendered row shares pipe offsets). - New ui-tui markdown.test.ts case (1): rendered column-2 start offset is identical for the header + every body row, including the CJK row that drifted before the fix. - Live: hermes chat -q with the user-reported screenshot prompt now produces a perfectly aligned table on the wire (header, divider, 4 body rows including '通义千问', all pipes at identical columns). |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| test_branch_command.py | ||
| test_busy_input_mode_command.py | ||
| test_cli_approval_ui.py | ||
| test_cli_background_tui_refresh.py | ||
| test_cli_bracketed_paste_sanitizer.py | ||
| test_cli_browser_connect.py | ||
| test_cli_context_warning.py | ||
| test_cli_copy_command.py | ||
| test_cli_extension_hooks.py | ||
| test_cli_external_editor.py | ||
| test_cli_file_drop.py | ||
| test_cli_force_redraw.py | ||
| test_cli_goal_interrupt.py | ||
| test_cli_image_command.py | ||
| test_cli_init.py | ||
| test_cli_interrupt_subagent.py | ||
| test_cli_loading_indicator.py | ||
| test_cli_markdown_rendering.py | ||
| test_cli_mcp_config_watch.py | ||
| test_cli_new_session.py | ||
| test_cli_prefix_matching.py | ||
| test_cli_preloaded_skills.py | ||
| test_cli_provider_resolution.py | ||
| test_cli_reload_skills.py | ||
| test_cli_retry.py | ||
| test_cli_save_config_value.py | ||
| test_cli_secret_capture.py | ||
| test_cli_shift_enter_newline.py | ||
| test_cli_shutdown_memory_messages.py | ||
| test_cli_skin_integration.py | ||
| test_cli_status_bar.py | ||
| test_cli_status_command.py | ||
| test_cli_steer_busy_path.py | ||
| test_cli_terminal_response_sanitizer.py | ||
| test_cli_tools_command.py | ||
| test_cli_user_message_preview.py | ||
| test_compress_focus.py | ||
| test_cprint_bg_thread.py | ||
| test_ctrl_enter_newline.py | ||
| test_cwd_env_respect.py | ||
| test_destructive_slash_confirm.py | ||
| test_fast_command.py | ||
| test_gquota_command.py | ||
| test_manual_compress.py | ||
| test_personality_none.py | ||
| test_prompt_text_input_thread_safety.py | ||
| test_quick_commands.py | ||
| test_reasoning_command.py | ||
| test_resume_display.py | ||
| test_save_conversation_location.py | ||
| test_session_boundary_hooks.py | ||
| test_stream_delta_think_tag.py | ||
| test_surrogate_sanitization.py | ||
| test_tool_progress_scrollback.py | ||
| test_worktree.py | ||
| test_worktree_security.py | ||