pub struct PtyShell {
pub last_command: String,
pub output_buffer: String,
pub command_running: bool,
pub output_truncated: bool,
pub last_returned_hash: Option<u64>,
pub attach_hint: Option<String>,
/* private fields */
}Expand description
Real PTY-based interactive shell
Uses portable-pty for true pseudo-terminal functionality, enabling proper handling of interactive programs like sudo, vim, etc.
Fields§
§last_command: StringLast command executed
output_buffer: StringAccumulated output buffer
command_running: boolWhether a command is currently running
output_truncated: boolFlag for output truncation
last_returned_hash: Option<u64>Hash of the last rendered output we shipped to the caller. Used by the
delta path in status_check to elide repeats when the screen is idle.
attach_hint: Option<String>Optional command a human can run to attach to the same terminal session.
Implementations§
Source§impl PtyShell
impl PtyShell
Sourcepub fn clear_to_run(&mut self, max_wait_secs: f32) -> Result<bool>
pub fn clear_to_run(&mut self, max_wait_secs: f32) -> Result<bool>
Drain any pending output and, if a previous command still seems to be
running, send a Ctrl-C to flush it. Mirrors wcgw’s clear_to_run so a
new command never inherits stale prompt fragments or a half-typed line.
Returns true if the shell looks idle (prompt seen), false if it
still wouldn’t yield after the Ctrl-C — caller may want to reset.
Sourcepub fn send_command(&mut self, command: &str) -> Result<()>
pub fn send_command(&mut self, command: &str) -> Result<()>
Send a command to the shell and start reading output
Sourcepub fn collect_scrollback(&self, lines: usize) -> String
pub fn collect_scrollback(&self, lines: usize) -> String
Return up to lines recent lines from the scrollback ring, oldest
first. When older lines were evicted or a long unterminated line was
clipped, a [winx: …] notice is prepended so the caller knows the
scrollback is incomplete rather than silently receiving less than asked.
Sourcepub fn fingerprint(text: &str) -> u64
pub fn fingerprint(text: &str) -> u64
Hash arbitrary rendered output into a u64 dedup key.
Sourcepub fn read_output(&mut self, timeout_secs: f32) -> Result<(String, bool)>
pub fn read_output(&mut self, timeout_secs: f32) -> Result<(String, bool)>
Read output from the PTY with timeout
Returns (output, is_complete) tuple where is_complete indicates
whether the command has finished (prompt detected)
Sourcepub fn poll_output_nonblocking(&mut self) -> bool
pub fn poll_output_nonblocking(&mut self) -> bool
Non-blocking drain of whatever the reader thread has already queued.
Unlike read_output, this never sleeps: it consumes
every chunk currently available, updates prompt/completion state, and
returns immediately. prune_finished_shells uses it so the global
background-shell lock is never held across a blocking 100ms read_output.
Returns true if the command has completed (prompt seen or PTY closed).
Sourcepub fn send_interrupt(&mut self) -> Result<()>
pub fn send_interrupt(&mut self) -> Result<()>
Send Ctrl+C (interrupt) to the PTY
Sourcepub fn send_suspend(&mut self) -> Result<()>
pub fn send_suspend(&mut self) -> Result<()>
Send Ctrl+Z (suspend) to the PTY
Sourcepub fn send_text(&mut self, text: &str) -> Result<()>
pub fn send_text(&mut self, text: &str) -> Result<()>
Send text directly to the PTY (for interactive input)
Sourcepub fn send_bytes(&mut self, bytes: &[u8]) -> Result<()>
pub fn send_bytes(&mut self, bytes: &[u8]) -> Result<()>
Send raw bytes directly to the PTY.
Sourcepub fn send_special_key(&mut self, key: &str) -> Result<()>
pub fn send_special_key(&mut self, key: &str) -> Result<()>
Send a special key sequence
Sourcepub fn live_snapshot(&self, max_lines: usize) -> Vec<String>
pub fn live_snapshot(&self, max_lines: usize) -> Vec<String>
Snapshot the live terminal screen — a stable, consolidated view of what a
human would currently see, with cursor moves/redraws applied and ANSI
stripped. max_lines of 0 returns the full screen buffer. This is the
foundation for piloting interactive TUIs (the claude CLI, vim, …).
Sourcepub fn live_in_alt_screen(&self) -> bool
pub fn live_in_alt_screen(&self) -> bool
Whether the live terminal is currently on the alternate screen buffer (a full-screen app like vim/htop/less is running).
Sourcepub fn live_cursor_position(&self) -> (u16, u16)
pub fn live_cursor_position(&self) -> (u16, u16)
Cursor position (row, col) on the live screen (0-based), so a piloting
agent knows where focus is in a menu/form. (0, 0) if the lock is poisoned.
Sourcepub fn live_snapshot_diff(
&self,
max_lines: usize,
threshold: usize,
) -> ScreenUpdate
pub fn live_snapshot_diff( &self, max_lines: usize, threshold: usize, ) -> ScreenUpdate
Diff the live screen against what the client last saw, returning only the
changed lines when the change is small (huge token savings over many
polls). Updates the baseline as a side effect. See ScreenUpdate.
Trait Implementations§
Source§impl Drop for PtyShell
impl Drop for PtyShell
Source§fn drop(&mut self)
fn drop(&mut self)
Kill and reap the shell child so it doesn’t leak.
std::process::Child::drop neither kills nor waits, so without this every
dropped shell (reset_shell, background-shell prune/remove) would leak a
live bash process — soon a zombie — plus the reader thread blocked in
read(). Killing the child closes the PTY slave, which makes the reader’s
read() return EOF so the thread terminates on its own. Best-effort.
Auto Trait Implementations§
impl !RefUnwindSafe for PtyShell
impl !Sync for PtyShell
impl !UnwindSafe for PtyShell
impl Freeze for PtyShell
impl Send for PtyShell
impl Unpin for PtyShell
impl UnsafeUnpin for PtyShell
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more