mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-14 04:02:26 +00:00
fix(cli): sanitize bracketed paste markers during setup
Strip bracketed-paste control sequences from setup prompt input so pasted API keys work on Linux and WSL terminals, and add regression tests for normal/password prompts. Closes #16491
This commit is contained in:
parent
8ebb81fd76
commit
02147cc850
2 changed files with 35 additions and 1 deletions
|
|
@ -15,6 +15,7 @@ import importlib.util
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
@ -208,12 +209,23 @@ def prompt(question: str, default: str = None, password: bool = False) -> str:
|
||||||
else:
|
else:
|
||||||
value = input(color(display, Colors.YELLOW))
|
value = input(color(display, Colors.YELLOW))
|
||||||
|
|
||||||
return value.strip() or default or ""
|
cleaned = _sanitize_pasted_input(value)
|
||||||
|
return cleaned.strip() or default or ""
|
||||||
except (KeyboardInterrupt, EOFError):
|
except (KeyboardInterrupt, EOFError):
|
||||||
print()
|
print()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
_BRACKETED_PASTE_PATTERN = re.compile(r"\x1b\[\s*200~|\x1b\[\s*201~")
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_pasted_input(value: str) -> str:
|
||||||
|
"""Strip terminal bracketed-paste control markers from pasted text."""
|
||||||
|
if not isinstance(value, str) or not value:
|
||||||
|
return value
|
||||||
|
return _BRACKETED_PASTE_PATTERN.sub("", value)
|
||||||
|
|
||||||
|
|
||||||
def _curses_prompt_choice(question: str, choices: list, default: int = 0, description: str | None = None) -> int:
|
def _curses_prompt_choice(question: str, choices: list, default: int = 0, description: str | None = None) -> int:
|
||||||
"""Single-select menu using curses. Delegates to curses_radiolist."""
|
"""Single-select menu using curses. Delegates to curses_radiolist."""
|
||||||
from hermes_cli.curses_ui import curses_radiolist
|
from hermes_cli.curses_ui import curses_radiolist
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,28 @@
|
||||||
from hermes_cli import setup as setup_mod
|
from hermes_cli import setup as setup_mod
|
||||||
|
|
||||||
|
|
||||||
|
def test_prompt_strips_bracketed_paste_markers(monkeypatch):
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"builtins.input",
|
||||||
|
lambda _prompt="": "\x1b[200~sk-ant-api-key\x1b[201~",
|
||||||
|
)
|
||||||
|
|
||||||
|
value = setup_mod.prompt("API key")
|
||||||
|
|
||||||
|
assert value == "sk-ant-api-key"
|
||||||
|
|
||||||
|
|
||||||
|
def test_password_prompt_strips_bracketed_paste_markers(monkeypatch):
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"getpass.getpass",
|
||||||
|
lambda _prompt="": "\x1b[200~secret-token\x1b[201~",
|
||||||
|
)
|
||||||
|
|
||||||
|
value = setup_mod.prompt("API key", password=True)
|
||||||
|
|
||||||
|
assert value == "secret-token"
|
||||||
|
|
||||||
|
|
||||||
def test_prompt_choice_uses_curses_helper(monkeypatch):
|
def test_prompt_choice_uses_curses_helper(monkeypatch):
|
||||||
monkeypatch.setattr(setup_mod, "_curses_prompt_choice", lambda question, choices, default=0, description=None: 1)
|
monkeypatch.setattr(setup_mod, "_curses_prompt_choice", lambda question, choices, default=0, description=None: 1)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue