hermes - ✅(Solved) Fix [Bug]: /model picker doesn't scroll with long provider catalogs (Ollama Cloud, 36+ models) and leaves command in input after selection [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#11583Fetched 2026-04-18 06:00:13
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2closed ×1

Root Cause

_get_model_picker_display() in cli.py renders every choice into a prompt_toolkit Window with no max_height and no scroll viewport. On long catalogs the panel exceeds terminal rows and prompt_toolkit's HSplit clips the bottom.

The Enter handler that confirms a picker selection (around cli.py:8557) closes the picker but never calls event.app.current_buffer.reset() — unlike the Ctrl+C handler which does — so the typed /model command stays in the buffer.

Fix Action

Fixed

PR fix notes

PR #11584: fix(cli): scroll the /model picker viewport on long provider catalogs

Description (problem / solution / changelog)

What does this PR do?

Fixes three UX bugs in the interactive /model picker:

  1. Long provider catalogs (Ollama Cloud's 36+ models, OpenRouter 31+) overflowed the panel — the picker rendered every choice into a prompt_toolkit Window with no max height, so the bottom border and any items past the terminal's last row were clipped. The cursor disappeared off-screen when arrowing down.
  2. No Esc binding — only Ctrl+C would dismiss the picker.
  3. /model text lingered in the input bar after selection — the picker's Enter handler closed the picker but never reset event.app.current_buffer, unlike the Ctrl+C and (new) Esc paths.

The viewport vocabulary (reserved_below=6) deliberately mirrors PR #11260 (approval/clarify row-budgeting) so the chrome math reads consistently across the modal panels.

Related Issue

Fixes #11583

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • cli.py (_compute_model_picker_viewport, new static helper) — slides a scroll offset that keeps the selected cursor on screen, sized from term_rows − reserved_below(6) − panel_chrome(6) with a min_visible(3) floor.
  • cli.py (_get_model_picker_display) — renders only the visible slice and persists the offset on _model_picker_state across redraws.
  • cli.py (Enter handler for picker) — resets event.app.current_buffer after _handle_model_picker_selection() so the prompt is empty after a successful switch.
  • cli.py (new keybinding) — binds Esc (eager) to close the picker, matching the Cancel button.
  • tests/hermes_cli/test_model_picker_viewport.py (new) — 8 unit tests covering short/long lists, scroll up/down, bottom clamp, tiny terminal, stage switch, and full traversal.

How to Test

  1. hermes chat
  2. Type /model, press Enter — provider list opens.
  3. Pick Ollama Cloud (or any provider with > terminal-rows-worth of models).
  4. Arrow down past the originally-visible window — the highlighted row scrolls into view; the bottom border stays drawn.
  5. Press Esc — picker closes, prompt is empty.
  6. Re-open /model, pick a model with Enter — picker closes, prompt is empty (no /model left behind).

Unit tests:

pytest tests/hermes_cli/test_model_picker_viewport.py -v

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(cli):, refactor(cli):)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (3 commits, all picker UX)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS (iTerm2)

Documentation & Housekeeping

  • I've updated relevant documentation — N/A (no public API change)
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) — get_app().output.get_size().rows and shutil.get_terminal_size() fallback are both terminal-agnostic
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Screenshots / Logs

Before

<img width="605" height="694" alt="image" src="https://github.com/user-attachments/assets/ef568cd6-7b2a-4f3f-885d-9347aa63ef87" />

After

<img width="579" height="625" alt="image" src="https://github.com/user-attachments/assets/6325765b-b479-407a-93c6-3a57de834ced" />

(adding screenshots)

Changed files

  • cli.py (modified, +54/-2)
  • tests/hermes_cli/test_model_picker_viewport.py (added, +62/-0)

PR #11625: fix(cli): scroll the /model picker viewport on long provider catalogs (salvage of #11584)

Description (problem / solution / changelog)

Summary

Salvage of PR #11584 (@jvcl) onto current main. Fixes three /model picker UX bugs: long provider catalogs no longer clip past the viewport, Esc dismisses the picker, and the /model text no longer lingers in the input bar after selection.

Changes

  • cli.py — adds _compute_model_picker_viewport (static helper), limits the render loop to the visible slice, binds Esc to close the picker, clears the input buffer on Enter-select
  • tests/hermes_cli/test_model_picker_viewport.py — 8 unit tests for the viewport math
  • scripts/release.py — AUTHOR_MAP entry for jvcl's commit email

Validation

  • pytest tests/hermes_cli/test_model_picker_viewport.py → 8/8 pass
  • pytest tests/hermes_cli/ → 2200 passed, 2 skipped
  • py_compile cli.py → ok
  • Live PTY smoke in tmux (PYTHONPATH pinned to worktree):
    • 25-row terminal, OpenRouter (31 models): scroll down tracks cursor, bottom border stays drawn, bottom clamp on Cancel works, upward scroll recovers, Esc dismisses with empty input, Enter-select leaves empty input
    • 13-row tiny terminal: min_visible=3 floor holds, only 3 models visible, chrome intact

Credit to @jvcl — three commits cherry-picked with original authorship preserved. Closes #11583.

Changed files

  • cli.py (modified, +54/-2)
  • scripts/release.py (modified, +1/-0)
  • tests/hermes_cli/test_model_picker_viewport.py (added, +62/-0)
RAW_BUFFERClick to expand / collapse

Bug Description

The /model picker in the interactive CLI does not scroll. When a provider exposes more models than fit on screen (e.g. Ollama Cloud has 36+ models), the bottom border of the picker panel and the last items in the list are clipped — there is no way to navigate to or select them. The cursor disappears below the visible area as you arrow down.

A second UX issue: after picking a model from the picker and confirming with Enter, the original /model text the user typed remains in the input bar instead of being cleared.

Steps to Reproduce

  1. Run hermes chat
  2. Type /model and press Enter
  3. Pick a provider with many models (Ollama Cloud — 36+)
  4. Arrow down past the visible window

Expected Behavior

  • The picker scrolls so the highlighted cursor stays on screen.
  • The bottom border of the panel is always visible.
  • After confirming a selection (Enter), the input bar is empty.
  • Pressing Esc closes the picker (consistent with Cancel).

Actual Behavior

  • Bottom border + last items are rendered off-screen and unreachable.
  • After selecting, /model is left lingering in the prompt.
  • No Esc binding to dismiss the picker (only Ctrl+C).

Affected Component

CLI (interactive chat)

Operating System

macOS (iTerm2)

Root Cause Analysis

_get_model_picker_display() in cli.py renders every choice into a prompt_toolkit Window with no max_height and no scroll viewport. On long catalogs the panel exceeds terminal rows and prompt_toolkit's HSplit clips the bottom.

The Enter handler that confirms a picker selection (around cli.py:8557) closes the picker but never calls event.app.current_buffer.reset() — unlike the Ctrl+C handler which does — so the typed /model command stays in the buffer.

Proposed Fix

  • Add a viewport helper that caps visible items based on terminal rows minus chrome, mirroring the row-budgeting vocabulary (reserved_below=6) from PR #11260's approval/clarify panel fix.
  • Slide a scroll offset to keep the selected cursor on screen.
  • Bind ESC (eager) to close the picker.
  • Reset event.app.current_buffer in the picker's Enter handler.

PR ready.

  • I'd like to fix this myself and submit a PR
<img width="660" height="689" alt="Image" src="https://github.com/user-attachments/assets/1a6fa82f-16b9-4432-90cd-c0bba89f8e71" />

extent analysis

TL;DR

To fix the scrolling issue in the /model picker and the input bar not clearing after selection, modify the cli.py file to add a viewport helper, implement scrolling, bind the ESC key to close the picker, and reset the current buffer in the Enter handler.

Guidance

  • Review the cli.py file, specifically the _get_model_picker_display() function, to understand how the picker is rendered and identify where to add the viewport helper.
  • Implement a scroll offset to keep the selected cursor on screen by tracking the current selection and adjusting the viewport accordingly.
  • Bind the ESC key to close the picker by adding an event handler that listens for the ESC key press and closes the picker.
  • Modify the Enter handler to reset event.app.current_buffer after confirming a selection to clear the input bar.

Example

# Example of how to reset the current buffer in the Enter handler
def enter_handler(event):
    # ... existing code ...
    event.app.current_buffer.reset()
    # ... existing code ...

Notes

The proposed fix involves modifying the cli.py file, which may require careful testing to ensure that the changes do not introduce new issues. Additionally, the implementation details may vary depending on the specific requirements and constraints of the project.

Recommendation

Apply the proposed workaround by modifying the cli.py file to add a viewport helper, implement scrolling, bind the ESC key to close the picker, and reset the current buffer in the Enter handler, as this addresses the specific issues reported and provides a clear solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Bug]: /model picker doesn't scroll with long provider catalogs (Ollama Cloud, 36+ models) and leaves command in input after selection [2 pull requests, 1 participants]