Skip to main content

HostExtensionRunner

Struct HostExtensionRunner 

Source
pub struct HostExtensionRunner { /* private fields */ }
Expand description

Product extension runner backed by a live pi-ext HostClient.

Construct with HostExtensionRunner::start (resolve + spawn) or HostExtensionRunner::connect (pre-built client, used by tests and the reload restart closure). All ExtensionRunner hooks send a single event request and trust only the validated typed response; the host owns the 15-hook merge. Host failures are isolated as a single non-retryable extension_error and never abort the session.

Implementations§

Source§

impl HostExtensionRunner

Source

pub async fn start( extension_paths: Vec<String>, ) -> Result<Arc<Self>, HostStartError>

Resolve, spawn, handshake, and load the host, returning a ready runner.

§Errors

Returns HostStartError::Resolve when no host executable is available, HostStartError::Spawn when the process cannot start, HostStartError::Handshake on version mismatch, or HostStartError::Load when the registration snapshot is unreadable.

Source

pub async fn spawn_from( spec: &HostSpec, extension_paths: Vec<String>, ) -> Result<Arc<Self>, HostStartError>

Spawn from an explicit HostSpec, then bind.

§Errors

See HostExtensionRunner::start.

Source

pub async fn connect( client: Arc<HostClient>, extension_paths: Vec<String>, ) -> Result<Arc<Self>, HostStartError>

Bind a runner to a pre-built client: handshake, load, spawn the event pump. Used by start, the reload restart path, and the fake-host test harness.

§Errors

Returns HostStartError::Handshake or HostStartError::Load.

Source

pub async fn connect_with_timeout( client: Arc<HostClient>, extension_paths: Vec<String>, hook_timeout: Duration, ) -> Result<Arc<Self>, HostStartError>

Bind a runner with a custom hook timeout (test harness; production uses connect which applies HOOK_TIMEOUT).

§Errors

Returns HostStartError::Handshake or HostStartError::Load.

Source

pub async fn connect_with_cwd( client: Arc<HostClient>, extension_paths: Vec<String>, load_cwd: impl Into<String>, hook_timeout: Duration, ) -> Result<Arc<Self>, HostStartError>

Bind a runner with an explicit load cwd (services factory / tests).

§Errors

Returns HostStartError::Handshake or HostStartError::Load.

Source

pub async fn connect_with_cwd_and_trust( client: Arc<HostClient>, extension_paths: Vec<String>, load_cwd: impl Into<String>, project_trusted: bool, hook_timeout: Duration, ) -> Result<Arc<Self>, HostStartError>

Bind a runner with an explicit load cwd and project-trust value.

§Errors

Returns HostStartError::Handshake or HostStartError::Load.

Source

pub fn client(&self) -> &Arc<HostClient>

Borrowed host client (for provider registration by the model runtime).

Source

pub fn extension_paths(&self) -> Vec<String>

Extension paths used for the current host load.

Source

pub fn load_errors(&self) -> Vec<(String, String)>

Host-reported per-path load errors from the latest snapshot.

Source

pub fn provider_configs(&self) -> HashMap<String, ProviderConfigInput>

Registered provider config inputs keyed by provider id.

Source

pub fn stream_provider_ids(&self) -> HashSet<String>

Provider ids that expose a host-side streamSimple handler.

Source

pub fn provider_extension_paths(&self) -> HashMap<String, String>

Optional extension path per provider (diagnostics).

Source

pub fn registered_flag_types(&self) -> BTreeMap<String, ExtensionFlagType>

Registered extension flags as name → type, for CLI validation.

Source

pub fn providers(&self) -> HashMap<String, ExtensionProvider>

Registered extension provider adapters keyed by provider id, freshly bound to the live host client (callers register them with the model runtime). Rebuilt per call since ExtensionProvider is not Clone.

Includes every host-registered provider. Custom-stream selection still requires streamSimple: true at registration time (Self::register_providers_on); baseURL-only providers stay native.

Source

pub fn register_providers_on( &self, runtime: &ModelRuntime, ) -> Vec<(String, Result<(), ModelRuntimeError>)>

Register this host’s provider configs + stream adapters on runtime.

Each provider failure becomes a diagnostic string; siblings continue. Stream handlers are registered only when streamSimple was true.

Source

pub fn unregister_providers_from(&self, runtime: &ModelRuntime)

Unregister every provider currently owned by this runner from runtime.

Source

pub fn registry(&self) -> Registry

Snapshot of the pi-ext Registry (tools/commands/shortcuts/flags/ renderers/providers with first-wins dedup applied).

Source

pub fn raw_shortcuts(&self) -> Vec<ShortcutRegistration>

Ordered, undeduplicated host shortcut registrations.

Product code applies last-wins filtering after combining extension and native shortcuts.

Source

pub fn reload_generation(&self) -> u64

Current reload generation (starts at 1, bumps on each reload).

Source

pub fn is_running(&self) -> bool

Whether the host transport is still believed alive.

Source

pub async fn apply_flag_values( &self, values: &BTreeMap<String, FlagValueWire>, ) -> Result<(), HostClientError>

Synchronize a complete validated flag overlay with the host.

The local flag snapshot is updated only after the host acknowledges the request.

§Errors

Returns HostClientError::Payload when the request or response payload cannot be (de)serialized, or when the host rejects the overlay (ok == false). Propagates the transport-level error from hook_request otherwise: HostClientError::NotRunning when the host is down, and HostClientError::Timeout, HostClientError::Closed, or HostClientError::Remote on transport failure.

Source

pub async fn execute_shortcut( &self, key: impl Into<String>, ) -> Result<ShortcutExecuteResponse, HostClientError>

Dispatch one effective extension shortcut.

§Errors

Returns HostClientError::Payload when the request or response payload cannot be (de)serialized. Propagates the transport-level error from hook_request otherwise: HostClientError::NotRunning when the host is down, and HostClientError::Timeout, HostClientError::Closed, or HostClientError::Remote on transport failure.

Source

pub async fn send_ui_event( &self, request: UiEventRequest, ) -> Result<UiEventResponse, HostClientError>

Deliver one event to a keyed UI slot generation.

§Errors

Returns HostClientError::Payload when the request or response payload cannot be (de)serialized. Propagates the transport-level error from hook_request otherwise: HostClientError::NotRunning when the host is down, and HostClientError::Timeout, HostClientError::Closed, or HostClientError::Remote on transport failure.

Source

pub fn subscribe_slot(&self, key: &str) -> Receiver<Option<SanitizedSlot>>

Subscribe to a keyed UI slot lifecycle. The receiver yields the latest sanitized slot, or None when the slot is disposed or invalidated by a reload. New keys start disposed (None) until the host pushes content.

Source

pub fn slot_keys(&self) -> Vec<String>

Currently live slot keys.

Source

pub fn current_slots(&self) -> Vec<SanitizedSlot>

Snapshot all currently live sanitized slots.

This lets a mode attach after session_start without losing widgets already published before its broadcast subscription existed.

Source

pub fn subscribe_tool_updates(&self) -> Receiver<ToolUpdate>

Subscribe to unsolicited partial tool updates from extension tools.

Source

pub fn subscribe_provider_events(&self) -> Receiver<ProviderEvent>

Subscribe to unsolicited custom-provider stream events.

Source

pub fn subscribe_errors(&self) -> Receiver<ExtensionErrorEvent>

Subscribe to non-retryable extension errors (host crashes, timeouts, remote error frames, handler-reported failures).

Source

pub fn has_terminal_input_handlers(&self) -> bool

Whether the loaded host has an active ui.onTerminalInput handler.

Source

pub async fn terminal_input( &self, data: &str, ) -> Result<TerminalInputResult, HostClientError>

Offer canonical terminal input to the host’s sequential 4 ms actor.

§Errors

Returns HostClientError when the host transport is down, the 4 ms deadline elapses, or the response payload cannot be decoded.

Source

pub fn subscribe_ui(&self) -> Receiver<ExtensionUiEvent>

Subscribe to host notifications and sanitized slot lifecycle.

Source

pub fn take_ui_requests(&self) -> Option<Receiver<HostUiRequest>>

Claim the sole lossless receiver for correlated host dialog requests.

A product mode calls this exactly once when it binds. Subsequent callers receive None, preventing two modes from racing responses.

Source

pub async fn respond_ui( &self, response: HostUiResponse, ) -> Result<(), HostClientError>

Answer a correlated host-initiated dialog request.

§Errors

Returns a transport error if the host has already exited.

Source

pub async fn render_extension_tool_html( &self, phase: ToolRenderPhase, tool_name: &str, payload: &Value, ) -> Option<String>

Render an extension tool call or result as sanitized HTML for session export. Returns Ok(None) when no renderer is registered for tool_name. The host runs the registered renderCall / renderResult and returns an HTML fragment; Rust strips <script> / <style> blocks and escapes the remaining markup so plugin bytes never inject active content into an exported document.

§Errors

Returns ExtensionRunner error semantics: transport failures are reported as a non-retryable extension_error and the call resolves to Ok(None) (isolation).

Source

pub async fn reload(&self) -> u64

Bump the reload generation, dispose every active slot, and reap the current host exactly once (reap-only; the session layer owns the typed session_shutdown{reload} emission before calling this). The caller re-creates the runner (via HostExtensionRunner::start / connect) for the clean registration pass. Returns the new generation.

Source

pub async fn restart_and_rewire( &self, runtime: &ModelRuntime, preserved_flags: HashMap<String, Value>, ) -> Result<Arc<Self>, HostStartError>

Transactional restart: prepare a fresh host and restore its flags while the old host and its runtime registrations remain live. Once the replacement is ready, replace the runtime registrations and return the new runner without reaping the old transport: the caller finishes the session-side cutover (trait runner, host handle, tool registry) while the old host is still live, then calls Self::retire_after_cutover on the old runner.

§Errors

Returns HostStartError when the replacement host fails to start or synchronize flags. The old runner and its runtime registrations remain usable on either failure.

Source

pub async fn retire_after_cutover(&self)

Retire this runner after a successful reload cutover.

Closes the traffic gate (new hook/tool calls on this retired runner fail cleanly without touching the transport), lets in-flight old-host traffic finish against the still-live client (bounded by the hook deadline plus grace so a hung call cannot pin two hosts forever), then bumps the reload generation, disposes slots, and reaps the transport exactly once via Self::reload.

Source

pub async fn start_with_cwd( extension_paths: Vec<String>, load_cwd: impl Into<String>, ) -> Result<Arc<Self>, HostStartError>

Resolve + spawn with an explicit load cwd.

§Errors

See HostExtensionRunner::start_with_cwd_and_trust.

Source

pub async fn start_with_cwd_and_trust( extension_paths: Vec<String>, load_cwd: impl Into<String>, project_trusted: bool, ) -> Result<Arc<Self>, HostStartError>

Resolve + spawn with an explicit load cwd and project-trust value.

Resolution follows product policy: env/sibling precedence first, then acquire of the pinned host asset when nothing is configured and extension_paths is non-empty (no download ever happens without discovered extensions).

§Errors

See HostExtensionRunner::start; additionally HostStartError::Acquire when acquisition fails.

Source

pub async fn spawn_with_cwd_and_trust( spec: &HostSpec, extension_paths: Vec<String>, load_cwd: impl Into<String>, project_trusted: bool, ) -> Result<Arc<Self>, HostStartError>

Spawn from an explicit HostSpec with a load cwd and project-trust value (the injection point for product-acquired hosts).

§Errors

See HostExtensionRunner::start.

Source

pub fn invalidate(&self)

Mark this runner stale (session replacement). Subsequent hooks and handler-presence queries short-circuit to no-ops; active slots are disposed so the host disposes the previous component generation.

Source

pub async fn shutdown_once(&self)

Graceful shutdown of the host client, exactly once. Repeated calls are no-ops. Slot subscriptions are disposed and the runner is marked disabled.

Trait Implementations§

Source§

impl ExtensionRunner for HostExtensionRunner

Source§

fn has_handlers(&self, event: &str) -> bool

Returns true when at least one handler is registered for event.
Source§

fn emit( &self, event: AgentSessionEvent, ) -> BoxFuture<'_, Result<Option<CancelResult>, ExtensionRunnerError>>

Emit a generic session lifecycle event (agent_start, turn_, tool_, etc.).
Source§

fn emit_message_update_delta<'a>( &'a self, event: &'a AssistantMessageEvent, ) -> BoxFuture<'a, Result<Option<CancelResult>, ExtensionRunnerError>>

Emit a compact streaming assistant delta. Read more
Source§

fn emit_message_end( &self, message: AgentMessage, ) -> BoxFuture<'_, Result<Option<AgentMessage>, ExtensionRunnerError>>

Emit message_end and optionally return a replacement message.
Source§

fn emit_tool_call( &self, tool_name: &str, tool_call_id: &str, input: Map<String, Value>, ) -> BoxFuture<'_, Result<Option<BeforeToolCallResult>, ExtensionRunnerError>>

Emit tool_call (before execution). Returns an optional block result.
Source§

fn emit_tool_result( &self, tool_name: &str, tool_call_id: &str, input: Map<String, Value>, content: Vec<ToolResultContent>, details: Value, is_error: bool, ) -> BoxFuture<'_, Result<Option<AfterToolCallResult>, ExtensionRunnerError>>

Emit tool_result (after execution). Returns an optional override.
Source§

fn emit_input( &self, text: &str, images: Option<Value>, source: &str, streaming_behavior: Option<&str>, ) -> BoxFuture<'_, Result<InputTransformResult, ExtensionRunnerError>>

Emit the input transform event.
Source§

fn emit_before_agent_start( &self, prompt: &str, images: Option<Value>, ) -> BoxFuture<'_, Result<Option<BeforeAgentStartResult>, ExtensionRunnerError>>

Emit before_agent_start and return optional message/system prompt injection.
Source§

fn emit_resources_discover( &self, cwd: &str, reason: &str, ) -> BoxFuture<'_, Result<ResourceExtensionPaths, ExtensionRunnerError>>

Discover additional resource paths from extensions.
Source§

fn get_registered_commands(&self) -> Vec<String>

Registered slash-command names (extension source).
Source§

fn execute_command( &self, name: &str, args: &str, ) -> BoxFuture<'_, Result<bool, ExtensionRunnerError>>

Execute an extension slash command by name. Read more
Source§

fn get_all_registered_tools(&self) -> HashMap<String, Arc<dyn AgentTool>>

Registered extension tools by name.
Source§

fn get_flag_values(&self) -> HashMap<String, Value>

Flag values provided by extensions.
Source§

fn invalidate(&self)

Mark the runner invalid after session replacement.
Source§

fn emit_error(&self, message: String)

Report an extension error to the host error listener.
Source§

fn has_command(&self, name: &str) -> bool

Whether a slash command named name is registered.

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

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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