feat(agent-manager): add WezTerm terminal support#128
Conversation
b86156c to
38ffcda
Compare
|
Updated per review feedback. New HEAD: `38ffcda` (force-pushed, single amended commit). Changes addressing the three review notes:
Validation (fresh):
Not merging. |
38ffcda to
1e3fc77
Compare
|
Updated per the WezTerm send-behavior feedback. New HEAD: `1e3fc77` (force-pushed, single amended commit). `TtyWriter.sendViaWezterm` now makes two explicit CLI calls (no stdin):
The user message is never built into a shell command or a shell string. Code: removed the previous stdin-based `ExecFileInputOptions` workaround entirely (net simplification); added a `CARRIAGE_RETURN = '\x0d'` constant. Tests added/updated (`TtyWriter.test.ts`):
Validation (fresh): `agent-manager` + `cli` `tsc --noEmit` clean; `eslint` 0 errors; pre-commit hook `nx run-many -t lint test` green — agent-manager 444, cli 843. Docs (design/implementation/testing) updated to describe the two-call, argv, CR-byte send. Not merging. |
Discover, focus, and type into the WezTerm pane that hosts a running
agent, alongside the existing tmux / iTerm2 / Terminal.app flows.
- TerminalFocusManager: add WEZTERM type; discover the owning pane from
`wezterm cli list --format json` by matching the agent TTY against the
JSON entry's `tty_name` field; focus via `wezterm cli activate-pane
--pane-id`. Tried after tmux and before the macOS-only AppleScript
probes, so non-macOS hosts short-circuit.
- TtyWriter: send via two explicit `wezterm cli send-text --pane-id` calls
150ms apart — (1) the message as a positional argv element, then (2)
Enter as a single carriage return byte (0x0d) with --no-paste. Both are
discrete argv elements via execFile (no shell), so bytes are delivered
verbatim regardless of shell metacharacters (injection-safe). The
equivalent shell command for Enter is:
wezterm cli send-text --pane-id <id> --no-paste $'\x0d'
(ANSI-C dollar-single-quoted CR; execFile passes the actual CR byte).
- TerminalFocusManager accepts an optional debug logger; `agent open
--debug` wires it to the ai-devkit:terminal logger so users can inspect
the matching/focus decision path.
- Control is CLI-only (no AppleScript), so it works cross-platform.
Missing/failed wezterm degrades like the tmux probe (null/false).
No other CLI changes: agent send and channel bridges pick up WezTerm
through the existing abstract findTerminal/focusTerminal/TtyWriter.send
API. Spawning agents into WezTerm remains out of scope (TmuxManager).
Validation: agent-manager + cli tsc/eslint clean; vitest 444 (agent-manager)
and 843 (cli) / monorepo pass; WezTerm send/focus/debug branches covered
incl. argv-injection-safety and CR-byte (0x0d) assertions.
1e3fc77 to
f8e8b65
Compare
|
Notation corrected per review. New HEAD: `f8e8b65` (force-pushed, single amended commit). Fix: wherever the shell form of the Enter command is written, it now uses dollar-single-quoted CR — `$'\x0d'` with the leading `$` — i.e. ``` Implementation is unchanged and still correct: `execFile` passes the actual CR byte as an argv element (JS `'\x0d'` = char `0x0d`), as the review confirmed it should. The distinction is now explicit everywhere:
Corrected in: `design`, `implementation`, `testing` docs, and the `TtyWriter.ts` + `TtyWriter.test.ts` comments. A grep confirms every shell-command occurrence uses `$'\x0d'`; remaining bare `'\x0d'` are only JS-source argv values (the constant `CARRIAGE_RETURN = '\x0d'`, the argv assertion, and prose explicitly labelled "JS char"). (I considered adding a unit test that asserts the shell-form string, but it would only check a constant defined in the test itself — a tautology. The behavioral test already pins the real contract: the Enter argv element is exactly char code `0x0d`, which is what `$'\x0d'` denotes.) Validation (fresh): pre-commit hook `nx run-many -t lint test` green — agent-manager 444, cli 843; `tsc --noEmit` clean; `eslint` 0 errors; `lint --feature wezterm-support` passes. Not merging. |
Summary
Adds support for discovering, focusing, and sending input to agents running inside WezTerm, alongside the existing tmux / iTerm2 / Terminal.app flows.
TerminalFocusManager: newWEZTERMterminal type. Discovers the owning WezTerm pane fromwezterm cli list --format jsonby matching the agent PID's TTY → pane id; focuses viawezterm cli focus-pane --pane-id. Probed after tmux, before the macOS AppleScript probes, so non-macOS hosts short-circuit cleanly (tmux-inside-WezTerm still resolves to tmux).TtyWriter: sends text viawezterm cli send-text --pane-idover the child stdin (text, then Enter, 150 ms apart) — the same two-step convention used for the other emulators so a bracketed-paste-aware TUI still sees Enter as a submit.null/false), so non-WezTerm users are unaffected.agent open,agent send, and channel bridges pick up WezTerm automatically through the existingfindTerminal/focusTerminal/TtyWriter.sendabstract API.Out of scope (deliberate): spawning new agents into WezTerm (that remains
TmuxManager's responsibility).