文件最后提交记录最后更新时间
fix(tui): handle timeout/error subagent statuses in /agents (#26687) Accept delegation timeout/error statuses in the TUI subagent model, normalize unknown status strings defensively, and harden /agents overlay rendering/sorting so unknown statuses cannot crash glyph/color lookup. Add regression tests for live event normalization and disk snapshot replay.20 天前
feat(tui): segment turns with rule above non-first user msgs; trim ticker dead space (#21846) Multi-turn transcripts ran together visually because every user message got the same vertical rhythm regardless of position. Adds a short ─── in the border colour above every user message after the first, so each turn reads as its own block. Height estimator gains a withSeparator flag so virtual scrolling pre-allocates the extra two rows (rule + top margin) and avoids a jump on first measurement. While in the area: the busy-indicator duration was padded with padStart(7), leaving five visible spaces between · and the digits (⠋ · 2s) — especially loud under the verb-less unicode style. Drop the padding entirely (⠋ · 2s); the model label now shifts a few columns as the duration grows, which is the right trade-off for the minimal indicator styles. The verb-padding test stays; the duration-padding test is removed alongside the function it covered.27 天前
Merge pull request #28829 from NousResearch/bb/tui-no-history-truncation fix(tui): render full assistant text in scrollback (no history truncation)16 天前
fix(tui): honor skin highlight colors (#20895)29 天前
feat(tui): collapsible sections in startup banner (skills, system prompt, MCP) The TUI SessionPanel banner now uses collapsible \u25b8/\u25be toggle sections matching the existing Chevron convention used for runtime agent details. Skills, system prompt, and MCP server lists are collapsed by default; tools remain expanded as the most actionable info. - tui_gateway/server.py: _session_info() now passes agent._cached_system_prompt through to the TUI frontend - ui-tui/src/types.ts: added system_prompt?: string to SessionInfo - ui-tui/src/components/branding.tsx: rewrote SessionPanel with CollapseToggle helper + per-section useState toggles Default states: tools=open, skills=collapsed, system=collapsed, mcp=collapsed. Clicking any \u25b8/\u25be header toggles that section. 29 天前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前
feat(tui): add a mini help menu when u write ? in the input field it feels so nice :3 just a lil popup ! doesn't get in the way or take any focus or anything, and directs users to /help for more info :3 1 个月前
fix(tui): preserve dunder identifiers in markdown 16 天前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前
Merge pull request #28829 from NousResearch/bb/tui-no-history-truncation fix(tui): render full assistant text in scrollback (no history truncation)16 天前
fix(tui): address remaining review feedback — ordering and digit shortcuts - Emit providers in CANONICAL_PROVIDERS order (matching hermes model) with user-defined/custom providers appended after - Remove digit quick-select (1-9,0) handler — inconsistent with absolute row numbering and already removed from hint text - Remove unused windowOffset import 1 个月前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前
fix(tui): allow transcript scroll + Esc during approval/clarify/confirm prompts (#26414) When an approval / clarify / confirm overlay was active, the global input handler in useInputHandlers returned for every key that wasn't Ctrl+C, which silently disabled transcript scrolling. On long threads the context the prompt was asking about often lived above the visible viewport, and being unable to scroll while answering felt like the prompt had locked the UI. ApprovalPrompt also had no Esc handler at all, so the one obvious 'abort' key did nothing during a permission prompt and the user had to memorize Ctrl+C or hunt for the deny number. Fixes: - Extract shouldFallThroughForScroll(key) (pure, exported) covering wheel scrolls, PageUp/PageDown, and Shift+ArrowUp/Down. When a prompt overlay is up and the pressed key is a scroll input, skip the early return so it reaches the existing wheel/PageUp/Shift+arrow handlers below. Plain arrows still drive in-prompt selection — they don't fall through. - ApprovalPrompt now maps Esc to onChoice('deny'), parity with the global Ctrl+C cancellation path that already invokes cancelOverlayFromCtrlC() for approvals. The bottom-of-prompt hint now advertises 'Esc/Ctrl+C deny'. - Extract approvalAction(ch, key, sel) — pure key-dispatch helper for the approval prompt, exported so the regression matrix (Esc, numbers, Enter, arrows, edge clamping, precedence) is testable without mounting Ink. Tests: - useInputHandlers.test.ts: 6 cases covering shouldFallThroughForScroll positives (wheel/PageUp/PageDown/Shift+arrows) and negatives (plain arrows, bare shift, no scroll key). - approvalAction.test.ts: 8 cases covering Esc→deny, numeric mapping, Enter, ↑↓ within bounds, edge clamping, Esc-beats-others precedence, unrelated keystrokes.20 天前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前
fix(tui): require double-tap d to confirm session delete Single-key confirm matches how the picker already accepts 1-9 to resume — no separate y/n keymap to learn — and "press d again" is self-documenting next to the cursor. 1 个月前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前
fix(tui): inline todo in transcript, group across thinking 1 个月前
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.20 天前
fix(tui): align composer cursorLayout with wrap-ansi to kill multiline cursor drift The composer's cursorLayout (in ui-tui/src/lib/inputMetrics.ts) used a hand-rolled word-wrap algorithm to decide where useDeclaredCursor should park the hardware cursor. But Ink's <Text wrap="wrap"> renders the same text via wrap-ansi. The two algorithms disagreed on common real-world inputs — "branch investigate" at cols=20, "hello world" at cols=8, exact-fill strings like "abcdefgh" at cols=8 — so the hardware cursor parked several cells past where Ink actually rendered the last character. Users saw a multi-cell blank gap between their last-typed letter and the cursor block, especially on narrow terminals (the Cursor IDE built-in terminal was the worst offender). Three previous PRs (#26717, #25860, #22197) chased fast-echo displayCursor/cursorDeclaration drift and in-band-vs-native cursor heuristics. None of them touched the underlying wrap-algorithm mismatch, which is why the bug kept resurfacing. Fix: source cursorLayout's line breaks from wrap-ansi directly. Walk its emitted string char-by-char, tracking original-string offsets, push a VisualLine at each '\n'. Also drop the buggy column >= w overflow rule in cursorLayout — that's what pushed exact-fill text onto a phantom next row. canFastBackspaceShape now detects the wrap boundary in BOTH coordinate conventions (column === 0 OR column >= columns), since exact-fill now reports as (0, columns) instead of the previous (1, 0). The physical state is identical — the terminal auto-wraps at column N either way — but the layout function reports the position more honestly. Tests: - ui-tui/src/__tests__/textInputWrap.test.ts: 3 tests that pinned the BUGGY behavior were updated to assert wrap-ansi parity (the real invariant). Added a typing-prefix invariant: cursorLayout must agree with wrap-ansi at every character of a long input. - ui-tui/src/__tests__/cursorDriftRegression.test.ts: new file. Walks the user-reported bug message char-by-char at 7 widths and asserts agreement with wrap-ansi at every prefix. Verification: - 791/791 vitest tests pass. - 84/84 tui-gateway pytest tests pass via scripts/run_tests.sh. - PTY repro (typing into a real hermes --tui PTY at cols=50/55/60): cursor lands exactly 1 cell past the last typed char in every case the bug previously drifted. 18 天前
refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC Full codebase pass using the /clean doctrine (KISS/DRY, no one-off helpers, no variables-used-once, pure functional where natural, inlined obvious one-liners, killed dead exports, narrowed types, spaced JSX). All contracts preserved — no RPC method, event name, or exported type shape changed. app/ — 15 files, -134 LOC - inlined 4 one-off helpers (titleCase, isLong, statusToneFrom, focusOutside predicate) - stores to arrow-const style (buildUiState, buildTurnState, buildOverlayState plus get/patch/reset triplets) - functional slash/registry byName map (flatMap over for-loops) - dropped dead param live in cancelOverlayFromCtrlC - DRY'd duplicate shift() call in scrollWithSelection - consolidated sections.push calls in /help components/ — 12 files, -40 LOC - extracted inline prop types to interfaces at file bottom (13×) - inlined 6 one-off vars (pctLabel, logoW, heroW, cwd, title, hint) - promoted HEART_COLORS + OPTS/LABELS to module scope - JSX sibling spacing across 9 files - un-shadowed raw in textInput - components/thinking.tsx + components/markdown.tsx untouched (structurally load-bearing / edge-case-heavy) config content domain protocol/ — 8 files, -77 LOC - tightened 3 regexes (MOUSE_TRACKING, looksLikeSlashCommand, hasInterpolation — dropped stateful lastIndex dance) - dead export ParsedSlashCommand removed - MODES narrowed to as const, .find(m => m === s) replaces .includes() ? (as cast) : null - fortunes.ts hash via reduce - fmtDuration ternary chain - inlined aboveViewport predicate in viewport.ts hooks/ + lib/ — 9 files, -38 LOC - ANSI_RE via String.fromCharCode(27) + WS_RE lifted to module scope (no more eslint-disable no-control-regex) - compactPreview/edgePreview/thinkingPreview → ternary arrows - useCompletion: hoisted pathReplace, moved stale-ref guard earlier - useInputHistory: dropped useCallback wrapper (append is stable) - useVirtualHistory: replaced 4× any with unknown + narrow MeasuredNode interface + one cast site root TS — 3 files, -63 LOC - banner.ts: parseRichMarkup via matchAll instead of exec/lastIndex, artWidth via reduce - gatewayClient.ts: resolvePython candidate list collapse, inlined one-branch guards in dispatch/pushLog/drain/request - types.ts: alpha-sorted ActiveTool / Msg / SudoReq / SecretReq members eslint config - disabled react-hooks/exhaustive-deps on packages/hermes-ink/** (compiled by react/compiler, deps live in $[N] memo arrays that eslint can't introspect) and removed the now-orphan in-file disable directive in ScrollBox.tsx fixes (not from the cleaner pass) - useComposerState: unlinkSync(file) + try/catch → rmSync(file, { force: true }) — kills the no-empty lint error and is more idiomatic - useConfigSync: added setBellOnComplete + setVoiceEnabled to the two useEffect dep arrays (they're stable React setState setters; adding is safe and silences exhaustive-deps) verification - npx eslint src/ packages/ → 0 errors, 0 warnings - npm run type-check → clean - npm test → 50/50 - npm run build → 394.8kb ink-bundle.js, 11ms esbuild - pytest tests/tui_gateway/ tests/test_tui_gateway_server.py tests/hermes_cli/test_tui_resume_flow.py tests/hermes_cli/test_tui_npm_install.py → 57/57 1 个月前
fix(tui): handle timeout/error subagent statuses in /agents (#26687) Accept delegation timeout/error statuses in the TUI subagent model, normalize unknown status strings defensively, and harden /agents overlay rendering/sorting so unknown statuses cannot crash glyph/color lookup. Add regression tests for live event normalization and disk snapshot replay.20 天前
fix(tui): restore macOS copy behavior and theme polish (#17131) This PR groups the TUI fixes that restore macOS Terminal usability and clean up the theme/composer regressions: - copy transcript selections on macOS drag-release so Terminal.app users can copy while mouse tracking is enabled - copy composer selections on macOS drag-release; composer selection is internal to TextInput and does not use the global Ink selection bus - keep IDE Cmd+C forwarding setup macOS-only, and make keybinding conflict checks respect simple when-clause overlap/negation - force truecolor before chalk initializes (unless NO_COLOR / FORCE_COLOR / HERMES_TUI_TRUECOLOR opt-outs apply) so the default banner keeps its gold/amber/bronze gradient in Terminal.app - move TUI surfaces onto semantic theme tokens and preserve skin prompt symbols as bare tokens with renderer-owned spacing - render focused placeholders as dim hint text in TTY mode instead of inverse/selected-looking synthetic cursor text1 个月前