feat: quiet events & fixed quiet detection#5
feat: quiet events & fixed quiet detection#5cryppadotta wants to merge 1 commit intonicobailon:mainfrom
Conversation
…on for TUI apps
Wire onHandsFreeUpdate in non-blocking code paths (attach and new
session) to broadcast updates via pi.events.emit("interactive-shell:update").
This lets other extensions (e.g. pi-drive) receive quiet/exit/takeover
notifications without polling.
Fix quiet detection for Ink-based TUI apps (e.g. Claude Code) that
emit periodic ANSI-only frames (cursor blink, redraws). These frames
previously reset the quiet timer on every PTY data event, preventing
quiet from ever being detected. Now uses stripVTControlCharacters()
to filter ANSI-only output — only visible content resets the timer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Cool! The core ideas here are good, but heads up that
No pressure to do any of this, I also don't mind taking it on directly. Thanks again! |
I'm working on a new pi plugin
pi-driver, that usespi-interactive-shell.I needed two things:
claudecode are actually quiet.Below is my Claude's summary:
PR: Emit hands-free update events + fix quiet detection for TUI apps
Title
feat: emit hands-free update events via pi.events + fix quiet detection for TUI appsSummary
Two small, focused changes that enable extensions to receive hands-free mode notifications and fix a bug where quiet detection never triggers for TUI-based sub-agents.
1. Emit
interactive-shell:updateevents viapi.events(index.ts)The
onHandsFreeUpdatecallback was already wired in the blocking code path but not in the two non-blocking paths (attach and new session). This means extensions running in hands-free mode withupdateMode: "on-quiet"had no way to receive quiet/exit/takeover notifications.This PR wires
onHandsFreeUpdatein both non-blocking paths to broadcast viapi.events.emit("interactive-shell:update", ...). The event payload is the sameHandsFreeUpdateshape that already exists intypes.ts.Use case: An outer-loop driver extension (like pi-drive) launches a sub-agent in hands-free mode and needs to know when it goes quiet so it can evaluate output and send follow-up prompts.
2. Content-based quiet detection filtering (overlay-component.ts)
Bug: TUI apps built with Ink (e.g. Claude Code) emit periodic ANSI-only PTY data — cursor blink sequences, frame redraws, status bar updates — even when the agent is idle and waiting for input. The existing
onDatahandler reset the quiet timer on every PTY data event regardless of content, so quiet was never detected.Fix: Use
stripVTControlCharacters()fromnode:utilto check if PTY data contains visible content. Only reset the quiet timer when there's actual visible output. ANSI-only frames (cursor repositioning, color codes, etc.) are ignored.This is a one-line behavioral change in the
onDatahandler. It doesn't affect dispatch mode or interval-based updates — only theon-quietupdate mode.Files changed
onHandsFreeUpdatein 2 non-blocking paths (+28 lines, 0 removed)stripVTControlCharactersimport, filter ANSI-only data inonData(+14 lines, -3 lines)Why it's safe to merge
onHandsFreeUpdatecallback andHandsFreeUpdatetype already exist — this just wires them in paths that were missing them.stripVTControlCharactersis from Node.js built-innode:util(stable since Node 16).updateMode === "on-quiet"in hands-free mode. Dispatch mode and interval-based updates are untouched.interactive-shell:updateare unaffected.