From b9949fff489e2c226775cd3b581cef27e189a1ee Mon Sep 17 00:00:00 2001 From: Tranquil-Flow Date: Sat, 25 Apr 2026 09:50:21 +1000 Subject: [PATCH] fix(cli): prevent trailing space in picker-command completions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commands that open pickers (/model, /skin, /personality) must not receive a trailing space from the completion handler. The TUI's submit handler applies pending completions on Enter — adding a space makes the input differ from the original, blocking picker execution. Supersedes #15339. --- hermes_cli/commands.py | 16 +++++++++++++++- tests/hermes_cli/test_commands.py | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/hermes_cli/commands.py b/hermes_cli/commands.py index efff57180..48b2c104f 100644 --- a/hermes_cli/commands.py +++ b/hermes_cli/commands.py @@ -865,6 +865,12 @@ class SlashCommandCompleter(Completer): except Exception: return {} + # Commands that open pickers when run without arguments. + # These should NOT receive a trailing space in completions because + # the TUI's submit handler applies completions on Enter if input differs, + # which blocks picker execution. + _PICKER_COMMANDS = frozenset({"model", "skin", "personality"}) + @staticmethod def _completion_text(cmd_name: str, word: str) -> str: """Return replacement text for a completion. @@ -873,8 +879,16 @@ class SlashCommandCompleter(Completer): returning ``help`` would be a no-op and prompt_toolkit suppresses the menu. Appending a trailing space keeps the dropdown visible and makes backspacing retrigger it naturally. + + However, commands that open pickers (model, skin, personality) should + NOT get a trailing space — the TUI would apply the completion on Enter + and block the picker from opening. """ - return f"{cmd_name} " if cmd_name == word else cmd_name + if cmd_name != word: + return cmd_name + if cmd_name in SlashCommandCompleter._PICKER_COMMANDS: + return cmd_name + return f"{cmd_name} " @staticmethod def _extract_path_word(text: str) -> str | None: diff --git a/tests/hermes_cli/test_commands.py b/tests/hermes_cli/test_commands.py index d77a076eb..499c62874 100644 --- a/tests/hermes_cli/test_commands.py +++ b/tests/hermes_cli/test_commands.py @@ -359,6 +359,23 @@ class TestSlashCommandCompleter: assert [item.text for item in completions] == ["help"] + # -- picker commands must NOT get trailing space --------------------- + + def test_picker_commands_no_trailing_space(self): + """Picker commands (/model, /skin, /personality) must not get trailing space.""" + for cmd in ("model", "skin", "personality"): + result = SlashCommandCompleter._completion_text(cmd, cmd) + assert result == cmd, f"/{cmd} should not have trailing space" + + def test_non_picker_exact_match_gets_trailing_space(self): + """Regular commands like /help should still get trailing space on exact match.""" + assert SlashCommandCompleter._completion_text("help", "help") == "help " + + def test_partial_match_never_has_trailing_space_for_picker(self): + """Partial matches should never have trailing space regardless of command type.""" + assert SlashCommandCompleter._completion_text("model", "mo") == "model" + assert SlashCommandCompleter._completion_text("help", "he") == "help" + # -- non-slash input returns nothing --------------------------------- def test_no_completions_for_non_slash_input(self):