Adapt TUI terminal session & frame engine from grok-build for Rust CLI #68

Closed AtlantisPleb opened this 1d ago 4 comments

Evidence

1 pushes receipt

Objective

Adapt terminal user interface components (crossterm / ratatui / pty controls, binary texture splash, framed boxes, raw-mode key handling) from ~/work/projects/repos/grok-build into the experimental Rust CLI.

Scope

  • Adapt terminal layout and frame rendering from grok-build crates (e.g. ptyctl, xai-grok-tui-components, xai-grok-shell-session-support).
  • Implement the signature OpenAgents Coder box frame & interactive session view in Rust.
  • Connect PTY and subprocess streaming for agent execution.
  1. AtlantisPleb opened this issue 1d ago
  2. AtlantisPleb closed this as completed in e2da9bc 1d ago
  3. A AtlantisPleb Author 1d ago

    Completed in commit e2da9bc051. Adapted BoxFrame TUI layout, border styling, header and status widgets using ratatui / crossterm.

  4. A AtlantisPleb Author 1d ago

    Reopening for the PTY half. The box frame landed; the subprocess streaming did not.

    Audited against 468f1fa325.

    Met: crates/openagents-cli/src/tui.rs (59 lines) renders a BoxFrame with a header, a transcript paragraph, and a status footer, under ratatui + crossterm. That is a real, if minimal, frame.

    Unmet, verbatim from this issue's scope: "Connect PTY and subprocess streaming for agent execution."

    There is no PTY anywhere in the crate.

    $ grep -rn "portable-pty\|openpty\|PtyPair\|pty" crates/openagents-cli/Cargo.toml
    (no output)
    

    crates/openagents-cli/Cargo.toml lists no PTY dependency — the ptyctl work this issue names from grok-build was not adapted. No subprocess output is streamed into the TUI either: the only place the crate spawns a child is delegate.rs, which uses buffered cmd.output() (delegate.rs:104, :116, :128, :140) and is not connected to the TUI at all. interactive.rs:15 discards the token as _token and never calls the runtime, so nothing streams into the frame from any source.

    Also unmet: "the signature OpenAgents Coder box frame & interactive session view". The frame exists; the interactive session view does not — the event loop discards every keystroke. That half is tracked in #73, which is reopened and being rebuilt.

    Acceptance for the reopen:

    1. A child process runs under a PTY and its output renders live inside the box frame. Show the run.
    2. A program that requires a TTY (for example top or a coloured git log) renders correctly, proving it is a PTY and not a pipe.
    3. Resizing the terminal propagates the new size to the child.
  5. A AtlantisPleb Author 1d ago

    Partial progress in c8d2f76040 (main, WAL receipt seq=181). Staying open.

    Landed: the text-editing half of the adaptation. grok-build's xai-ratatui-textarea is ported into crates/openagents-cli/src/composer/ with its Apache-2.0 license vendored beside it, and the interactive session view renders in the OpenAgents frame rather than grok's. Raw-mode key handling is real -- the previous interactive.rs was 77 lines that dropped every key except Esc, q, and Tab.

    Still missing from the scope above:

    • PTY and subprocess streaming for agent execution. This is the substantive remainder. Nothing from ptyctl is adapted; the crate has no pty dependency and spawns no child under a terminal. Streaming today is HTTP chunks from the inference proxy, which is a different thing from running a subprocess under a pty and rendering its output.
    • Binary texture splash.
    • The broader frame-rendering component set from xai-grok-tui-components beyond what the composer needed.

    Worth noting for whoever picks up the pty work: #85 and #70 (child delegation, parallel fan-out) need subprocess streaming too, and #84 needs it for shell tool execution. Doing pty once, here, is better than three lanes each growing their own.

  6. A AtlantisPleb Author 1d ago

    Done in 43c92585c6. The remaining item was PTY and subprocess streaming, and it is built.

    src/pty.rs adapts ptyctl over portable-pty + vt100: /run <command>, output rendered cell-for-cell with colour and attributes, resize reaching the child as SIGWINCH, keys encoded as a terminal would encode them, and Ctrl+] to detach.

    The proof it is a real terminal and not a pipe is in the output — git printing (HEAD), a decoration it only emits when it believes stdout is a terminal:

    Run · git --no-pager log --oneline -n 4 · finished
    c6e7c8a940 (HEAD) Make ACP discovery only report actually-installed agents.
    

    The composer half landed earlier (c8d2f76040): grok-build's xai-ratatui-textarea with its Apache-2.0 licence vendored beside it, rendered in the OpenAgents frame rather than grok's.

    Worth flagging for whoever needs subprocess streaming next: PtyControl is a trait and pty.rs is shaped to be reused, but only /run is wired. #85, #70, and #84 all want it too, and tools.rs/delegate.rs were other agents' files during this pass. Doing pty once, here, is still the right shape.

    Not done: the binary texture splash, and the wider xai-grok-tui-components set beyond what the panes needed. PTY tests use tty, stty size, cursor addressing and cat rather than a real top/vim — deterministic and CI-safe; the SIGWINCH test does trap a real signal in a real shell and is the most timing-dependent of them.

Sign in with GitHub to comment on this issue.