mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-09 03:11:58 +00:00
Adds a dedicated '## Windows-Specific Quirks' section to the hermes-agent skill so Windows pitfalls have one discoverable place to evolve. Inaugural entries cover: - Input / keybindings — Alt+Enter intercepted by Windows Terminal, Ctrl+Enter as the Windows newline keystroke, mintty/git-bash behavior, pointer to scripts/keystroke_diagnostic.py for investigation. - Config / files — UTF-8 BOM HTTP-400 trap. - execute_code / sandbox — WinError 10106 SYSTEMROOT root cause + _WINDOWS_ESSENTIAL_ENV_VARS fix location. - Testing / contributing — scripts/run_tests.sh POSIX-venv limitation and the system-Python workaround, POSIX-only test skip-guard patterns. - Path / filesystem — line-ending warnings (cosmetic), forward-slash portability. Collapses the old scattered Windows bullets under 'Platform-specific issues' into a single pointer at the new dedicated section so there's only one place to maintain this content. Also adds the scripts/keystroke_diagnostic.py the skill now references — a small prompt_toolkit Application that prints the Keys.* identifier and raw escape bytes for every keystroke. Used to establish the Ctrl+Enter = c-j fact on Windows Terminal; generally useful for anyone adding a platform-aware keybinding.
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Diagnose how prompt_toolkit identifies keystrokes in the current terminal.
|
|
|
|
Useful when adding a keybinding to Hermes (or any prompt_toolkit app) and you
|
|
need to know what the terminal actually delivers — particularly on Windows,
|
|
where terminals can collapse, intercept, or silently remap key combinations.
|
|
|
|
Usage:
|
|
# POSIX
|
|
python scripts/keystroke_diagnostic.py
|
|
|
|
# Windows (PowerShell / git-bash / cmd)
|
|
python scripts\\keystroke_diagnostic.py
|
|
|
|
Press the key combinations you care about. Each keystroke prints the
|
|
prompt_toolkit `Keys.*` identifier and the raw escape bytes the terminal
|
|
sent. The last 20 keystrokes stay on screen. Ctrl+Q or Ctrl+C to quit.
|
|
|
|
Common questions this answers:
|
|
- Does my terminal distinguish Ctrl+Enter from plain Enter?
|
|
(On Windows Terminal: yes, Ctrl+Enter → c-j, Enter → c-m.)
|
|
- Does Alt+Enter reach the app, or does the terminal eat it?
|
|
(Windows Terminal eats it for fullscreen; mintty may too.)
|
|
- Does Shift+Enter register as a separate key?
|
|
(Almost never — most terminals collapse it to Enter.)
|
|
- What byte sequence does Home/End/PageUp/etc. produce?
|
|
|
|
Example output for Ctrl+Enter on Windows Terminal + PowerShell:
|
|
key=<Keys.ControlJ: 'c-j'> data='\\n'
|
|
|
|
Then in Hermes, bind the newline behaviour to that key:
|
|
@kb.add('c-j')
|
|
def handle_ctrl_enter(event):
|
|
event.current_buffer.insert_text('\\n')
|
|
"""
|
|
from prompt_toolkit import Application
|
|
from prompt_toolkit.key_binding import KeyBindings
|
|
from prompt_toolkit.layout import Layout
|
|
from prompt_toolkit.layout.containers import Window
|
|
from prompt_toolkit.layout.controls import FormattedTextControl
|
|
|
|
|
|
_HISTORY: list[str] = []
|
|
|
|
|
|
def _header() -> list[str]:
|
|
return [
|
|
"Keystroke diagnostic — press keys to see how prompt_toolkit sees them.",
|
|
"Try: Enter, Ctrl+Enter, Shift+Enter, Alt+Enter, Ctrl+J, Ctrl+M, arrows, Home/End.",
|
|
"Ctrl+Q or Ctrl+C to quit. Last 20 keystrokes shown.",
|
|
"",
|
|
]
|
|
|
|
|
|
def _render_text() -> str:
|
|
return "\n".join(_header() + _HISTORY[-20:])
|
|
|
|
|
|
def main() -> None:
|
|
kb = KeyBindings()
|
|
|
|
@kb.add("<any>")
|
|
def _on_any(event): # noqa: ANN001 — prompt_toolkit event type
|
|
parts = []
|
|
for kp in event.key_sequence:
|
|
parts.append(f"key={kp.key!r} data={kp.data!r}")
|
|
_HISTORY.append(" | ".join(parts))
|
|
event.app.invalidate()
|
|
|
|
@kb.add("c-q")
|
|
@kb.add("c-c")
|
|
def _quit(event): # noqa: ANN001
|
|
event.app.exit()
|
|
|
|
control = FormattedTextControl(text=_render_text)
|
|
layout = Layout(Window(content=control))
|
|
Application(layout=layout, key_bindings=kb, full_screen=False).run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|