mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-09 03:11:58 +00:00
docs: add Windows-Specific Quirks section to hermes-agent skill + keystroke diagnostic
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.
This commit is contained in:
parent
d1838041e5
commit
b63f9645f0
2 changed files with 210 additions and 1 deletions
81
scripts/keystroke_diagnostic.py
Normal file
81
scripts/keystroke_diagnostic.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#!/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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue