mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-08 03:01:47 +00:00
fix(ui): reduce status-line jitter while scrolling
This commit is contained in:
parent
a869a523ee
commit
e45df2e81e
4 changed files with 49 additions and 4 deletions
7
cli.py
7
cli.py
|
|
@ -2589,9 +2589,12 @@ class HermesCLI:
|
|||
elapsed = time.monotonic() - t0
|
||||
if elapsed >= 60:
|
||||
_m, _s = int(elapsed // 60), int(elapsed % 60)
|
||||
elapsed_str = f"{_m}m {_s}s"
|
||||
# Fixed-width timer to avoid status-line wrap jitter while
|
||||
# scrolling/repainting (e.g. 01m05s, 12m09s).
|
||||
elapsed_str = f"{_m:02d}m{_s:02d}s"
|
||||
else:
|
||||
elapsed_str = f"{elapsed:.1f}s"
|
||||
# Keep width stable before the 60s rollover as well.
|
||||
elapsed_str = f"{elapsed:5.1f}s"
|
||||
return f" {txt} ({elapsed_str})"
|
||||
return f" {txt}"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
|
@ -244,6 +245,24 @@ class TestCLIStatusBar:
|
|||
|
||||
assert cli_obj._spinner_widget_height(width=64) == 2
|
||||
|
||||
def test_spinner_elapsed_format_is_fixed_width_to_reduce_wrap_jitter(self):
|
||||
cli_obj = _make_cli()
|
||||
cli_obj._spinner_text = "running tool"
|
||||
|
||||
# <60s path
|
||||
cli_obj._tool_start_time = time.monotonic() - 9.2
|
||||
short = cli_obj._render_spinner_text()
|
||||
|
||||
# >=60s path
|
||||
cli_obj._tool_start_time = time.monotonic() - 65.2
|
||||
long = cli_obj._render_spinner_text()
|
||||
|
||||
short_elapsed = short.split("(", 1)[1].rstrip(")")
|
||||
long_elapsed = long.split("(", 1)[1].rstrip(")")
|
||||
|
||||
assert len(short_elapsed) == len(long_elapsed)
|
||||
assert "m" in long_elapsed and "s" in long_elapsed
|
||||
|
||||
def test_voice_status_bar_compacts_on_narrow_terminals(self):
|
||||
cli_obj = _make_cli()
|
||||
cli_obj._voice_mode = True
|
||||
|
|
|
|||
18
ui-tui/src/__tests__/statusBarTicker.test.ts
Normal file
18
ui-tui/src/__tests__/statusBarTicker.test.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { padVerb, VERB_PAD_LEN } from '../components/appChrome.js'
|
||||
import { VERBS } from '../content/verbs.js'
|
||||
|
||||
describe('FaceTicker verb padding', () => {
|
||||
it('pads every verb to the same width', () => {
|
||||
for (const verb of VERBS) {
|
||||
expect(padVerb(verb)).toHaveLength(VERB_PAD_LEN)
|
||||
}
|
||||
})
|
||||
|
||||
it('keeps trailing ellipsis attached', () => {
|
||||
for (const verb of VERBS) {
|
||||
expect(padVerb(verb).startsWith(`${verb}…`)).toBe(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -20,6 +20,11 @@ import type { Msg, Usage } from '../types.js'
|
|||
const FACE_TICK_MS = 2500
|
||||
const HEART_COLORS = ['#ff5fa2', '#ff4d6d']
|
||||
|
||||
// Keep verb segment width stable so status-bar content to the right doesn't
|
||||
// jitter when the ticker rotates between short/long verbs.
|
||||
export const VERB_PAD_LEN = VERBS.reduce((max, v) => Math.max(max, v.length), 0) + 1 // + ellipsis
|
||||
export const padVerb = (verb: string) => `${verb}…`.padEnd(VERB_PAD_LEN, ' ')
|
||||
|
||||
// Compact alternates for the `emoji` and `ascii` indicator styles.
|
||||
// Each entry is a fixed-width (display-width) glyph.
|
||||
const EMOJI_FRAMES = ['⚕ ', '🌀', '🤔', '✨', '🍵', '🔮']
|
||||
|
|
@ -102,8 +107,8 @@ function FaceTicker({ color, startedAt }: { color: string; startedAt?: null | nu
|
|||
|
||||
const { frame } = renderIndicator(style, tick)
|
||||
const verb = VERBS[verbTick % VERBS.length] ?? ''
|
||||
const verbSegment = showVerb ? ` ${verb}…` : ''
|
||||
const durationSegment = startedAt ? ` · ${fmtDuration(now - startedAt)}` : ''
|
||||
const verbSegment = showVerb ? ` ${padVerb(verb)}` : ''
|
||||
const durationSegment = startedAt ? `· ${fmtDuration(now - startedAt)}` : ''
|
||||
|
||||
return (
|
||||
<Text color={color}>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue