Skip to content

feat(tui): reveal matrix-rain words from real codex/claude PTY output - #47

Merged
edwin-zvs merged 2 commits into
mainfrom
matrix-rain-pty-reveals
May 19, 2026
Merged

edwin-zvs merged 2 commits into
mainfrom
matrix-rain-pty-reveals

Conversation

@edwin-zvs

@edwin-zvs edwin-zvs commented May 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Codex / claude in interactive mode (and shell) only emit SessionEvent::Pty while the agent is working — no ToolUse / Status for matrix_rain::word_for_event to map. Result before this PR: the rain stayed silent for them while zarvis revealed words.

Now MatrixRain::observe_pty_activity(session_id, bytes, now) harvests words from the live byte stream:

  • Skip ANSI escape sequences (CSI / OSC) inline, then collect ASCII-alpha runs of 4–12 chars into a per-session FIFO pool (cap 32). Oversize runs poison themselves so we don't surface trailing sub-words.
  • Drop exact consecutive duplicates so a "Thinking…" spinner can't flood the pool with one word.
  • On each per-session throttle tick (~1 reveal per 3.5s), pop the newest pooled word and queue it as the matrix reveal. Drain the rest so the next reveal reflects fresh activity.
  • Fall back to a small rotating word list (working / thinking / running / writing / reading / typing) only when the pool is empty (first chunk, or a quiet stretch with only escapes).
  • Throttle + pool both clear on SessionEvent::Reset and session removal so the maps stay bounded.

Test plan

  • cargo test -p agentd-cli --release — 107 unit + 1 integration pass; includes 11 new matrix-rain tests covering extraction (CSI/OSC strip, dedupe, length cap), pool cap, harvested-vs-fallback selection, throttle, cross-session independence, and session forget.
  • Run agent with a codex session and watch the matrix-rain pane reveal words pulled from codex's output (tool names, file stems, action verbs) every few seconds.
  • Same with a claude session.
  • Run a zarvis session in parallel — the richer Editing / Reading / Running words from word_for_event still appear (PTY harvesting only fires for PTY events; zarvis doesn't emit those).
  • Reset a session (M-x reset) and confirm the next PTY chunk seeds a fresh reveal without delay.

edwin-zvs added 2 commits May 18, 2026 17:13
PTY-only adapters (codex/claude interactive, shell) emit
SessionEvent::Pty bursts while the agent is working but no
ToolUse/Status — so the matrix rain stayed silent for them while
zarvis (which emits structured tool events) revealed words.

Add a per-session, ~3.5s rate-limited heartbeat on PTY events that
queues a rotating activity word ("working" / "thinking" / "running"
/ "writing" / "reading" / "typing"). Throttle state is cleared on
Reset and session removal so the map stays bounded.

Internally, route reveal queuing through queue_at/queue_random_at so
the throttle and the reveal share a single timestamp — without it,
tests that inject a deterministic `now` were racing the implicit
Instant::now() inside queue.
The first pass cycled a hard-coded list of generic activity words
("working", "thinking", ...) on a per-session timer. That signaled
"something is happening" but not *what* — codex's "Editing
src/main.rs" and claude's "Reading" looked identical to the matrix.

Now `observe_pty_activity` takes the PTY byte stream:

- Skip ANSI escape sequences (CSI + OSC), then harvest ASCII-alpha
  runs of 4–12 chars into a per-session FIFO pool (cap 32). Words
  longer than the cap poison their entire run so we don't surface
  trailing sub-words.
- Drop exact consecutive duplicates so a spinner that re-prints
  "Thinking" every frame doesn't dominate the pool.
- On each throttled reveal tick (≤ 1 / 3.5s per session), pop the
  newest pooled word and queue it as the matrix reveal text. Drain
  the rest so the next reveal reflects fresh activity.
- Fall back to the rotating generic words only when the pool is
  empty (very first chunk, or a quiet stretch with only escapes).

Throttle + pool both clear on `Reset` and session removal.
@edwin-zvs edwin-zvs changed the title feat(tui): reveal matrix-rain words for codex/claude PTY activity feat(tui): reveal matrix-rain words from real codex/claude PTY output May 19, 2026
@edwin-zvs
edwin-zvs merged commit d955d8c into main May 19, 2026
1 check passed
edwin-zvs added a commit that referenced this pull request May 19, 2026
Resolved conflicts:
  - crates/cli/src/ui.rs: took upstream's reveal-pin-on-real-drops algorithm
    (#47, #49) and reapplied the SessionEvent::ContextCompacted arms in
    format_event_body + short_event_label. Conflicts were only there
    because cargo fmt churn from this branch touched lines near the
    upstream rewrite.
  - crates/adapter-zarvis/src/provider/codex_oauth.rs: new provider
    introduced by #46 needed a Content::Summary arm matching the other
    providers — emits the SUMMARY_WIRE_PREFIX'd text as a user input
    message in the Responses-API shape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant