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
impl HostExtensionRunner
Sourcepub async fn start(
extension_paths: Vec<String>,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub async fn spawn_from(
spec: &HostSpec,
extension_paths: Vec<String>,
) -> Result<Arc<Self>, HostStartError>
pub async fn spawn_from( spec: &HostSpec, extension_paths: Vec<String>, ) -> Result<Arc<Self>, HostStartError>
Sourcepub async fn connect(
client: Arc<HostClient>,
extension_paths: Vec<String>,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub async fn connect_with_timeout(
client: Arc<HostClient>,
extension_paths: Vec<String>,
hook_timeout: Duration,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub async fn connect_with_cwd(
client: Arc<HostClient>,
extension_paths: Vec<String>,
load_cwd: impl Into<String>,
hook_timeout: Duration,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub 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>
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.
Sourcepub fn client(&self) -> &Arc<HostClient> ⓘ
pub fn client(&self) -> &Arc<HostClient> ⓘ
Borrowed host client (for provider registration by the model runtime).
Sourcepub fn extension_paths(&self) -> Vec<String>
pub fn extension_paths(&self) -> Vec<String>
Extension paths used for the current host load.
Sourcepub fn load_errors(&self) -> Vec<(String, String)>
pub fn load_errors(&self) -> Vec<(String, String)>
Host-reported per-path load errors from the latest snapshot.
Sourcepub fn provider_configs(&self) -> HashMap<String, ProviderConfigInput>
pub fn provider_configs(&self) -> HashMap<String, ProviderConfigInput>
Registered provider config inputs keyed by provider id.
Sourcepub fn stream_provider_ids(&self) -> HashSet<String>
pub fn stream_provider_ids(&self) -> HashSet<String>
Provider ids that expose a host-side streamSimple handler.
Sourcepub fn provider_extension_paths(&self) -> HashMap<String, String>
pub fn provider_extension_paths(&self) -> HashMap<String, String>
Optional extension path per provider (diagnostics).
Sourcepub fn registered_flag_types(&self) -> BTreeMap<String, ExtensionFlagType>
pub fn registered_flag_types(&self) -> BTreeMap<String, ExtensionFlagType>
Registered extension flags as name → type, for CLI validation.
Sourcepub fn providers(&self) -> HashMap<String, ExtensionProvider>
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.
Sourcepub fn register_providers_on(
&self,
runtime: &ModelRuntime,
) -> Vec<(String, Result<(), ModelRuntimeError>)>
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.
Sourcepub fn unregister_providers_from(&self, runtime: &ModelRuntime)
pub fn unregister_providers_from(&self, runtime: &ModelRuntime)
Unregister every provider currently owned by this runner from runtime.
Sourcepub fn registry(&self) -> Registry
pub fn registry(&self) -> Registry
Snapshot of the pi-ext Registry (tools/commands/shortcuts/flags/
renderers/providers with first-wins dedup applied).
Sourcepub fn raw_shortcuts(&self) -> Vec<ShortcutRegistration>
pub fn raw_shortcuts(&self) -> Vec<ShortcutRegistration>
Ordered, undeduplicated host shortcut registrations.
Product code applies last-wins filtering after combining extension and native shortcuts.
Sourcepub fn reload_generation(&self) -> u64
pub fn reload_generation(&self) -> u64
Current reload generation (starts at 1, bumps on each reload).
Sourcepub fn is_running(&self) -> bool
pub fn is_running(&self) -> bool
Whether the host transport is still believed alive.
Sourcepub async fn apply_flag_values(
&self,
values: &BTreeMap<String, FlagValueWire>,
) -> Result<(), HostClientError>
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.
Sourcepub async fn execute_shortcut(
&self,
key: impl Into<String>,
) -> Result<ShortcutExecuteResponse, HostClientError>
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.
Sourcepub async fn send_ui_event(
&self,
request: UiEventRequest,
) -> Result<UiEventResponse, HostClientError>
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.
Sourcepub fn subscribe_slot(&self, key: &str) -> Receiver<Option<SanitizedSlot>>
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.
Sourcepub fn current_slots(&self) -> Vec<SanitizedSlot>
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.
Sourcepub fn subscribe_tool_updates(&self) -> Receiver<ToolUpdate>
pub fn subscribe_tool_updates(&self) -> Receiver<ToolUpdate>
Subscribe to unsolicited partial tool updates from extension tools.
Sourcepub fn subscribe_provider_events(&self) -> Receiver<ProviderEvent>
pub fn subscribe_provider_events(&self) -> Receiver<ProviderEvent>
Subscribe to unsolicited custom-provider stream events.
Sourcepub fn subscribe_errors(&self) -> Receiver<ExtensionErrorEvent>
pub fn subscribe_errors(&self) -> Receiver<ExtensionErrorEvent>
Subscribe to non-retryable extension errors (host crashes, timeouts, remote error frames, handler-reported failures).
Sourcepub fn has_terminal_input_handlers(&self) -> bool
pub fn has_terminal_input_handlers(&self) -> bool
Whether the loaded host has an active ui.onTerminalInput handler.
Sourcepub async fn terminal_input(
&self,
data: &str,
) -> Result<TerminalInputResult, HostClientError>
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.
Sourcepub fn subscribe_ui(&self) -> Receiver<ExtensionUiEvent>
pub fn subscribe_ui(&self) -> Receiver<ExtensionUiEvent>
Subscribe to host notifications and sanitized slot lifecycle.
Sourcepub fn take_ui_requests(&self) -> Option<Receiver<HostUiRequest>>
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.
Sourcepub async fn respond_ui(
&self,
response: HostUiResponse,
) -> Result<(), HostClientError>
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.
Sourcepub async fn render_extension_tool_html(
&self,
phase: ToolRenderPhase,
tool_name: &str,
payload: &Value,
) -> Option<String>
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).
Sourcepub async fn reload(&self) -> u64
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.
Sourcepub async fn restart_and_rewire(
&self,
runtime: &ModelRuntime,
preserved_flags: HashMap<String, Value>,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub async fn retire_after_cutover(&self)
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.
Sourcepub async fn start_with_cwd(
extension_paths: Vec<String>,
load_cwd: impl Into<String>,
) -> Result<Arc<Self>, HostStartError>
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
Sourcepub async fn start_with_cwd_and_trust(
extension_paths: Vec<String>,
load_cwd: impl Into<String>,
project_trusted: bool,
) -> Result<Arc<Self>, HostStartError>
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.
Sourcepub 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>
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>
Sourcepub fn invalidate(&self)
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.
Sourcepub async fn shutdown_once(&self)
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
impl ExtensionRunner for HostExtensionRunner
Source§fn has_handlers(&self, event: &str) -> bool
fn has_handlers(&self, event: &str) -> bool
event.Source§fn emit(
&self,
event: AgentSessionEvent,
) -> BoxFuture<'_, Result<Option<CancelResult>, ExtensionRunnerError>>
fn emit( &self, event: AgentSessionEvent, ) -> BoxFuture<'_, Result<Option<CancelResult>, ExtensionRunnerError>>
agent_start, turn_, tool_, etc.).Source§fn emit_message_update_delta<'a>(
&'a self,
event: &'a AssistantMessageEvent,
) -> BoxFuture<'a, Result<Option<CancelResult>, ExtensionRunnerError>>
fn emit_message_update_delta<'a>( &'a self, event: &'a AssistantMessageEvent, ) -> BoxFuture<'a, Result<Option<CancelResult>, ExtensionRunnerError>>
Source§fn emit_message_end(
&self,
message: AgentMessage,
) -> BoxFuture<'_, Result<Option<AgentMessage>, ExtensionRunnerError>>
fn emit_message_end( &self, message: AgentMessage, ) -> BoxFuture<'_, Result<Option<AgentMessage>, ExtensionRunnerError>>
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>>
fn emit_tool_call( &self, tool_name: &str, tool_call_id: &str, input: Map<String, Value>, ) -> BoxFuture<'_, Result<Option<BeforeToolCallResult>, ExtensionRunnerError>>
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>>
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>>
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>>
fn emit_input( &self, text: &str, images: Option<Value>, source: &str, streaming_behavior: Option<&str>, ) -> BoxFuture<'_, Result<InputTransformResult, ExtensionRunnerError>>
input transform event.Source§fn emit_before_agent_start(
&self,
prompt: &str,
images: Option<Value>,
) -> BoxFuture<'_, Result<Option<BeforeAgentStartResult>, ExtensionRunnerError>>
fn emit_before_agent_start( &self, prompt: &str, images: Option<Value>, ) -> BoxFuture<'_, Result<Option<BeforeAgentStartResult>, ExtensionRunnerError>>
before_agent_start and return optional message/system prompt injection.Source§fn emit_resources_discover(
&self,
cwd: &str,
reason: &str,
) -> BoxFuture<'_, Result<ResourceExtensionPaths, ExtensionRunnerError>>
fn emit_resources_discover( &self, cwd: &str, reason: &str, ) -> BoxFuture<'_, Result<ResourceExtensionPaths, ExtensionRunnerError>>
Source§fn get_registered_commands(&self) -> Vec<String>
fn get_registered_commands(&self) -> Vec<String>
Source§fn execute_command(
&self,
name: &str,
args: &str,
) -> BoxFuture<'_, Result<bool, ExtensionRunnerError>>
fn execute_command( &self, name: &str, args: &str, ) -> BoxFuture<'_, Result<bool, ExtensionRunnerError>>
Source§fn get_all_registered_tools(&self) -> HashMap<String, Arc<dyn AgentTool>>
fn get_all_registered_tools(&self) -> HashMap<String, Arc<dyn AgentTool>>
Source§fn invalidate(&self)
fn invalidate(&self)
Source§fn emit_error(&self, message: String)
fn emit_error(&self, message: String)
Source§fn has_command(&self, name: &str) -> bool
fn has_command(&self, name: &str) -> bool
name is registered.Auto Trait Implementations§
impl !RefUnwindSafe for HostExtensionRunner
impl !UnwindSafe for HostExtensionRunner
impl Freeze for HostExtensionRunner
impl Send for HostExtensionRunner
impl Sync for HostExtensionRunner
impl Unpin for HostExtensionRunner
impl UnsafeUnpin for HostExtensionRunner
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> 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