pub struct DurableSshController {
block_id: String,
broker: Option<Arc<Broker>>,
event_bus: Option<Arc<EventBus>>,
mstore: Option<Arc<Store>>,
filestore: Option<Arc<FileStore>>,
auth_key: String,
config: Option<Arc<ConfigState>>,
fallback: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
inner: Mutex<Inner>,
}Fields§
§block_id: String§broker: Option<Arc<Broker>>§event_bus: Option<Arc<EventBus>>§mstore: Option<Arc<Store>>§filestore: Option<Arc<FileStore>>§auth_key: Stringsrv’s auth key, for the askpass helper to reach srv with.
config: Option<Arc<ConfigState>>Settings, for whether the pane is still durable (wants).
fallback: Option<Arc<dyn Fn() -> bool + Send + Sync>>Restarts the pane as a plain SSH terminal, when the user declines the
helper (Fallback).
inner: Mutex<Inner>Implementations§
Source§impl DurableSshController
impl DurableSshController
pub fn new( block_id: String, broker: Option<Arc<Broker>>, event_bus: Option<Arc<EventBus>>, mstore: Option<Arc<Store>>, filestore: Option<Arc<FileStore>>, auth_key: String, config: Option<Arc<ConfigState>>, fallback: Option<Arc<dyn Fn() -> bool + Send + Sync>>, ) -> Self
fn snapshot(&self) -> BlockControllerRuntimeStatus
fn publish(&self)
Sourcefn session_id(&self, meta: &HashMap<String, Value>) -> String
fn session_id(&self, meta: &HashMap<String, Value>) -> String
The pane’s session id, made and recorded on first start.
fn write_block_meta(&self, key: &str, value: Value)
fn leave(&self, how: Leave)
Trait Implementations§
Source§impl Controller for DurableSshController
impl Controller for DurableSshController
Source§fn stop_for_replace(&self, new_status: &str) -> Result<(), String>
fn stop_for_replace(&self, new_status: &str) -> Result<(), String>
A forced restart or a connection change: detach, so the session is still there if this pane comes back to it.
Source§fn shutdown(
&self,
deadline: Instant,
) -> Pin<Box<dyn Future<Output = StopOutcome> + Send>>
fn shutdown( &self, deadline: Instant, ) -> Pin<Box<dyn Future<Output = StopOutcome> + Send>>
Pane close ends the session; AgentMux quitting detaches it. Waits for
the ssh to deliver that before the deadline.
Source§fn start(
&self,
block_meta: HashMap<String, Value>,
rt_opts: Option<Value>,
_force: bool,
) -> Result<(), String>
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>
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
fn get_runtime_status(&self) -> BlockControllerRuntimeStatus
Get the current runtime status.
Source§fn send_input(
&self,
input: BlockInputUnion,
_seq: Option<u64>,
) -> Result<(), String>
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
fn controller_type(&self) -> &str
Get the controller type (e.g., “shell”, “cmd”).
Source§fn agent_id(&self) -> Option<String>
fn agent_id(&self) -> Option<String>
This block’s own live, spawn-time-captured jekt/muxbus identity, if
it has one — an independent source of truth for the recipient-
identity check in
ReactiveHandler::inject_message_inner, deliberately
NOT derived from ReactiveHandler’s own name_to_blocks/agent_info
maps (checking a registry against itself would be a tautology and
catch nothing). Default None for controller types that aren’t
jekt-addressable at all (e.g. plain terminals) — only ShellController
and PersistentSubprocessController currently override this, mirroring
the two paths that already resolve a jekt-registration identity at
spawn time (resolve_agent_id_for_jekt, muxbus_agent_id_from_env).Source§fn turn_provenance(&self) -> Option<TurnProvenance>
fn turn_provenance(&self) -> Option<TurnProvenance>
What started this agent’s current turn (SPEC_AGENT_SELF_QUIT §6.3), if
the controller tracks it.
None = unknown, which never counts as the
user — the safe answer for controllers that can’t tell (ACP, App
Server, subprocess: both origins reach them through one method).Source§fn turn_tracker(&self) -> Option<Arc<TurnActivityTracker>>
fn turn_tracker(&self) -> Option<Arc<TurnActivityTracker>>
This controller’s turn tracker, for the turn ledger’s bookkeeping from
outside the controller (a held message’s join hint).
None for
controllers that track no turns.Source§fn set_agent_id(&self, _id: Option<String>)
fn set_agent_id(&self, _id: Option<String>)
Refresh this block’s own captured jekt/muxbus identity (see
agent_id’s doc comment). Called whenever
ReactiveHandler::register_agent/register_agent_with_nonce
(re-)registers THIS block’s block_id under a (possibly different)
agent_id, so the two independently-written copies never drift apart
(#2697: agent_id() was captured once at spawn and never
refreshed, while the registry’s name bindings get re-keyed on every
register_agent call — e.g. handle_reactive_register’s
frontend-initiated HTTP path — causing a legitimately renamed or
reconfigured agent’s own messages to be falsely rejected as an
identity mismatch). Default no-op for controller types that don’t
override agent_id either.Source§fn stable_agent_id(&self) -> Option<String>
fn stable_agent_id(&self) -> Option<String>
This block’s STABLE jekt identity —
AGENTMUX_AGENT_ID as captured
once at spawn, never refreshed. Distinct from agent_id,
which tracks the LIVE, renameable display name and is deliberately
refreshed every turn (see that method’s doc comment on #2697).
AGENTMUX_AGENT_ID is embedded verbatim in PR-body tags specifically
because it does NOT change if the agent is later renamed — but
ReactiveHandler’s registry only tracks one key per block, and
every turn’s agent_id() refresh evicts whatever this block was
previously registered under. ReactiveHandler::inject_message_inner’s
recipient-identity check (#2695) uses this alongside agent_id() so
a jekt addressed to the stable ID is validated correctly even after
the primary registry key has moved on to the live display name. See
INCIDENT_2026_09_09_JEKT_STABLE_ID_ALIAS.md. Default None,
mirroring agent_id’s default — only PersistentSubprocessController
currently overrides this.Source§fn stable_agent_uid(&self) -> Option<String>
fn stable_agent_uid(&self) -> Option<String>
Identity M2: this block’s UID (
db_agents.id) as carried in its
spawn env (AGENTMUX_AGENT_UID, set by build_persistent_spawn_env
since M1a), captured once at spawn like [stable_agent_id]. Backs the
registry’s UID confirmer: consulted only for targets that resolved by
UID, and None — a registered-but-not-yet-spawned controller, or a
block with no row — is “unverifiable”, not a mismatch. Default
None; only PersistentSubprocessController overrides this.Auto Trait Implementations§
impl !Freeze for DurableSshController
impl !RefUnwindSafe for DurableSshController
impl !UnwindSafe for DurableSshController
impl Send for DurableSshController
impl Sync for DurableSshController
impl Unpin for DurableSshController
impl UnsafeUnpin for DurableSshController
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
Mutably borrows from an owned value. Read more
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn 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>
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)
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)
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
impl<T> DowncastSync for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> 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> ⓘ
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 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> ⓘ
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