ShellController

Struct ShellController 

Source
pub struct ShellController {
    controller_type: String,
    tab_id: String,
    block_id: String,
    run_lock: Arc<AtomicBool>,
    inner: Arc<Mutex<ShellControllerInner>>,
    conn_factory: Mutex<Option<Box<dyn Fn(&str, &HashMap<String, Value>) -> Result<Box<dyn ConnInterface>, String> + Send + Sync>>>,
    broker: Option<Arc<Broker>>,
    event_bus: Option<Arc<EventBus>>,
    wstore: Option<Arc<Store>>,
}
Expand description

ShellController manages one shell or command block.

Fields§

§controller_type: String

Controller type: “shell” or “cmd”.

§tab_id: String§block_id: String§run_lock: Arc<AtomicBool>

Prevents concurrent run() calls.

§inner: Arc<Mutex<ShellControllerInner>>

Protected inner state.

§conn_factory: Mutex<Option<Box<dyn Fn(&str, &HashMap<String, Value>) -> Result<Box<dyn ConnInterface>, String> + Send + Sync>>>

Optional factory for creating ConnInterface (for testing).

§broker: Option<Arc<Broker>>

WPS broker for publishing events (blockfile, controllerstatus).

§event_bus: Option<Arc<EventBus>>

Event bus (unused for now, reserved for future event routing).

§wstore: Option<Arc<Store>>

Wave object store — used to seed cmd:cwd on shell spawn.

Implementations§

Source§

impl ShellController

Source

pub fn new( controller_type: String, tab_id: String, block_id: String, broker: Option<Arc<Broker>>, event_bus: Option<Arc<EventBus>>, wstore: Option<Arc<Store>>, ) -> Self

Create a new ShellController.

Source

pub fn set_conn_factory( &self, factory: Box<dyn Fn(&str, &HashMap<String, Value>) -> Result<Box<dyn ConnInterface>, String> + Send + Sync>, )

Set a custom ConnInterface factory (for testing).

Source

fn try_lock_run(&self) -> bool

Try to acquire the run lock. Returns false if already running.

Source

fn unlock_run(&self)

Release the run lock.

Source

fn set_status(inner: &mut ShellControllerInner, status: &str)

Update process status and increment version (must hold inner lock).

Source

fn get_status_snapshot(&self) -> BlockControllerRuntimeStatus

Get the runtime status (snapshot).

Source

pub fn last_output_secs_ago(&self) -> Option<u64>

Seconds since last PTY output, or None if no output yet.

Source

pub fn is_agent_pane(&self) -> bool

True if this pane is running an agent CLI.

Source

fn should_run_on_start(meta: &HashMap<String, Value>) -> bool

Check block meta for whether to run on start.

Source

fn should_run_once(meta: &HashMap<String, Value>) -> bool

Check block meta for run-once mode (used in full lifecycle integration).

Source

fn should_clear_on_start(meta: &HashMap<String, Value>) -> bool

Check block meta for clear-on-start (used in full lifecycle integration).

Source

fn should_close_on_exit(meta: &HashMap<String, Value>) -> bool

Check block meta for close-on-exit (used in full lifecycle integration).

Source

fn should_close_on_exit_force(meta: &HashMap<String, Value>) -> bool

Check block meta for force close-on-exit (used in full lifecycle integration).

Source

fn close_on_exit_delay_ms(meta: &HashMap<String, Value>) -> u64

Get the close-on-exit delay in ms (defaults to 2000, used in full lifecycle integration).

Source

fn get_conn_name(meta: &HashMap<String, Value>) -> String

Get the connection name from block meta.

Source

fn get_cmd_str(meta: &HashMap<String, Value>) -> String

Get the command string from block meta.

Source

fn get_cmd_args(meta: &HashMap<String, Value>) -> Vec<String>

Get cmd:args array from block meta.

Source

fn is_interactive(meta: &HashMap<String, Value>) -> bool

Check if cmd:interactive is set in block meta.

Source

fn publish_status(&self)

Publish current controller status via the WPS broker.

Source

fn pty_size_from_rt_opts(rt_opts: &Option<Value>) -> PtySize

Resolve the initial PTY geometry from the resync rt_opts payload.

The agent pane is a custom UI (not xterm.js), so the PTY never receives a fitAddon resize and must be born at the right width — otherwise the first batch of agent/tool output wraps at the fallback width until a post-spawn resize RPC lands, and that RPC races controller startup (it can fail outright). The frontend computes cols from the pane and passes them as rtopts.termsize on the controllerresync command (see usePtyWidth.ts / launch-flow.ts).

Falls back to the historical 25x200 default when rt_opts is absent, unparseable, or carries the serde-default termsize (rows==0 && cols==0, per obj::is_default_term_size). Per-field guards let a cols-only payload keep the default row count. Each axis is clamped to [1, 1000] so the i64 → u16 cast is lossless and a bogus value cannot open a zero-size or wrapped-size PTY. See docs/analysis/AGENT_PANE_PTY_RESIZE_RACE_2026_06_16.md.

Trait Implementations§

Source§

impl Controller for ShellController

Source§

fn start( &self, block_meta: HashMap<String, Value>, rt_opts: Option<Value>, force: bool, ) -> Result<(), String>

Start the controller. May spawn background tasks. force restarts even if already running.
Source§

fn stop(&self, _graceful: bool, new_status: &str) -> Result<(), String>

Stop the controller. graceful waits for process to exit; new_status is the target state.
Source§

fn get_runtime_status(&self) -> BlockControllerRuntimeStatus

Get the current runtime status.
Source§

fn send_input( &self, input: BlockInputUnion, seq: Option<u64>, ) -> Result<(), String>

Send input (terminal data, signal, or resize) to the controller. seq is the per-TermViewModel monotonic counter; None means fire-and-forget (no ordering).
Source§

fn controller_type(&self) -> &str

Get the controller type (e.g., “shell”, “cmd”).
Source§

fn block_id(&self) -> &str

Get the block ID.
Source§

fn as_any(&self) -> &dyn Any

Downcast support for concrete controller types.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,